Newer
Older
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Launch a docker image but bind the local directory inside the container
and define the module path automatically.
isort:skip_file
"""

Vincent Hatakeyama
committed
# Version 2.22
import argparse

Vincent Hatakeyama
committed
import glob
import logging

Vincent Hatakeyama
committed
import pwd
from subprocess import call
import sys

Vincent Hatakeyama
committed
try:
from configparser import ConfigParser
except ImportError:
from ConfigParser import SafeConfigParser as ConfigParser
import docker # apt python-docker (1.9) or pip install docker

Vincent Hatakeyama
committed
from psycopg2 import connect, OperationalError # apt python-psycopg2
if docker.__version__ > '2.5.0':
from docker import APIClient as docker_api
else:
from docker import Client as docker_api
# TODO auto create list of module
_logger = logging.getLogger(__name__)
__version__ = '1.1.13'
__date__ = '2017-08-11'
__updated__ = '2019-07-15'
def which(program):
"""Return path of program if it exists
https://stackoverflow.com/questions/377017/test-if-executable-exists-in-python/377028#377028
"""
def is_exe(fpath):
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
fpath, fname = os.path.split(program)
if fpath:
if is_exe(program):
return program
else:
for path in os.environ["PATH"].split(os.pathsep):
exe_file = os.path.join(path, program)
if is_exe(exe_file):
return exe_file
return None
def flake8(odoo_type):
"""Run flake8
_logger.info('Running flake8')
if odoo_type in ('odoo7', 'odoo8', 'odoo9', 'odoo10'):
image = 'xcgd/flake8:2'
image = 'xcgd/flake8:3'
call([
'docker', 'run', '--rm', '--volume',
'{}:/mnt'.format(os.environ['PWD']), image,
'/mnt'])
def isort(docker_client):
"""
_logger.info('Pulling isort')
docker_client.pull(repository='xcgd/isort', tag='odoo')
_logger.info('Running isort')
call([
'docker', 'run', '--rm', '--volume',
'{}:/mnt'.format(os.environ['PWD']), '-w', '/mnt', 'xcgd/isort:odoo',
'isort', '-c'])
def main(argv=None): # IGNORE:C0111
"""Parse arguments and launch conversion
"""
program_version = __version__
program_build_date = str(__updated__)
program_version_message = '%%(prog)s %s (%s)' % (
program_version, program_build_date)

Vincent Hatakeyama
committed
program_shortdesc = __doc__.split(".")[0]
program_license = '''%s
Created by Vincent Hatakeyama on %s.
Copyright 2017, 2018, 2019 XCG Consulting. All rights reserved.
Licensed under the MIT License
Distributed on an "AS IS" basis without warranties
or conditions of any kind, either express or implied.
USAGE

Vincent Hatakeyama
committed
project_path = os.path.realpath('.')
project_name = os.path.basename(project_path)
if project_name == 'odoo_scripts':
logging.fatal(
"You must run this script from the super project"
" (./odoo_scripts/docker_dev_start.py)")

Vincent Hatakeyama
committed
setup_path = 'setup.cfg'
# Argument parsing
parser = argparse.ArgumentParser(
description=program_license,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument(
'-V', '--version', action='version',
version=program_version_message)
parser.add_argument(
'-v', '--verbose', dest='verbose', action='count',
help="set verbosity level [default: %(default)s]")
parser.add_argument(
'--db_user',
help="Database user [default: %(default)s]",
default=None,
)
parser.add_argument(
'--db_password',
help="Database user password [default: %(default)s]",
default=None,
)
parser.add_argument(
'--max-cron-threads',
help="max cron threads [default: %(default)s]",
default=None,
)
parser.add_argument(
'-d',
'--database',
help="Database [default: %(default)s]",
default=None,
)
parser.add_argument(
'-p',
'--dbport',
help="Change database port",
default=None,
group = parser.add_mutually_exclusive_group()
group.add_argument(
'-u',
'--update',
help="Module to update (will also set --i18n-overwrite)"
" [default: %(default)s]\n"
"Options --update, --test and --test-default"
" cannot be used at the same time",
default=None,
)
group.add_argument(
'-t',
'--test',
help="Modules to test (will also set --log-level=test)"
" [default: %(default)s]\n"
"Options --update, --test and --test-default"
" cannot be used at the same time",
)
group.add_argument(
'--test-default',
help="Test all modules in module_list_test"
" [default: %(default)s]\n"
"Options --update, --test and --test-default"
" cannot be used at the same time",
action='store_true',
)
parser.add_argument(
'-i',
'--install',
help="Module to install [default: %(default)s]",
default=None,
)
parser.add_argument(
'--without-demo',
help="Module to avoid including demo data [default: %(default)s]",
default=None,
)

Vincent Hatakeyama
committed
parser.add_argument(
help="Create user in database (using $user) [default: %(default)s]",

Vincent Hatakeyama
committed
action='store_true',
)

Vincent Hatakeyama
committed
parser.add_argument(
'--install-default',
help=("Append the module_list from setup.cfg to the modules to install"
" [default: %(default)s]"),

Vincent Hatakeyama
committed
action='store_true',
)

Vincent Hatakeyama
committed
parser.add_argument(
'--start-postgresql',
help="Start a Postgresql docker",
action='store_true',
)
parser.add_argument(
'--no-flake8',
help="Do not run flake8",
action='store_false',
dest='flake8',

Vincent Hatakeyama
committed
)

Vincent Hatakeyama
committed
parser.add_argument(
'--no-isort',
help="Do not run isort",
action='store_false',
dest='isort',
)
parser.add_argument(

Vincent Hatakeyama
committed
'--odoo-help',
help="Pass --help to odoo binary [default: %(default)s]",
action='store_true',
)
parser.add_argument(
'--stop-after-init',
help="Pass --stop-after-init to odoo binary [default: %(default)s]",
action='store_true',
)

Vincent Hatakeyama
committed
build_group = parser.add_mutually_exclusive_group()
build_group.add_argument(
'--no-build',
help="Do not build locally [default: %(default)s]",
action='store_true',
)
build_group.add_argument(
'--force-build',
help="Force new local build [default: %(default)s]",
action='store_true',
)

Vincent Hatakeyama
committed
network_group = parser.add_mutually_exclusive_group()
network_group.add_argument(
'--host-network',
help="Use host network [default: %(default)s]",
action='store_true',
default=True,

Vincent Hatakeyama
committed
)
network_group.add_argument(
'--docker-network',
help=("Use docker network (works better with"
" python-netifaces installed) [default: %(default)s]"),
action='store_false',
dest='host_network',
default=False,

Vincent Hatakeyama
committed
)
parser.add_argument(
'--no-dev',
help="No dev options",
action='store_false',
dest='dev',
)

Vincent Hatakeyama
committed
parser.add_argument(
'--load-language',
help="specifies the languages for the translations you want to be"
" loaded",
default=None,
dest='LOAD_LANGUAGE',
)
# TODO there are more
odoo_log_levels = ['info', 'warn', 'debug', 'debug_sql']
parser.add_argument(
'--log-level',
help="Override odoo log level (for tests and install)",
default=None,
choices=odoo_log_levels,
)
'--log-handler',
help="log handler [default: %(default)s]",
default=None,
)
parser.add_argument(
'--restore',
help="Database to restore [default: %(default)s]",
default=None,
dest='DUMP',
)
parser.add_argument(
'--config',
help="Configuration file to use, if any [default: %(default)s]",
default=os.path.join('conf', 'dev', 'odoo.conf'),
)

Vincent Hatakeyama
committed
py3o_group = parser.add_mutually_exclusive_group()
py3o_group.add_argument(
'--start-py3o',
help="start py3o docker [default: %(default)s]",
action='store_const',
default=None,
const=1,
dest='start_py3o',
)
py3o_group.add_argument(
'--no-start-py3o',
help="do not start py3o docker [default: %(default)s]",
action='store_const',
default=None,
const=-1,
dest='start_py3o',
)

Vincent Hatakeyama
committed
# TODO detect that user is member of docker group
# TODO add a way to add options to docker
# TODO add a way to add arg to odoo

Vincent Hatakeyama
committed
nmspc = parser.parse_args(argv)
verbose = nmspc.verbose
if not verbose:
logging.basicConfig(level=logging.WARN)
logging.basicConfig(level=logging.INFO)
logging.basicConfig(level=logging.DEBUG)
db_user = nmspc.db_user
db_password = nmspc.db_password

Vincent Hatakeyama
committed
use_host_network = nmspc.host_network
_logger.debug('Use host network: %s', str(use_host_network))

Vincent Hatakeyama
committed
start_postgresql = nmspc.start_postgresql
run_flake8 = nmspc.flake8
run_isort = nmspc.isort

Vincent Hatakeyama
committed
odoo_help = nmspc.odoo_help
restore_filename = nmspc.DUMP
database = nmspc.database
if restore_filename:
if not database:

Vincent Hatakeyama
committed
_logger.fatal('No database name given for restore')

Vincent Hatakeyama
committed
c = ConfigParser()
if not os.path.exists(setup_path):

Vincent Hatakeyama
committed
_logger.fatal('Missing %s', setup_path)
c.read(setup_path)

Vincent Hatakeyama
committed
modules = []
if c.has_option('odoo_scripts', 'modules'):
for entry in c.get('odoo_scripts', 'modules').split():
modules.extend(glob.glob(entry))
_logger.debug("addon modules: %s", ','.join(modules))
if not db_user and c.has_option('odoo_scripts', 'db_user'):
db_user = c.get('odoo_scripts', 'db_user')
if not db_password and c.has_option('odoo_scripts', 'db_password'):
db_password = c.get('odoo_scripts', 'db_password')
registry = (
c.has_section('odoo_scripts') and
c.has_option('odoo_scripts', 'registry') and
c.get('odoo_scripts', 'registry')) or 'registry.xcg.io'
project = (
c.has_section('odoo_scripts') and
c.has_option('odoo_scripts', 'image') and
c.get('odoo_scripts', 'image')) or os.path.basename(project_path)

Vincent Hatakeyama
committed
odoo_type = (
c.has_section('odoo_scripts') and
c.has_option('odoo_scripts', 'odoo_type') and
c.get('odoo_scripts', 'odoo_type')) or 'odoo7'

Vincent Hatakeyama
committed
image = "%s/%s:latest" % (registry, project)

Vincent Hatakeyama
committed
postgresql_version = (
c.has_section('odoo_scripts') and
c.has_option('odoo_scripts', 'postgresql_version') and
c.get('odoo_scripts', 'postgresql_version')) or '9.6'
module_list = (
c.has_section('odoo_scripts') and
c.has_option('odoo_scripts', 'module_list') and
c.get('odoo_scripts', 'module_list').split()) or []
if nmspc.start_py3o:
_logger.debug("Command line start py3o %d", nmspc.start_py3o)
start_py3o_stack = nmspc.start_py3o == 1
else:
start_py3o_stack = (
c.has_section('odoo_scripts') and
c.has_option('odoo_scripts', 'start_py3o') and
c.get('odoo_scripts', 'start_py3o') in ('yes', 'true'))
_logger.debug("No command line start py3o %d", start_py3o_stack)

Vincent Hatakeyama
committed
_logger.debug("Docker image: %s", image)

Vincent Hatakeyama
committed
# detect if docker image already exists
docker_client = docker_api(base_url='unix://var/run/docker.sock')

Vincent Hatakeyama
committed
image_list = docker_client.images(name=image, quiet=True)
if not image_list:

Vincent Hatakeyama
committed
_logger.info("Image %s does not exist", image)

Vincent Hatakeyama
committed
else:

Vincent Hatakeyama
committed
_logger.info("Image %s exists", image)

Vincent Hatakeyama
committed
if (not image_list and not nmspc.no_build) or nmspc.force_build:

Vincent Hatakeyama
committed
_logger.info("Building image %s", image)

Vincent Hatakeyama
committed
arguments = [
'--dev'
]
if verbose == 1:
arguments.append('-v')
elif verbose and verbose > 1:
arguments.append('-vv')
failed = docker_build.main(arguments)
if failed:
return failed

Vincent Hatakeyama
committed
# options is only used with subprocess call
options = [
'--name',
project_name,
'--rm',
'--tty',
'--interactive',
]
if not use_host_network:
options.append('--publish')
options.append('8069:8069')

Vincent Hatakeyama
committed
binds = []
arg = [
'start',
]
if db_password:
arg.append('--db_password %s' % db_password)
if nmspc.update:
arg.append('-u %s' % nmspc.update)
arg.append('--i18n-overwrite')
if nmspc.test:
arg.append('-u %s' % nmspc.test)
arg.append('--test-enable')
if odoo_type == 'odoo7':
arg.append('--log-level=test')
if nmspc.test or nmspc.stop_after_init:
arg.append('--stop-after-init')
if nmspc.test_default:
test_modules = c.get('odoo_scripts', 'module_list_tests').split() or []
str_modules = ','.join(test_modules)
arg.append('-u %s' % str_modules)
arg.append('--test-enable')
if odoo_type == 'odoo7':
arg.append('--log-level=test')
arg.append('--stop-after-init')
if database:
arg.append('-d %s' % database)

Vincent Hatakeyama
committed
if nmspc.install or nmspc.install_default:
modules_to_install = []
if nmspc.install:
modules_to_install.extend(nmspc.install.split(','))

Vincent Hatakeyama
committed
if nmspc.install_default:
modules_to_install.extend(module_list)

Vincent Hatakeyama
committed
if modules_to_install:
arg.append('-i')
arg.append(','.join(modules_to_install))
if nmspc.without_demo:
arg.append('--without-demo')
arg.append(nmspc.without_demo)
if nmspc.max_cron_threads:
arg.append('--max-cron-threads=%s' % nmspc.max_cron_threads)
if nmspc.log_level:
arg.append('--log-level')
arg.append(nmspc.log_level)
if nmspc.log_handler:
arg.append('--log-handler')
arg.append(nmspc.log_handler)

Vincent Hatakeyama
committed
if nmspc.LOAD_LANGUAGE:
arg.append('--load-language')
arg.append(nmspc.LOAD_LANGUAGE)
# auto detect local ip

Vincent Hatakeyama
committed
if use_host_network:
local_ip = '127.0.0.1'

Vincent Hatakeyama
committed
options.append('--network')
options.append('host')
else:
local_ip = None
try:
from netifaces import ifaddresses, AF_INET # apt python-netifaces
iface_name = 'docker0'
addresses = [
i['addr']
for i in ifaddresses(
iface_name
).setdefault(AF_INET, [{'addr': 'No IP addr'}])
]
if addresses:
local_ip = addresses[0]
except ImportError:

Vincent Hatakeyama
committed
_logger.warn("Consider installing python netifaces"

Vincent Hatakeyama
committed
import socket

Vincent Hatakeyama
committed
_logger.info('Contacting Google Public DNS to find our IP')
local_ip = [
(
s.connect(('8.8.8.8', 53)),
s.getsockname()[0],
s.close()
) for s in [
socket.socket(socket.AF_INET, socket.SOCK_DGRAM)]
][0][1]

Vincent Hatakeyama
committed
_logger.debug('IP found %s', local_ip)
arg.append('--db_host')
arg.append(local_ip)
if nmspc.dbport:
arg.append("--db_port")
# auto detect local conf
local_conf_path = nmspc.config
local_conf_dir = os.path.dirname(os.path.realpath(local_conf_path))

Vincent Hatakeyama
committed
password = db_password
if os.path.isfile(local_conf_path):

Vincent Hatakeyama
committed
_logger.info('Local configuration file found: %s', local_conf_path)
odoo_conf_path = (
'/etc/odoo' if odoo_type in ('odoo11', 'odoo12', )

Vincent Hatakeyama
committed
else '/opt/odoo/etc'
)
binds.append('{}:{}'.format(os.path.join(
project_path, local_conf_dir), odoo_conf_path))

Vincent Hatakeyama
committed
cp_local = ConfigParser()

Vincent Hatakeyama
committed
cp_local.read(local_conf_path)
if not user:
user = cp_local.get('options', 'db_user')

Vincent Hatakeyama
committed
if not password:

Vincent Hatakeyama
committed
# doing this avoid having to change the value of redis_host
# used by smile_redis_session_store
redis_host = (
cp_local.has_section('options') and
cp_local.has_option('options', 'redis_host') and
cp_local.get('options', 'redis_host')) or None
if redis_host:
options.append('--add-host')
options.append('{}:{}'.format(redis_host, local_ip))
else:
_logger.info('No configuration file at: %s', local_conf_path)
# default values if nothing else
if not user:
user = 'odoo'

Vincent Hatakeyama
committed
arg.append('--db_user %s' % user)
if not password:
password = 'odoo'

Vincent Hatakeyama
committed

Vincent Hatakeyama
committed
# data volume handling
if odoo_type == 'odoo7':
_logger.debug('Only sessions volume for this odoo version')
# this path is in odoo code, the last part is the system user
data_volume_path = '/tmp/oe-sessions-{}'.format('odoo')
else:
data_volume_path = '/mnt/data'
arg.append('--data-dir {}'.format(data_volume_path))
data_volume_name = '{}_data'.format(project_name)
_logger.debug('Using data volume %s', data_volume_name)
createVolume(docker_client, data_volume_name)
# make sure the permission in the volume are correct
mount_opts = '{}:/mnt'.format(data_volume_name)
# TODO replace by something cleaner if possible
call([
'docker', 'run', '--rm', '-v', mount_opts, '--entrypoint',
'/bin/chown', image, 'odoo', '/mnt',
])
binds.append('{}:{}'.format(data_volume_name, data_volume_path))

Vincent Hatakeyama
committed

Vincent Hatakeyama
committed
# avoid the duplication of unbind volumes with all addons
if odoo_type == 'odoo7':
extra_volumes = [
'/opt/odoo/additional_addons', '/opt/odoo/var',
# not used but declared as a mount point in Dockerfile :-(
'/opt/odoo/data',
]
elif odoo_type == 'odoo8':
extra_volumes = [
'/opt/odoo/additional_addons', '/opt/odoo/var', '/opt/odoo/data',
]
elif odoo_type == 'odoo10':
extra_volumes = [
'/opt/odoo/additional_addons', '/opt/odoo/var', '/opt/odoo/data',
]
else:
extra_volumes = [
'/var/lib/odoo',
]
for extra_volume in extra_volumes:
volume_name = '{}_{}'.format(
project_name, extra_volume.replace('/', '_'))
binds.append('{}:{}'.format(volume_name, extra_volume))

Vincent Hatakeyama
committed
if start_py3o_stack:
start_py3o(docker_client)
options.append('--add-host')
options.append('py3o-fusion-server:{}'.format(local_ip))

Vincent Hatakeyama
committed
if start_postgresql and not odoo_help:
host_pg_port = nmspc.dbport if nmspc.dbport else 5433
name, stop_postgresql = docker_run_postgresql(
docker_client, project_name, postgresql_version, host_pg_port)

Vincent Hatakeyama
committed
arg.append('--db_port')
arg.append(str(host_pg_port))

Vincent Hatakeyama
committed
# Check that connection can be done, try to create user if asked to
# TODO: handle the case where the database is still starting up
# TODO: (and remove the sleep)
try:
if local_ip or start_postgresql:
port = host_pg_port if start_postgresql else None
user=user,
password=password,
database='postgres',
host=local_ip,
port=port,
)

Vincent Hatakeyama
committed
else:
user=user,
password=password,
database='postgres',
)
except OperationalError as exception:
if nmspc.create_user:

Vincent Hatakeyama
committed
_logger.debug('Cannot connect to database with user %s', user)
_logger.debug(exception)
_logger.info('Creating user %s', user)
database='postgres',
host=local_ip,
port=host_pg_port,
)
else:
loginname = pwd.getpwuid(os.getuid())[0]
connection = connect(user=loginname, database='postgres')
with connection.cursor() as cursor:
# not injection safe but you are on your own machine
# with already full access to db
cursor.execute(
'CREATE ROLE %s LOGIN CREATEDB PASSWORD %%s' % user,
(password,))
connection.commit()
connection.close()
else:

Vincent Hatakeyama
committed
_logger.fatal(

Vincent Hatakeyama
committed
_logger.fatal(exception)
_logger.info(
"You can add the --create-user argument to create it")
return 16
# restore
if restore_filename:
restore_basename = os.path.basename(restore_filename)

Vincent Hatakeyama
committed
_logger.info("Copying dump file in docker")
call([
'docker', 'cp', restore_filename,
'{}:/tmp/{}'.format(name, restore_basename)])

Vincent Hatakeyama
committed
_logger.info("Creating database")
call([
'docker', 'exec', name, 'createdb', '-U', user, database])

Vincent Hatakeyama
committed
_logger.info("Restoring database")
restore = call([
'docker', 'exec', name, 'pg_restore', '-U', user, '-O',
'-d', database, '/tmp/{}'.format(restore_basename)])
if not restore:
return 15

Vincent Hatakeyama
committed
_logger.info("Removing dump file in docker")
call(['docker', 'exec', name, '/tmp/{}'.format(restore_basename)])
if not start_postgresql and not odoo_help and restore_filename:

Vincent Hatakeyama
committed
_logger.info("Creating database %s", database)
createdb = call([
'createdb', '-U', user, database])
if not createdb:
return 17

Vincent Hatakeyama
committed
_logger.info("Restoring database %s", database)
restore = call([
'pg_restore', '-U', user, '-O',
'-d', database, restore_filename])
if not restore:
return 15
# volume magic

Vincent Hatakeyama
committed
for module in modules:
'%s:/mnt/addons/%s' % (

Vincent Hatakeyama
committed
os.path.realpath(os.path.join(
project_path, module)),
os.path.basename(module))
)
all_addons_dir = ['/mnt/addons']
if odoo_type in ('odoo7', 'odoo8'):
all_addons_dir.append('/opt/odoo/sources/odoo/addons')
if all_addons_dir:
arg.append('--addons-path')
arg.append(','.join(all_addons_dir))
if run_isort:
isort(docker_client)
if dev:
if odoo_type in ('odoo11', 'odoo10'):
# ipdb should not be run if not interactive
arg.append('--dev=reload,ipdb')
if odoo_type in ('odoo8',):
arg.append('--auto-reload')

Vincent Hatakeyama
committed
if odoo_help:
arg.append('--help')
# use call to allow usage of pdb
for bind in binds:
options.append('--volume')
options.append(bind)
cmd = ['docker', 'run']
cmd.extend(options)
cmd.append(image)
cmd.extend(arg)

Vincent Hatakeyama
committed
_logger.debug(' '.join(cmd))
result = call(cmd)
return result

Vincent Hatakeyama
committed
def createVolume(docker_client, data_volume_name):

Vincent Hatakeyama
committed
"""Return the volume passed in parameter, creating it if it does not exists
"""
volumes = docker_client.volumes(filters={'name': data_volume_name})
if volumes['Volumes']:

Vincent Hatakeyama
committed
_logger.debug('Volume %s already exist', data_volume_name)

Vincent Hatakeyama
committed
return volumes['Volumes'][0]
else:

Vincent Hatakeyama
committed
_logger.debug('Creating volume %s', data_volume_name)

Vincent Hatakeyama
committed
return docker_client.create_volume(name=data_volume_name)
def isRunning(docker_client, container_id):
"""Return true if the container is still running
"""
return len(docker_client.containers(
filters={'id': container_id}, quiet=True))
def docker_run_postgresql(
docker_client, project_name, postgresql_version, host_pg_port=None,
stop_at_exit=True,
):
"""
:param docker_client:
:param project_name:
:param postgresql_version:
:param host_pg_port: if None, put the socket in /tmp, else publish the port
:param stop_at_exit:
:return:
"""
pg_repository = 'postgres'
version = '{}-alpine'.format(postgresql_version)
pg_image = '{}:{}'.format(pg_repository, version)
name = 'postgresql-{}-{}'.format(postgresql_version, project_name)
docker_client.pull(repository=pg_repository, tag=version)
pg_data_volume_name = 'postgresql_{}-{}'.format(
postgresql_version, project_name)
# volume = createVolume(docker_client, pg_data_volume_name)
binds = [

Vincent Hatakeyama
committed
'{}:/var/lib/postgresql/data'.format(pg_data_volume_name),
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
]
port_bindings = {}
if host_pg_port:
port_bindings[5432] = host_pg_port
else:
binds.append('/tmp:/var/run/postgresql')
host_config = docker_client.create_host_config(
binds=binds,
port_bindings=port_bindings,
)
if any(
'/{}'.format(name) in container['Names']
for container in docker_client.containers()
):
_logger.debug('Postgresql Container already running')
return name, False
_logger.debug('Creating postgresql container')
pg = docker_client.create_container(
image=pg_image,
host_config=host_config,
name=name,
)
_logger.debug('Starting postgresql container')
docker_client.start(pg.get('Id'))
def stop_postgresql():
# TODO test if still exists
try:
_logger.info('Stopping postgresql')
docker_client.stop(pg.get('Id'))
_logger.info('Removing container postgresql')
docker_client.remove_container(pg.get('Id'))
except docker.errors.NotFound:
_logger.info('Postgresql already stopped')
if stop_at_exit:
atexit.register(stop_postgresql)
_logger.debug("Waiting for postgres to start")
# give pg the time to start up
import time
time.sleep(5)
return name, stop_postgresql
def find_container(docker_client, name):
"""Return container object from its name
"""
for container in docker_client.containers():
if '/{}'.format(name) in container['Names']:
return container
def remove_and_stop(docker_client, name):
# TODO handle the case when the container has been created, not running
tostop = find_container(docker_client, name)
docker_client.stop(tostop.get('Id'))
docker_client.remove_container(tostop.get('Id'))
def start_py3o(
docker_client, host_fusion_port=8765, stop_at_exit=True,
):
fusion_repository = 'xcgd/py3o'
fusion_version = '1.0.0'
fusion_name = 'py3o_fusion'
fusion_image = '{}:{}'.format(fusion_repository, fusion_version)
try:
docker_client.pull(repository=fusion_repository, tag=fusion_version)
except Exception as e:
_logger.warning('Exception when trying to pull: %s', e)
if any(
'/{}'.format(fusion_name) in container['Names']
for container in docker_client.containers()
):
_logger.debug('%s Container already running', fusion_name)
remove_and_stop(docker_client, fusion_name)
# TODO handle --host-network option
port_bindings = {8765: host_fusion_port}
host_config = docker_client.create_host_config(
binds=[],
port_bindings=port_bindings,
)
_logger.debug('Starting %s container', fusion_name)
fusion = docker_client.create_container(
image=fusion_image,
host_config=host_config,
name=fusion_name,
)
_logger.debug('Starting %s container', fusion_name)
docker_client.start(container=fusion.get('Id'))
def stop_py3o():
# TODO test if still exists
_logger.info('Stopping fusion')
docker_client.stop(fusion.get('Id'))
_logger.info('Removing containers')
docker_client.remove_container(fusion.get('Id'))
if stop_at_exit:
atexit.register(stop_py3o)
return fusion_name, stop_py3o
if __name__ == "__main__":

Vincent Hatakeyama
committed
return_code = main(sys.argv[1:])

Vincent Hatakeyama
committed
if return_code:
exit(return_code)