Skip to content
Snippets Groups Projects
docker_dev_start.py 6 KiB
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.
"""
import argparse
import logging
from subprocess import call
import sys
import os

import ConfigParser

from netifaces import interfaces, ifaddresses, AF_INET

# TODO auto create list of module

_logger = logging.getLogger(__name__)

__version__ = '0.1.0'
__date__ = '2017-08-11'
__updated__ = '2017-08-11'

def main(argv=None):  # IGNORE:C0111
    """Parse arguments and launch conversion
    """
    if argv is None:
        argv = sys.argv
    else:
        sys.argv.extend(argv)

    program_version = __version__
    program_build_date = str(__updated__)
    program_version_message = '%%(prog)s %s (%s)' % (
        program_version, program_build_date)
    program_shortdesc = __doc__.split("\n")[1]
    program_license = '''%s

  Created by Vincent Hatakeyama on %s.
  Copyright 2017 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
''' % (
    program_shortdesc,
    str(__date__),
    )
    # TODO the script assume it is launched from the parent super project
    project_path = os.path.realpath('.')
    project_name = os.path.basename(project_path)
    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]",
    )
    parser.add_argument(
        '--db_password',
        help="Database user password [default: %(default)s]",
    parser.add_argument(
        '-d',
        '--database',
        help="Database [default: %(default)s]",
        default=None,
    )
    parser.add_argument(
        '-u',
        '--update',
        help="Module to update (will also set --i18n-overwrite)"
             "[default: %(default)s]",
        default=None,
    )
    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,
    )
    # XXX add auto create user and password?

    # TODO add a way to add options to docker
    # TODO add a way to add arg to odoo

    nmspc = parser.parse_args()
    verbose = nmspc.verbose
    if not verbose:
        logging.basicConfig(level=logging.WARN)
    if verbose == 1:
        logging.basicConfig(level=logging.INFO)
    if verbose and verbose > 1:
        logging.basicConfig(level=logging.DEBUG)
    db_user = nmspc.db_user
    db_password = nmspc.db_password

    if project_name == 'odoo_scripts':
        logging.fatal(
            "You must run this script from the super project"
            " (./odoo_scripts/docker_dev_start.py)")
        return

    c = ConfigParser.ConfigParser()
    logging.debug('setup file path %s', setup_path)
    # TODO test that setup file exists
    c.read(setup_path)

    addon_dirs = c.get('odoo_scripts', 'addon_dirs', '').split()
    logging.debug("addon directories: %s", addon_dirs)
    registry = (
        c.has_section('odoo_scripts') and
        c.has_option('odoo_scripts', 'registry') and
        c.get('odoo_scripts', 'registry')) or 'dockerhub.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's avatar
Vincent Hatakeyama committed
    image = "%s/%s" % (registry, project)
    logging.debug("Docker image: %s", image)
    # TODO detect if docker image already exists

    options = [
        '--rm',
        '--publish',
        '8069:8069',
        '--tty',
        '--interactive',
    ]
    arg = [
        'start',
    ]
    if db_user:
        arg.append('--db_user %s' % db_user)
    if db_password:
        arg.append('--db_password %s' % db_user)
    if nmspc.update:
        arg.append('-u %s' % nmspc.update)
        arg.append('--i18n-overwrite')
    if nmspc.database:
        arg.append('-d %s' % nmspc.database)
    if nmspc.install:
        arg.append('-i %s' % nmspc.database)
        arg.append('--without-demo %s' % nmspc.database)
Vincent Hatakeyama's avatar
Vincent Hatakeyama committed
    ifaceName = 'docker0'
    addresses = [i['addr'] for i in ifaddresses(ifaceName).setdefault(AF_INET, [{'addr':'No IP addr'}])]
    if addresses:
        local_ip = addresses[0]
    else:
        import socket
        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]
    arg.append('--db_host')
    arg.append(local_ip)
    # auto detect local conf
    local_conf_path = 'conf/dev/odoo.conf'
    if os.path.isfile(local_conf_path):
        logging.info('Local configuration file found: %s' % local_conf_path)
        options.append('--volume')
        options.append('%s:/opt/odoo/etc/odoo.conf' % os.path.join(
            project_path, local_conf_path))

    # volume magic
    for addons_dir in addon_dirs:
        options.append('--volume')
        options.append('%s:/mnt/%s' % (os.path.join(project_path, addons_dir), addons_dir))
    all_addons_dir = [
        '/opt/odoo/sources/odoo/addons',
    ]
    all_addons_dir.extend('/mnt/%s' % addons_dir for addons_dir in addon_dirs)
    arg.append('--addons-path')
    arg.append(','.join(all_addons_dir))

    cmd = ['docker', 'run']
    cmd.extend(options)
    cmd.append(image)
    cmd.extend(arg)
    logging.debug(cmd)
    call(cmd)
    # TODO add handling of signal to reload

if __name__ == "__main__":
    main()