Newer
Older
#!/usr/bin/env python
# vim: set shiftwidth=4 softtabstop=4:
"""Script to locally build a docker image
"""
import argparse
import json
import logging
import os
import signal
from subprocess import call
import sys
import ConfigParser
import docker # apt python-docker (1.9) or pip install docker
if docker.__version__ > '2.5.0':
from docker import APIClient as docker_api
else:
from docker import Client as docker_api
_logger = logging.getLogger(__name__)
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
def main(argv=None): # IGNORE:C0111
"""Parse arguments and docker build
"""
program_version = __version__
program_build_date = str(__updated__)
program_version_message = '%%(prog)s %s (%s)' % (
program_version, program_build_date)
program_shortdesc = __doc__.split(".")[0]
program_license = '''%s
Created by Vincent Hatakeyama on %s.
Copyright 2018 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)
if project_name == 'odoo_scripts':
logging.fatal(
"You must run this script from the super project"
" (./odoo_scripts/docker_build.py)")
return
setup_path = 'setup.cfg'
# TODO add a way to store configuration options in a project file
# 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]")
# TODO add tag option, and maybe force tag option
parser.add_argument(
'--ensureconf',
help="ensureconf [default: %(default)s]",
action='store_true',
)
parser.add_argument(
'--push',
help="Push image [default: %(default)s]",
action='store_true',
)
parser.add_argument(
'--dev',
help="add dev feature to generated image [default: %(default)s]",
action='store_true',
)
# TODO (maybe) add argument for other build arg
# TODO detect that user is member of docker group

Vincent Hatakeyama
committed
nmspc = parser.parse_args(argv)
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)
ensureconf = nmspc.ensureconf
dev = nmspc.dev
push = nmspc.push
c = ConfigParser.ConfigParser()
if not os.path.exists(setup_path):
logging.fatal('Missing %s', setup_path)
return 12
c.read(setup_path)
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)
odoo_type = (
c.has_section('odoo_scripts') and
c.has_option('odoo_scripts', 'odoo_type') and
c.get('odoo_scripts', 'odoo_type')) or 'odoo7'
image = "%s/%s:latest" % (registry, project)
logging.debug("Docker image: %s", image)
# TODO ensureconf
if ensureconf:
raise NotImplementedError
# call build copy
cmd = ['./odoo_scripts/docker_build_copy']
logging.debug(' '.join(cmd))
call(cmd)
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# clean on exit
def signal_handler(code, frame):
cmd = ['./odoo_scripts/docker_build_clean']
logging.debug(' '.join(cmd))
call(cmd)
# XXX needed?
# sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
# TODO docker build
buildargs = {}
dockerfile = 'Dockerfile'
if dev:
debug_dockerfile = 'Dockerfile.debug'
call(['cp', dockerfile, debug_dockerfile])
with open(debug_dockerfile, 'a') as myfile:
myfile.write('\n# Developer helpers\n'
'RUN apt-get update -qq\n')
myfile.write(
'RUN DEBIAN_FRONTEND=noninteractive apt-get install -y -qq ')
if odoo_type == 'odoo11':
myfile.write(
'python3-watchdog python3-ipdb\n')
elif odoo_type in ('odoo10', ):
'python-ipdb\n')

Vincent Hatakeyama
committed
myfile.write('RUN pip install watchdog')
elif odoo_type in ('odoo7', 'odoo8'):
myfile.write(
'python-ipdb\n')
myfile.write('RUN pip install pyinotify')
dockerfile = debug_dockerfile
# TODO remove temp image
docker_client = docker_api(base_url='unix://var/run/docker.sock')
builder = docker_client.build(
path='.', rm=True, pull=True, buildargs=buildargs,
tag=image, dockerfile=dockerfile)
# this is for python docker 1.8-1.9
# TODO add compatibility with newer python docker
for line in builder:
d = json.loads(line)
if 'stream' in d:
logging.info(d['stream'])

Vincent Hatakeyama
committed
if 'errorDetail' in d:
logging.fatal(d['errorDetail'])
return 1
# TODO exit if build failed
# TODO docker tag with tags/bookmarks (unused so maybe no need)
# TODO docker push (only when asked for)
if push:
raise NotImplementedError
# XXX call cleanup more intelligently
signal_handler(0, None)
return 0
if __name__ == "__main__":

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