Skip to content

Commit

Permalink
Merge pull request #83 from autopilotpattern/containerpilot3-dev
Browse files Browse the repository at this point in the history
upgrade to ContainerPilot 3.0.0-RC1
  • Loading branch information
tgross authored Jun 12, 2017
2 parents 3aef683 + 9202b92 commit 04832fd
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 106 deletions.
18 changes: 5 additions & 13 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
FROM percona:5.6

ENV CONTAINERPILOT_VER 2.6.0
ENV CONTAINERPILOT file:///etc/containerpilot.json
ENV CONTAINERPILOT_VER 3.0.0-RC1
ENV CONTAINERPILOT /etc/containerpilot.json5

# By keeping a lot of discrete steps in a single RUN we can clean up after
# ourselves in the same layer. This is gross but it saves ~100MB in the image
Expand All @@ -23,6 +23,7 @@ RUN set -ex \
python-Consul==0.4.7 \
manta==2.5.0 \
mock==2.0.0 \
json5==0.2.4 \
# \
# Add Consul from https://releases.hashicorp.com/consul \
# \
Expand All @@ -35,7 +36,7 @@ RUN set -ex \
# \
# Add ContainerPilot and set its configuration file path \
# \
&& export CONTAINERPILOT_CHECKSUM=c1bcd137fadd26ca2998eec192d04c08f62beb1f \
&& export CONTAINERPILOT_CHECKSUM=f67929d1c8567d31772085fc252338091a5f795c \
&& curl -Lvo /tmp/containerpilot.tar.gz "https://github.com/joyent/containerpilot/releases/download/${CONTAINERPILOT_VER}/containerpilot-${CONTAINERPILOT_VER}.tar.gz" \
&& echo "${CONTAINERPILOT_CHECKSUM} /tmp/containerpilot.tar.gz" | sha1sum -c \
&& tar zxf /tmp/containerpilot.tar.gz -C /usr/local/bin \
Expand All @@ -59,13 +60,4 @@ COPY bin/manage.py /usr/local/bin/manage.py

# override the parent entrypoint
ENTRYPOINT []

# use --console to get error logs to stderr
CMD [ "containerpilot", \
"mysqld", \
"--console", \
"--log-bin=mysql-bin", \
"--log_slave_updates=ON", \
"--gtid-mode=ON", \
"--enforce-gtid-consistency=ON" \
]
CMD ["/usr/local/bin/containerpilot"]
58 changes: 23 additions & 35 deletions bin/manager/containerpilot.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
""" autopilotpattern/mysql ContainerPilot configuraton wrapper """
import json
import os
import signal
import subprocess

import json5

from manager.utils import debug, env, to_flag, log, UNASSIGNED

# pylint: disable=invalid-name,no-self-use,dangerous-default-value
Expand All @@ -19,38 +22,20 @@ def __init__(self):

def load(self, envs=os.environ):
"""
Parses the ContainerPilot config file and interpolates the
environment into it the same way that ContainerPilot does.
The `state` attribute will be populated with the state
derived from the configuration file and not the state known
by Consul.
Fetches the ContainerPilot config file and asks ContainerPilot
to render it out so that all environment variables have been
interpolated.
"""
self.path = env('CONTAINERPILOT', None, envs,
lambda x: x.replace('file://', ''))
with open(self.path, 'r') as f:
cfg = f.read()

# remove templating so that we can parse it as JSON; we'll
# override the attributes directly in the resulting dict
cfg = cfg.replace('[{{ if .CONSUL_AGENT }}', '[')
cfg = cfg.replace('}{{ end }}', '}')

# remove templating for SERVICE_NAME
service_name = env('SERVICE_NAME', 'mysql')
cfg = cfg.replace('{{ if .SERVICE_NAME }}{{ .SERVICE_NAME }}{{ else }}mysql{{ end }}',service_name)
config = json.loads(cfg)

if env('CONSUL_AGENT', False, envs, to_flag):
config['consul'] = 'localhost:8500'
cmd = config['coprocesses'][0]['command']
host_cfg_idx = cmd.index('-retry-join') + 1
cmd[host_cfg_idx] = env('CONSUL', 'consul', envs)
config['coprocesses'][0]['command'] = cmd
else:
config['consul'] = env('CONSUL', 'consul', envs,
fn='{}:8500'.format)
config['coprocesses'] = []
self.path = env('CONTAINERPILOT', None, envs)
try:
cfg = subprocess.check_output(['containerpilot', '-config',
self.path, '-template'],
env=envs.copy())
except (subprocess.CalledProcessError, OSError) as ex:
log.error('containerpilot -template returned error: %s', ex)
raise(ex)

config = json5.loads(cfg)
self.config = config

@debug(log_output=True)
Expand All @@ -61,21 +46,24 @@ def update(self):
"""
if self.state == UNASSIGNED:
return False
if self.state and self.config['services'][0]['name'] != self.state:
self.config['services'][0]['name'] = self.state
if self.state and self.config['jobs'][1]['name'] != self.state:
self.config['jobs'][1]['name'] = self.state
self._render()
return True
return False

@debug
def _render(self):
""" Writes the current config to file. """
new_config = json.dumps(self.config)
new_config = json5.dumps(self.config)
with open(self.path, 'w') as f:
log.info('rewriting ContainerPilot config: %s', new_config)
f.write(new_config)

def reload(self):
""" Force ContainerPilot to reload its configuration """
log.info('Reloading ContainerPilot configuration.')
os.kill(1, signal.SIGHUP)
try:
subprocess.check_output(['containerpilot', '-reload'])
except subprocess.CalledProcessError:
log.info("call to 'containerpilot -reload' failed")
21 changes: 8 additions & 13 deletions bin/test.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from datetime import datetime, timedelta
import fcntl
import json
import logging
import os
import tempfile
import unittest

# pylint: disable=import-error
import consul as pyconsul
import json5
import mock

import manage
Expand Down Expand Up @@ -835,25 +835,20 @@ def test_parse_with_consul_agent(self):
self.environ['CONSUL_AGENT'] = '1'
cp = ContainerPilot()
cp.load(envs=self.environ)

self.assertEqual(cp.config['consul'], 'localhost:8500')
cmd = cp.config['coprocesses'][0]['command']
cmd = cp.config['jobs'][4]['exec']
host_cfg_idx = cmd.index('-retry-join') + 1
self.assertEqual(cmd[host_cfg_idx], 'my.consul.example.com')
self.assertEqual(cp.state, UNASSIGNED)

def test_parse_without_consul_agent(self):
self.environ['CONSUL_AGENT'] = '0'
cp = ContainerPilot()
cp.load(envs=self.environ)
self.assertEqual(cp.config['consul'], 'my.consul.example.com:8500')
self.assertEqual(cp.config['coprocesses'], [])
self.assertEqual(cp.state, UNASSIGNED)

self.environ['CONSUL_AGENT'] = ''
cp = ContainerPilot()
cp.load(envs=self.environ)
self.assertEqual(cp.config['consul'], 'my.consul.example.com:8500')
self.assertEqual(cp.config['coprocesses'], [])
self.assertFalse('consul-agent' in
[job['name'] for job in cp.config['jobs']])
self.assertEqual(cp.state, UNASSIGNED)

def test_update(self):
Expand All @@ -873,9 +868,9 @@ def test_update(self):
cp.state = PRIMARY
cp.update()
with open(temp_file.name, 'r') as updated:
config = json.loads(updated.read())
config = json5.loads(updated.read())
self.assertEqual(config['consul'], 'localhost:8500')
cmd = config['coprocesses'][0]['command']
cmd = config['jobs'][4]['exec']
host_cfg_idx = cmd.index('-retry-join') + 1
self.assertEqual(cmd[host_cfg_idx], 'my.consul.example.com')

Expand Down Expand Up @@ -936,7 +931,7 @@ def test_env_parse(self):
'CONSUL': 'my.consul.example.com',
'CONSUL_AGENT': '1',

'CONTAINERPILOT': 'file:///etc/containerpilot.json',
'CONTAINERPILOT': '/etc/containerpilot.json5',

'MYSQL_DATABASE': 'test_mydb',
'MYSQL_USER': 'test_me',
Expand Down
1 change: 0 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ services:
env_file: _env
network_mode: bridge
environment:
- CONTAINERPILOT=file:///etc/containerpilot.json
- CONSUL_AGENT=1
- LOG_LEVEL=INFO
- SERVICE_NAME=mysql
Expand Down
44 changes: 0 additions & 44 deletions etc/containerpilot.json

This file was deleted.

64 changes: 64 additions & 0 deletions etc/containerpilot.json5
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
consul: '{{ if .CONSUL_AGENT }}localhost{{ else }}{{ .CONSUL | default "consul"}}{{ end }}:8500',
logging: {
level: '{{ .LOG_LEVEL | default "INFO" }}'
},
jobs: [
{
name: "preStart",
exec: "python /usr/local/bin/manage.py"
},
{
name: '{{ .SERVICE_NAME | default "mysql" }}',
exec: ["mysqld",
"--console",
"--log-bin=mysql-bin",
"--log_slave_updates=ON",
"--gtid-mode=ON",
"--enforce-gtid-consistency=ON"],
port: 3306,
when: {
source: "preStart",
once: "exitSuccess"
},
health: {
exec: "python /usr/local/bin/manage.py health",
interval: 5,
ttl: 25
}
},
{
name: "onChange",
exec: "python /usr/local/bin/manage.py on_change",
when: {
source:'watch.{{ .SERVICE_NAME | default "mysql" }}-primary' ,
each: "changed"
}
},
{
name: "snapshot-check",
exec: "python /usr/local/bin/manage.py snapshot_task",
timeout: "10m",
when: {
interval: "5m"
},
},
{{ if .CONSUL_AGENT }}{
name: "consul-agent",
restarts: "unlimited",
exec: ["/usr/local/bin/consul", "agent",
"-data-dir=/data",
"-config-dir=/config",
"-rejoin",
"-retry-join", '{{ .CONSUL | default "consul"}}',
"-retry-max", "10",
"-retry-interval", "10s"]
}{{ end }}
],
watches: [
{
name: '{{ .SERVICE_NAME | default "mysql" }}-primary',
interval: 10
}
]
}

0 comments on commit 04832fd

Please sign in to comment.