Browse code

docker-ci 0.40. Migrate docker-ci to Digital Ocean.

Daniel Mizyrycki authored on 2013/10/30 14:14:28
Showing 2 changed files
... ...
@@ -1,14 +1,16 @@
1 1
 # VERSION:        0.22
2 2
 # DOCKER-VERSION  0.6.3
3 3
 # AUTHOR:         Daniel Mizyrycki <daniel@dotcloud.com>
4
-# DESCRIPTION:    Deploy docker-ci on Amazon EC2
4
+# DESCRIPTION:    Deploy docker-ci on Digital Ocean
5 5
 # COMMENTS:
6 6
 #     CONFIG_JSON is an environment variable json string loaded as:
7 7
 #
8 8
 # export CONFIG_JSON='
9
-#     { "AWS_TAG":             "EC2_instance_name",
10
-#       "AWS_ACCESS_KEY":      "EC2_access_key",
11
-#       "AWS_SECRET_KEY":      "EC2_secret_key",
9
+#     { "DROPLET_NAME":        "docker-ci",
10
+#       "DO_CLIENT_ID":        "Digital_Ocean_client_id",
11
+#       "DO_API_KEY":          "Digital_Ocean_api_key",
12
+#       "DOCKER_KEY_ID":       "Digital_Ocean_ssh_key_id",
13
+#       "DOCKER_CI_KEY_PATH":  "docker-ci_private_key_path",
12 14
 #       "DOCKER_CI_PUB":       "$(cat docker-ci_ssh_public_key.pub)",
13 15
 #       "DOCKER_CI_KEY":       "$(cat docker-ci_ssh_private_key.key)",
14 16
 #       "BUILDBOT_PWD":        "Buildbot_server_password",
... ...
@@ -37,7 +39,7 @@ run echo 'deb http://archive.ubuntu.com/ubuntu precise main universe' \
37 37
     > /etc/apt/sources.list
38 38
 run apt-get update; apt-get install -y git python2.7 python-dev libevent-dev \
39 39
     python-pip ssh rsync less vim
40
-run pip install boto fabric
40
+run pip install requests fabric
41 41
 
42 42
 # Add deployment code and set default container command
43 43
 add . /docker-ci
... ...
@@ -1,11 +1,11 @@
1 1
 #!/usr/bin/env python
2 2
 
3
-import os, sys, re, json, base64
4
-from boto.ec2.connection import EC2Connection
3
+import os, sys, re, json, requests, base64
5 4
 from subprocess import call
6 5
 from fabric import api
7 6
 from fabric.api import cd, run, put, sudo
8 7
 from os import environ as env
8
+from datetime import datetime
9 9
 from time import sleep
10 10
 
11 11
 # Remove SSH private key as it needs more processing
... ...
@@ -20,42 +20,41 @@ for key in CONFIG:
20 20
 env['DOCKER_CI_KEY'] = re.sub('^.+"DOCKER_CI_KEY".+?"(.+?)".+','\\1',
21 21
     env['CONFIG_JSON'],flags=re.DOTALL)
22 22
 
23
-
24
-AWS_TAG = env.get('AWS_TAG','docker-ci')
25
-AWS_KEY_NAME = 'dotcloud-dev'       # Same as CONFIG_JSON['DOCKER_CI_PUB']
26
-AWS_AMI = 'ami-d582d6bc'            # Ubuntu 13.04
27
-AWS_REGION = 'us-east-1'
28
-AWS_TYPE = 'm1.small'
29
-AWS_SEC_GROUPS = 'gateway'
30
-AWS_IMAGE_USER = 'ubuntu'
23
+DROPLET_NAME = env.get('DROPLET_NAME','docker-ci')
24
+TIMEOUT = 120            # Seconds before timeout droplet creation
25
+IMAGE_ID = 1004145       # Docker on Ubuntu 13.04
26
+REGION_ID = 4            # New York 2
27
+SIZE_ID = 62             # memory 2GB
28
+DO_IMAGE_USER = 'root'   # Image user on Digital Ocean
29
+API_URL = 'https://api.digitalocean.com/'
31 30
 DOCKER_PATH = '/go/src/github.com/dotcloud/docker'
32 31
 DOCKER_CI_PATH = '/docker-ci'
33 32
 CFG_PATH = '{}/buildbot'.format(DOCKER_CI_PATH)
34 33
 
35 34
 
36
-class AWS_EC2:
37
-    '''Amazon EC2'''
38
-    def __init__(self, access_key, secret_key):
35
+class digital_ocean():
36
+
37
+    def __init__(self, key, client):
39 38
         '''Set default API parameters'''
40
-        self.handler = EC2Connection(access_key, secret_key)
41
-    def create_instance(self, tag, instance_type):
42
-        reservation = self.handler.run_instances(**instance_type)
43
-        instance = reservation.instances[0]
44
-        sleep(10)
45
-        while instance.state != 'running':
46
-            sleep(5)
47
-            instance.update()
48
-            print "Instance state: %s" % (instance.state)
49
-        instance.add_tag("Name",tag)
50
-        print "instance %s done!" % (instance.id)
51
-        return instance.ip_address
52
-    def get_instances(self):
53
-        return self.handler.get_all_instances()
54
-    def get_tags(self):
55
-        return dict([(i.instances[0].id, i.instances[0].tags['Name'])
56
-            for i in self.handler.get_all_instances() if i.instances[0].tags])
57
-    def del_instance(self, instance_id):
58
-        self.handler.terminate_instances(instance_ids=[instance_id])
39
+        self.key = key
40
+        self.client = client
41
+        self.api_url = API_URL
42
+
43
+    def api(self, cmd_path, api_arg={}):
44
+        '''Make api call'''
45
+        api_arg.update({'api_key':self.key, 'client_id':self.client})
46
+        resp = requests.get(self.api_url + cmd_path, params=api_arg).text
47
+        resp = json.loads(resp)
48
+        if resp['status'] != 'OK':
49
+            raise Exception(resp['error_message'])
50
+        return resp
51
+
52
+    def droplet_data(self, name):
53
+        '''Get droplet data'''
54
+        data = self.api('droplets')
55
+        data = [droplet for droplet in data['droplets']
56
+            if droplet['name'] == name]
57
+        return data[0] if data else {}
59 58
 
60 59
 
61 60
 def json_fmt(data):
... ...
@@ -63,20 +62,36 @@ def json_fmt(data):
63 63
     return json.dumps(data, sort_keys = True, indent = 2)
64 64
 
65 65
 
66
-# Create EC2 API handler
67
-ec2 = AWS_EC2(env['AWS_ACCESS_KEY'], env['AWS_SECRET_KEY'])
66
+do = digital_ocean(env['DO_API_KEY'], env['DO_CLIENT_ID'])
68 67
 
69
-# Stop processing if AWS_TAG exists on EC2
70
-if AWS_TAG in ec2.get_tags().values():
71
-    print ('Instance: {} already deployed. Not further processing.'
72
-        .format(AWS_TAG))
68
+# Get DROPLET_NAME data
69
+data = do.droplet_data(DROPLET_NAME)
70
+
71
+# Stop processing if DROPLET_NAME exists on Digital Ocean
72
+if data:
73
+    print ('Droplet: {} already deployed. Not further processing.'
74
+        .format(DROPLET_NAME))
73 75
     exit(1)
74 76
 
75
-ip = ec2.create_instance(AWS_TAG, {'image_id':AWS_AMI, 'instance_type':AWS_TYPE,
76
-    'security_groups':[AWS_SEC_GROUPS], 'key_name':AWS_KEY_NAME})
77
+# Create droplet
78
+do.api('droplets/new', {'name':DROPLET_NAME, 'region_id':REGION_ID,
79
+    'image_id':IMAGE_ID, 'size_id':SIZE_ID,
80
+    'ssh_key_ids':[env['DOCKER_KEY_ID']]})
81
+
82
+# Wait for droplet to be created.
83
+start_time = datetime.now()
84
+while (data.get('status','') != 'active' and (
85
+ datetime.now()-start_time).seconds < TIMEOUT):
86
+    data = do.droplet_data(DROPLET_NAME)
87
+    print data['status']
88
+    sleep(3)
77 89
 
78
-# Wait 30 seconds for the machine to boot
79
-sleep(30)
90
+# Wait for the machine to boot
91
+sleep(15)
92
+
93
+# Get droplet IP
94
+ip = str(data['ip_address'])
95
+print 'droplet: {}    ip: {}'.format(DROPLET_NAME, ip)
80 96
 
81 97
 # Create docker-ci ssh private key so docker-ci docker container can communicate
82 98
 # with its EC2 instance
... ...
@@ -86,7 +101,7 @@ os.chmod('/root/.ssh/id_rsa',0600)
86 86
 open('/root/.ssh/config','w').write('StrictHostKeyChecking no\n')
87 87
 
88 88
 api.env.host_string = ip
89
-api.env.user = AWS_IMAGE_USER
89
+api.env.user = DO_IMAGE_USER
90 90
 api.env.key_filename = '/root/.ssh/id_rsa'
91 91
 
92 92
 # Correct timezone
... ...
@@ -106,13 +121,11 @@ open(DOCKER_CI_PATH + '/nightlyrelease/release_credentials.json', 'w').write(
106 106
 
107 107
 # Transfer docker
108 108
 sudo('mkdir -p ' + DOCKER_CI_PATH)
109
-sudo('chown {}.{} {}'.format(AWS_IMAGE_USER, AWS_IMAGE_USER, DOCKER_CI_PATH))
110
-call('/usr/bin/rsync -aH {} {}@{}:{}'.format(DOCKER_CI_PATH, AWS_IMAGE_USER, ip,
109
+sudo('chown {}.{} {}'.format(DO_IMAGE_USER, DO_IMAGE_USER, DOCKER_CI_PATH))
110
+call('/usr/bin/rsync -aH {} {}@{}:{}'.format(DOCKER_CI_PATH, DO_IMAGE_USER, ip,
111 111
     os.path.dirname(DOCKER_CI_PATH)), shell=True)
112 112
 
113 113
 # Install Docker and Buildbot dependencies
114
-sudo('addgroup docker')
115
-sudo('usermod -a -G docker ubuntu')
116 114
 sudo('mkdir /mnt/docker; ln -s /mnt/docker /var/lib/docker')
117 115
 sudo('wget -q -O - https://get.docker.io/gpg | apt-key add -')
118 116
 sudo('echo deb https://get.docker.io/ubuntu docker main >'
... ...
@@ -122,7 +135,7 @@ sudo('echo -e "deb http://archive.ubuntu.com/ubuntu raring main universe\n'
122 122
     ' > /etc/apt/sources.list; apt-get update')
123 123
 sudo('DEBIAN_FRONTEND=noninteractive apt-get install -q -y wget python-dev'
124 124
     ' python-pip supervisor git mercurial linux-image-extra-$(uname -r)'
125
-    ' aufs-tools make libfontconfig libevent-dev')
125
+    ' aufs-tools make libfontconfig libevent-dev libsqlite3-dev libssl-dev')
126 126
 sudo('wget -O - https://go.googlecode.com/files/go1.1.2.linux-amd64.tar.gz | '
127 127
     'tar -v -C /usr/local -xz; ln -s /usr/local/go/bin/go /usr/bin/go')
128 128
 sudo('GOPATH=/go go get -d github.com/dotcloud/docker')
... ...
@@ -137,9 +150,6 @@ sudo('curl -s https://phantomjs.googlecode.com/files/'
137 137
 # Preventively reboot docker-ci daily
138 138
 sudo('ln -s /sbin/reboot /etc/cron.daily')
139 139
 
140
-# Preventively reboot docker-ci daily
141
-sudo('ln -s /sbin/reboot /etc/cron.daily')
142
-
143 140
 # Build docker-ci containers
144 141
 sudo('cd {}; docker build -t docker .'.format(DOCKER_PATH))
145 142
 sudo('cd {}; docker build -t docker-ci .'.format(DOCKER_CI_PATH))