-
Notifications
You must be signed in to change notification settings - Fork 16
/
build-ami.py
executable file
·147 lines (126 loc) · 5.03 KB
/
build-ami.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#!/usr/bin/env python
import boto.ec2
import datetime
import os
import time
from fabric.api import cd, env, execute, local, put, run, sudo
from fabric.colors import green as _green, yellow as _yellow
from fabric.context_managers import shell_env
from fabric.contrib.files import exists
from fabric.network import disconnect_all
#
# Edit env defaults to customize AMI.
#
env.ec2_region = "us-west-2"
env.ec2_amis = ['ami-fb68f8cb'] # Ubuntu 12.04 LTS amd64 EBS
env.ec2_keypair = 'MinecraftEC2'
env.ec2_secgroups = ['minecraft']
env.ec2_instancetype = 'm1.small'
env.ec2_userdata = open('cloud-config').read()
def launch_instance():
print(_green("Launching instance of %s..." % env.ec2_amis[0]))
conn = boto.ec2.connect_to_region(env.ec2_region)
reservation = conn.run_instances(
image_id=env.ec2_amis[0],
key_name=env.ec2_keypair,
security_groups=env.ec2_secgroups,
instance_type=env.ec2_instancetype,
user_data=env.ec2_userdata)
instance = reservation.instances[0]
while instance.state == u'pending':
print(_yellow("Instance state: %s" % instance.state))
time.sleep(15)
instance.update()
while not instance.public_dns_name:
print(_yellow("Waiting for Public DNS"))
time.sleep(15)
instance.update()
print(_green("Public DNS: %s" % instance.public_dns_name))
print(_green("Public IP address: %s" % instance.ip_address))
print(_green("Instance state: %s" % instance.state))
print(_green("Instance ID: %s" % instance.id))
print(_green("Waiting 60 seconds for instance to boot..."))
time.sleep(60)
return instance
def set_host_env(instance):
env.user = 'ubuntu'
env.hosts = [instance.public_dns_name]
env.key_filename = os.path.join(os.getenv('HOME'), '.ssh', env.ec2_keypair)
def check_instance_availability():
while not exists('/var/lib/cloud/instance/boot-finished'):
print(_yellow("Waiting for cloud-init to finish running..."))
time.sleep(15)
print(_green("Instance is ready."))
def copy_manifests():
print(_green("Copying puppet manifests..."))
local('git archive --prefix=puppet-minecraft/ --output=puppet-minecraft.tar.gz HEAD')
put('puppet-minecraft.tar.gz', '/home/ubuntu')
with cd('/home/ubuntu'):
run('tar xzf puppet-minecraft.tar.gz')
local('rm puppet-minecraft.tar.gz')
def apply_manifests():
print(_green("Running puppet apply..."))
sudo("puppet apply -v " +
"--modulepath=/home/ubuntu/puppet-minecraft/modules " +
"/home/ubuntu/puppet-minecraft/manifests/base.pp")
def image_name():
"""
Return image name in format 'Minecraft-Server-XXX',
where 'XXX' is the version number, which increments by one
each time the AMI is built.
"""
conn = boto.ec2.connect_to_region(env.ec2_region)
images = conn.get_all_images(owners='self')
prev_versions = [int(i.name.split('-')[-1]) for i in images
if i.name.split('-')[0] == 'Minecraft']
prev_versions.append(0) # Ensure prev_versions isn't empty
version = str(max(prev_versions) + 1).zfill(3)
return "Minecraft-Server-%s" % version
def image_description():
today = datetime.date.today().isoformat()
head_sha1 = local('git rev-parse --verify --short HEAD', capture=True)
return "Built on %s from %s" % (today, head_sha1)
def create_image(instance_id):
conn = boto.ec2.connect_to_region(env.ec2_region)
ami_id = conn.create_image(instance_id, image_name(), image_description())
return ami_id
def check_image_availability(ami_id):
print(_green("Building AMI..."))
conn = boto.ec2.connect_to_region(env.ec2_region)
image = conn.get_image(ami_id)
while image.state == u'pending':
print(_yellow("AMI state: %s" % image.state))
time.sleep(15)
image.update()
if image.state == u'available':
print(_green("AMI is ready."))
print(_green("AMI ID: %s" % image.id))
print(_green("AMI Name: %s" % image.name))
print(_green("AMI Description: %s" % image.description))
else:
print(_yellow("AMI state: %s" % image.state))
def terminate_instance(instance_id):
print(_green("Terminating instance..."))
conn = boto.ec2.connect_to_region(env.ec2_region)
results = conn.terminate_instances(instance_ids=[instance_id])
instance = results[0]
while instance.state == u'shutting-down':
print(_yellow("Instance state: %s" % instance.state))
time.sleep(15)
instance.update()
if instance.state == u'terminated':
print(_green("Instance terminated."))
else:
print(_yellow("Instance state: %s" % instance.state))
def main():
instance = launch_instance()
set_host_env(instance)
execute(check_instance_availability)
execute(copy_manifests)
execute(apply_manifests)
disconnect_all()
ami_id = create_image(instance.id)
check_image_availability(ami_id)
terminate_instance(instance.id)
if __name__ == '__main__':
main()