Skip to content

Commit

Permalink
Merge pull request #6 from redcanari/adding-dockerize-subcommand
Browse files Browse the repository at this point in the history
Adding dockerize subcommand
  • Loading branch information
allfro committed Aug 6, 2016
2 parents b8852a9 + d5823e8 commit b6306aa
Show file tree
Hide file tree
Showing 11 changed files with 212 additions and 7 deletions.
18 changes: 18 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
FROM alpine
COPY . /root/sdist
RUN apk add --no-cache \
ca-certificates \
alpine-sdk \
python-dev \
py-lxml \
py-setuptools \
py-twisted && \
cd /root/sdist && \
python setup.py install && \
cd /root && \
rm -rf sdist && \
apk del \
alpine-sdk \
python-dev

ENTRYPOINT ["canari"]
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
'argparse',
'flask',
'Twisted',
'safedexml'
'safedexml',
'lxml'
]

if os.name == 'nt':
Expand Down
1 change: 1 addition & 0 deletions src/canari/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
'create_transform',
'csv2sheets',
'debug_transform',
'dockerize_package',
'framework',
'generate_entities',
'help',
Expand Down
104 changes: 104 additions & 0 deletions src/canari/commands/dockerize_package.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#!/usr/bin/env python
import os
import subprocess

import re

from canari import question
from mrbob.configurator import Configurator

from canari.project import CanariProject
from canari.utils.fs import PushDir
from common import canari_main
from distutils.spawn import find_executable
from framework import SubCommand, Argument

__author__ = 'Nadeem Douba'
__copyright__ = 'Copyright 2012, Canari Project'
__credits__ = ['Nadeem Douba']

__license__ = 'GPLv3'
__version__ = '0.5'
__maintainer__ = 'Nadeem Douba'
__email__ = 'ndouba@gmail.com'
__status__ = 'Development'


def run_command(args, **kwargs):
print 'Running command: %s' % ' '.join(args)
return subprocess.Popen(args, **kwargs)

@SubCommand(
canari_main,
help='Creates a Docker build file pre-configured with Plume.',
description='Creates a Docker build file that can be used to run remote transforms using Plume.'
)
@Argument(
'-H',
'--host',
metavar='[host]',
action='append',
default=[],
help='Docker daemon socket(s) to connect to'
)
def dockerize_package(args):

project = CanariProject()

print('Dockerizing %s transform package...' % project.name)

configurator = Configurator(
'canari.resources.templates:dockerize_package',
project.root_dir,
{'non_interactive': True},
variables={'project.name': project.name}
)

print('Creating Dockerfile for %s...' % project.name)
configurator.render()
print('done!')

if not find_executable('docker'):
print """Could not find 'docker' in your system path. Please download and install Docker from http://docker.com
and rerun this command again.
"""

exit(-1)

docker_hosts = [j for sublist in [('-H', i) for i in args.host] for j in sublist]
container = '%s/%s' % (project.name, project.name)

if not args.host:
if not find_executable('docker-machine'):
print """Could not find 'docker-machine' in your system path. Please download and install Docker Machine from
http://docker.com and rerun this command again or manually specify a Docker host using the '-H' parameter,
instead.
"""
exit(-1)

print 'Attempting to discover available Docker machines.'
machines = run_command(['docker-machine', 'ls', '-q'], stdout=subprocess.PIPE).communicate()[0].split('\n')
machines.remove('')

machine = question.parse_int('More than one Docker machine was detected. Which one would you like to use to'
'build and run this container?', machines) if len(machines) != 1 else 0

print 'Setting up environment for Docker machine %s' % machines[machine]

# Inject docker environment variables
env = run_command(['docker-machine', 'env', machines[machine]], stdout=subprocess.PIPE).communicate()[0]
os.environ.update(re.findall(r'export ([^=]+)="([^"]+)', env))

with PushDir(project.root_dir):
p = run_command(['docker'] + docker_hosts + ['build', '-t', container, '.'])
p.communicate()
if p.returncode:
print 'An error occurred while building the Docker container.'
exit(-1)

if question.parse_bool('Would you like to run this container now?'):
port = question.parse_int_range('Which port would you like Plume to listen on externally?', 0, 65535, 8080)
print 'Plume will be listening on http://%s:%s' % (re.findall('://([^:]+)', os.environ['DOCKER_HOST'])[0], port)
run_command(['docker'] + docker_hosts + ['run', '-it', '-p', '8080:%s' % port, container]).communicate()

print 'done!'
3 changes: 1 addition & 2 deletions src/canari/commands/install_plume.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,7 @@ def install_defaults(opts):
print 'The log files will be at /var/log/plume.log...'
configurator.variables['plume.log_dir'] = '/var/log'
configurator.variables['plume.user'] = check_uid(configurator, '', 'nobody')
configurator.variables['plume.group'] = check_gid(configurator, '',
'www-data' if 'linux' in sys.platform else 'nobody')
configurator.variables['plume.group'] = check_gid(configurator, '', 'nobody')
print 'The Plume server will under UID/GID=%s/%s...' % (
configurator.variables['plume.user'], configurator.variables['plume.group'])
print 'TLS will be disabled by default...'
Expand Down
9 changes: 8 additions & 1 deletion src/canari/commands/load_plume_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@
default=os.getcwd(),
help='the path where Plume is installed.'
)
@Argument(
'--accept-defaults',
'-y',
help='Load Plume package with all the defaults in non-interactive mode.',
default=False,
action='store_true'
)
def load_plume_package(opts):

with PushDir(opts.plume_dir):
Expand All @@ -59,7 +66,7 @@ def load_plume_package(opts):

if transform_package.has_remote_transforms:
try:
transform_package.configure(opts.plume_dir, remote=True)
transform_package.configure(opts.plume_dir, remote=True, defaults=opts.accept_defaults)
except ImportError, e:
print 'An error occurred while trying to import %r from %s: %s' % (
transform_package.name, opts.plume_dir, e
Expand Down
4 changes: 2 additions & 2 deletions src/canari/pkgutils/transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,10 +240,10 @@ def _update_config(self, canari_config, load=True, remote=False):

config.write(file(canari_config, mode='wb'))

def configure(self, install_prefix, load=True, remote=False, **kwargs):
def configure(self, install_prefix, load=True, remote=False, defaults=False, **kwargs):
if load:
dst = os.path.join(install_prefix, 'canari.conf')
if os.path.lexists(dst) and \
if os.path.lexists(dst) and not defaults and \
parse_bool('%s already exists. Would you like to overwrite it?' % dst, default=False):
print 'Writing fresh copy of canari.conf to %r...' % dst
variables = {
Expand Down
20 changes: 20 additions & 0 deletions src/canari/question.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,25 @@ def parse_int(question, choices, default=0):
print('Invalid selection (%s) must be an integer between 0 and %d.' % (ans, i))


def parse_int_range(question, from_, to, default=0):
from_ = int(from_)
to = int(to)

if from_ > to:
temp = from_
from_ = to
to = temp

while True:
ans = parse_str('%s. Valid values are between %d and %d' % (question, from_, to), default)
try:
ans = int(ans)
if not from_ <= ans <= to:
raise ValueError
return ans
except ValueError:
print('Invalid selection (%s) must be an integer between %d and %d.' % (ans, from_, to))


def parse_str(question, default):
return raw_input('%s [%s]: ' % (question, default)) or default
Empty file.
22 changes: 22 additions & 0 deletions src/canari/resources/templates/dockerize_package/Dockerfile.bob
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
FROM redcanari/canari
ADD . /root/sdist
RUN apk add --no-cache \
ca-certificates \
alpine-sdk \
python-dev \
py-lxml \
py-setuptools \
py-twisted && \
cd /root/sdist && \
python setup.py install && \
cd /root && \
rm -rf /root/sdist && \
mkdir -p /var/plume && \
cd /var/plume && \
canari install-plume -y && \
canari load-plume-package -y {{{ project.name }}} && \
apk del \
alpine-sdk \
python-dev
EXPOSE 8080
ENTRYPOINT /etc/init.d/plume start-docker
35 changes: 34 additions & 1 deletion src/canari/resources/templates/install_plume/plume.bob
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ cd $PLUME_DIR

case $1 in
start)
echo -n 'Starting plume: '
echo -n 'Starting Canari Plume: '
if [ -z "$PLUME_CERTIFICATE" ]; then
twistd \
--pidfile=$PID_FILE \
Expand Down Expand Up @@ -67,6 +67,39 @@ case $1 in
echo 'failed.';
fi;
;;
start-docker)
echo -n 'Starting Canari Plume container: '
if [ -z "$PLUME_CERTIFICATE" ]; then
twistd \
--pidfile=$PID_FILE \
--rundir=$PLUME_DIR \
--uid=$PLUME_UID \
--gid=$PLUME_GID \
-n \
web \
--wsgi=canari.tas.plume.application \
--port=$PLUME_PORT;
else
twistd \
--pidfile=$PID_FILE \
--rundir=$PLUME_DIR \
--uid=$PLUME_UID \
--gid=$PLUME_GID \
-n \
web \
--wsgi=canari.tas.plume.application \
--certificate=$PLUME_CERTIFICATE \
--privkey=$PLUME_PRIVATE_KEY \
--https=$PLUME_PORT \
--port=0;
fi;
sleep 1
if [ -f $PID_FILE ]; then
echo 'done.';
else
echo 'failed.';
fi;
;;
stop)
echo -n 'Stopping plume: '
if [ -f $PID_FILE ]; then
Expand Down

0 comments on commit b6306aa

Please sign in to comment.