| #!/usr/bin/env python |
| |
| import os, sys, re, json, requests, base64 |
| from subprocess import call |
| from fabric import api |
| from fabric.api import cd, run, put, sudo |
| from os import environ as env |
| from datetime import datetime |
| from time import sleep |
| |
| # Remove SSH private key as it needs more processing |
| CONFIG = json.loads(re.sub(r'("DOCKER_CI_KEY".+?"(.+?)",)','', |
| env['CONFIG_JSON'], flags=re.DOTALL)) |
| |
| # Populate environment variables |
| for key in CONFIG: |
| env[key] = CONFIG[key] |
| |
| # Load SSH private key |
| env['DOCKER_CI_KEY'] = re.sub('^.+"DOCKER_CI_KEY".+?"(.+?)".+','\\1', |
| env['CONFIG_JSON'],flags=re.DOTALL) |
| |
| DROPLET_NAME = env.get('DROPLET_NAME','docker-ci') |
| TIMEOUT = 120 # Seconds before timeout droplet creation |
| IMAGE_ID = 1004145 # Docker on Ubuntu 13.04 |
| REGION_ID = 4 # New York 2 |
| SIZE_ID = 62 # memory 2GB |
| DO_IMAGE_USER = 'root' # Image user on Digital Ocean |
| API_URL = 'https://api.digitalocean.com/' |
| DOCKER_PATH = '/go/src/github.com/dotcloud/docker' |
| DOCKER_CI_PATH = '/docker-ci' |
| CFG_PATH = '{}/buildbot'.format(DOCKER_CI_PATH) |
| |
| |
| class DigitalOcean(): |
| |
| def __init__(self, key, client): |
| '''Set default API parameters''' |
| self.key = key |
| self.client = client |
| self.api_url = API_URL |
| |
| def api(self, cmd_path, api_arg={}): |
| '''Make api call''' |
| api_arg.update({'api_key':self.key, 'client_id':self.client}) |
| resp = requests.get(self.api_url + cmd_path, params=api_arg).text |
| resp = json.loads(resp) |
| if resp['status'] != 'OK': |
| raise Exception(resp['error_message']) |
| return resp |
| |
| def droplet_data(self, name): |
| '''Get droplet data''' |
| data = self.api('droplets') |
| data = [droplet for droplet in data['droplets'] |
| if droplet['name'] == name] |
| return data[0] if data else {} |
| |
| |
| def json_fmt(data): |
| '''Format json output''' |
| return json.dumps(data, sort_keys = True, indent = 2) |
| |
| |
| do = DigitalOcean(env['DO_API_KEY'], env['DO_CLIENT_ID']) |
| |
| # Get DROPLET_NAME data |
| data = do.droplet_data(DROPLET_NAME) |
| |
| # Stop processing if DROPLET_NAME exists on Digital Ocean |
| if data: |
| print ('Droplet: {} already deployed. Not further processing.' |
| .format(DROPLET_NAME)) |
| exit(1) |
| |
| # Create droplet |
| do.api('droplets/new', {'name':DROPLET_NAME, 'region_id':REGION_ID, |
| 'image_id':IMAGE_ID, 'size_id':SIZE_ID, |
| 'ssh_key_ids':[env['DOCKER_KEY_ID']]}) |
| |
| # Wait for droplet to be created. |
| start_time = datetime.now() |
| while (data.get('status','') != 'active' and ( |
| datetime.now()-start_time).seconds < TIMEOUT): |
| data = do.droplet_data(DROPLET_NAME) |
| print data['status'] |
| sleep(3) |
| |
| # Wait for the machine to boot |
| sleep(15) |
| |
| # Get droplet IP |
| ip = str(data['ip_address']) |
| print 'droplet: {} ip: {}'.format(DROPLET_NAME, ip) |
| |
| # Create docker-ci ssh private key so docker-ci docker container can communicate |
| # with its EC2 instance |
| os.makedirs('/root/.ssh') |
| open('/root/.ssh/id_rsa','w').write(env['DOCKER_CI_KEY']) |
| os.chmod('/root/.ssh/id_rsa',0600) |
| open('/root/.ssh/config','w').write('StrictHostKeyChecking no\n') |
| |
| api.env.host_string = ip |
| api.env.user = DO_IMAGE_USER |
| api.env.key_filename = '/root/.ssh/id_rsa' |
| |
| # Correct timezone |
| sudo('echo "America/Los_Angeles" >/etc/timezone') |
| sudo('dpkg-reconfigure --frontend noninteractive tzdata') |
| |
| # Load public docker-ci key |
| sudo("echo '{}' >> /root/.ssh/authorized_keys".format(env['DOCKER_CI_PUB'])) |
| |
| # Create docker nightly release credentials file |
| credentials = { |
| 'AWS_ACCESS_KEY': env['PKG_ACCESS_KEY'], |
| 'AWS_SECRET_KEY': env['PKG_SECRET_KEY'], |
| 'GPG_PASSPHRASE': env['PKG_GPG_PASSPHRASE']} |
| open(DOCKER_CI_PATH + '/nightlyrelease/release_credentials.json', 'w').write( |
| base64.b64encode(json.dumps(credentials))) |
| |
| # Transfer docker |
| sudo('mkdir -p ' + DOCKER_CI_PATH) |
| sudo('chown {}.{} {}'.format(DO_IMAGE_USER, DO_IMAGE_USER, DOCKER_CI_PATH)) |
| call('/usr/bin/rsync -aH {} {}@{}:{}'.format(DOCKER_CI_PATH, DO_IMAGE_USER, ip, |
| os.path.dirname(DOCKER_CI_PATH)), shell=True) |
| |
| # Install Docker and Buildbot dependencies |
| sudo('mkdir /mnt/docker; ln -s /mnt/docker /var/lib/docker') |
| sudo('wget -q -O - https://get.docker.io/gpg | apt-key add -') |
| sudo('echo deb https://get.docker.io/ubuntu docker main >' |
| ' /etc/apt/sources.list.d/docker.list') |
| sudo('echo -e "deb http://archive.ubuntu.com/ubuntu raring main universe\n' |
| 'deb http://us.archive.ubuntu.com/ubuntu/ raring-security main universe\n"' |
| ' > /etc/apt/sources.list; apt-get update') |
| sudo('DEBIAN_FRONTEND=noninteractive apt-get install -q -y wget python-dev' |
| ' python-pip supervisor git mercurial linux-image-extra-$(uname -r)' |
| ' aufs-tools make libfontconfig libevent-dev libsqlite3-dev libssl-dev') |
| sudo('wget -O - https://go.googlecode.com/files/go1.1.2.linux-amd64.tar.gz | ' |
| 'tar -v -C /usr/local -xz; ln -s /usr/local/go/bin/go /usr/bin/go') |
| sudo('GOPATH=/go go get -d github.com/dotcloud/docker') |
| sudo('pip install -r {}/requirements.txt'.format(CFG_PATH)) |
| |
| # Install docker and testing dependencies |
| sudo('apt-get install -y -q lxc-docker') |
| sudo('curl -s https://phantomjs.googlecode.com/files/' |
| 'phantomjs-1.9.1-linux-x86_64.tar.bz2 | tar jx -C /usr/bin' |
| ' --strip-components=2 phantomjs-1.9.1-linux-x86_64/bin/phantomjs') |
| |
| # Build docker-ci containers |
| sudo('cd {}; docker build -t docker .'.format(DOCKER_PATH)) |
| sudo('cd {}; docker build -t docker-ci .'.format(DOCKER_CI_PATH)) |
| sudo('cd {}/nightlyrelease; docker build -t dockerbuilder .'.format( |
| DOCKER_CI_PATH)) |
| sudo('cd {}/registry-coverage; docker build -t registry_coverage .'.format( |
| DOCKER_CI_PATH)) |
| |
| # Download docker-ci testing container |
| sudo('docker pull mzdaniel/test_docker') |
| |
| # Setup buildbot |
| sudo('mkdir /data') |
| sudo('{0}/setup.sh root {0} {1} {2} {3} {4} {5} {6} {7} {8} {9} {10}' |
| ' {11} {12}'.format(CFG_PATH, DOCKER_PATH, env['BUILDBOT_PWD'], |
| env['IRC_PWD'], env['IRC_CHANNEL'], env['SMTP_USER'], |
| env['SMTP_PWD'], env['EMAIL_RCP'], env['REGISTRY_USER'], |
| env['REGISTRY_PWD'], env['REGISTRY_BUCKET'], env['REGISTRY_ACCESS_KEY'], |
| env['REGISTRY_SECRET_KEY'])) |
| |
| # Preventively reboot docker-ci daily |
| sudo('ln -s /sbin/reboot /etc/cron.daily') |