2013-10-10 20:46:09 -04:00
|
|
|
#!/usr/bin/env python
|
|
|
|
|
2013-10-30 01:14:28 -04:00
|
|
|
import os, sys, re, json, requests, base64
|
2013-10-10 20:46:09 -04:00
|
|
|
from subprocess import call
|
|
|
|
from fabric import api
|
|
|
|
from fabric.api import cd, run, put, sudo
|
|
|
|
from os import environ as env
|
2013-10-30 01:14:28 -04:00
|
|
|
from datetime import datetime
|
2013-10-10 20:46:09 -04:00
|
|
|
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)
|
|
|
|
|
2013-10-30 01:14:28 -04:00
|
|
|
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/'
|
2013-10-10 20:46:09 -04:00
|
|
|
DOCKER_PATH = '/go/src/github.com/dotcloud/docker'
|
|
|
|
DOCKER_CI_PATH = '/docker-ci'
|
|
|
|
CFG_PATH = '{}/buildbot'.format(DOCKER_CI_PATH)
|
|
|
|
|
|
|
|
|
2013-11-06 23:05:26 -05:00
|
|
|
class DigitalOcean():
|
2013-10-30 01:14:28 -04:00
|
|
|
|
|
|
|
def __init__(self, key, client):
|
2013-10-10 20:46:09 -04:00
|
|
|
'''Set default API parameters'''
|
2013-10-30 01:14:28 -04:00
|
|
|
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 {}
|
2013-10-10 20:46:09 -04:00
|
|
|
|
|
|
|
|
|
|
|
def json_fmt(data):
|
|
|
|
'''Format json output'''
|
|
|
|
return json.dumps(data, sort_keys = True, indent = 2)
|
|
|
|
|
|
|
|
|
2013-11-06 23:05:26 -05:00
|
|
|
do = DigitalOcean(env['DO_API_KEY'], env['DO_CLIENT_ID'])
|
2013-10-10 20:46:09 -04:00
|
|
|
|
2013-10-30 01:14:28 -04:00
|
|
|
# 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))
|
2013-10-10 20:46:09 -04:00
|
|
|
exit(1)
|
|
|
|
|
2013-10-30 01:14:28 -04:00
|
|
|
# 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)
|
2013-10-10 20:46:09 -04:00
|
|
|
|
2013-10-30 01:14:28 -04:00
|
|
|
# Wait for the machine to boot
|
|
|
|
sleep(15)
|
|
|
|
|
|
|
|
# Get droplet IP
|
|
|
|
ip = str(data['ip_address'])
|
|
|
|
print 'droplet: {} ip: {}'.format(DROPLET_NAME, ip)
|
2013-10-10 20:46:09 -04:00
|
|
|
|
|
|
|
# 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
|
2013-10-30 01:14:28 -04:00
|
|
|
api.env.user = DO_IMAGE_USER
|
2013-10-10 20:46:09 -04:00
|
|
|
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'],
|
2013-10-27 15:13:03 -04:00
|
|
|
'GPG_PASSPHRASE': env['PKG_GPG_PASSPHRASE']}
|
2013-10-10 20:46:09 -04:00
|
|
|
open(DOCKER_CI_PATH + '/nightlyrelease/release_credentials.json', 'w').write(
|
|
|
|
base64.b64encode(json.dumps(credentials)))
|
|
|
|
|
|
|
|
# Transfer docker
|
|
|
|
sudo('mkdir -p ' + DOCKER_CI_PATH)
|
2013-10-30 01:14:28 -04:00
|
|
|
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,
|
2013-10-10 20:46:09 -04:00
|
|
|
os.path.dirname(DOCKER_CI_PATH)), shell=True)
|
|
|
|
|
|
|
|
# Install Docker and Buildbot dependencies
|
|
|
|
sudo('mkdir /mnt/docker; ln -s /mnt/docker /var/lib/docker')
|
2013-12-27 10:18:40 -05:00
|
|
|
sudo('apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9')
|
2013-10-10 20:46:09 -04:00
|
|
|
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)'
|
2013-10-30 01:14:28 -04:00
|
|
|
' aufs-tools make libfontconfig libevent-dev libsqlite3-dev libssl-dev')
|
2013-12-17 01:57:54 -05:00
|
|
|
sudo('wget -O - https://go.googlecode.com/files/go1.2.linux-amd64.tar.gz | '
|
2013-10-10 20:46:09 -04:00
|
|
|
'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))
|
2013-10-27 15:13:03 -04:00
|
|
|
sudo('cd {}; docker build -t docker-ci .'.format(DOCKER_CI_PATH))
|
2013-10-10 20:46:09 -04:00
|
|
|
sudo('cd {}/nightlyrelease; docker build -t dockerbuilder .'.format(
|
|
|
|
DOCKER_CI_PATH))
|
2013-10-27 15:13:03 -04:00
|
|
|
sudo('cd {}/registry-coverage; docker build -t registry_coverage .'.format(
|
|
|
|
DOCKER_CI_PATH))
|
2013-10-10 20:46:09 -04:00
|
|
|
|
2013-10-19 01:33:16 -04:00
|
|
|
# Download docker-ci testing container
|
|
|
|
sudo('docker pull mzdaniel/test_docker')
|
|
|
|
|
2013-10-10 20:46:09 -04:00
|
|
|
# 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']))
|
2013-11-06 23:05:26 -05:00
|
|
|
|
|
|
|
# Preventively reboot docker-ci daily
|
|
|
|
sudo('ln -s /sbin/reboot /etc/cron.daily')
|