-
Georges Racinet authored
This constant has no use any more.
Georges Racinet authoredThis constant has no use any more.
launch 7.04 KiB
#!/usr/bin/env python3
import argparse
import json
import os
import re
import subprocess
import sys
import tarfile
HOME = os.environ['HOME']
# ! Docker context directory for the *heptapod-dev* image!
DOCKER_CONTEXT_DIR = os.path.realpath(os.path.dirname(__file__))
OMNIBUS_DIR = os.path.dirname(DOCKER_CONTEXT_DIR)
DOCKER_BASE_CONTEXT_DIR = os.path.join(OMNIBUS_DIR, 'heptapod')
SOURCES_DIR = os.path.join(OMNIBUS_DIR, 'repos')
PREFETCH_SOURCES = { # name in heptapod_revisions -> repo slug
'workhorse': 'heptapod-workhorse',
'shell': 'heptapod-shell',
}
def read_docker_file_from_field(path, image_tag_rx='.*?'):
"""Read the FROM of Dockerfile at given path."""
rx = re.compile(r'^FROM\s*(' + image_tag_rx + r')\s*$')
with open(path) as dockerfile:
for line in dockerfile.readlines():
line = line.strip().split('#', 1)[0]
match = rx.match(line)
if match is not None:
return match.group(1)
return LookupError("Cant find FROM statement in Dockerfile %r" % path)
def dev_from_base_image_tag(base_image_tag):
split = base_image_tag.split(':', 1)
if len(split) == 1:
image, tag = split[0], 'latest'
else:
image, tag = split
# for the dev image, `testing` tags don't bring much. Instead, they
# could a source of confusion if both `testing` and `latest` images
# happen to have been pushed with inconsistent versions (especially if
# `testing` is older than `latest`)
tag = tag.replace('testing', 'latest')
return ':'.join((image + '-dev', tag))
def get_volumes_dir(cl_args, arg_parser):
if cl_args.volumes_dir:
return cl_args.volumes_dir
image_tag = cl_args.image_tag
docker_repo, tag = image_tag.split(':', 1)
if docker_repo == 'octobus/heptapod':
subdir = tag
else:
arg_parser.error("Please provide an explicit --volumes-dir value "
"when using an image not from octobus/heptapod "
"(got %r)" % image_tag)
return os.path.join(os.environ['HOME'], 'heptapod-volumes', subdir)
DEFAULT_IMAGE_TAG = 'octobus/heptapod:testing'
def expand_join(*segments):
return os.path.expanduser(os.path.join(*segments))
def print_header(header, underline_char='-'):
print(header)
print(underline_char * len(header))
print()
def print_conf_section(header, elements):
print_header(header)
fmt = '%-{}s%s'.format(2 + max(len(le[0]) for le in elements))
for line_elts in elements:
print(fmt % (line_elts[0] + ':', line_elts[1]))
print()
def inspect_archive(tarball):
"""Return the contents of archival metadata as a dict."""
with tarfile.open(tarball) as tar:
archival = tar.extractfile('.hg_archival.txt')
res = dict([token.strip() for token in line.decode().split(':', 1)]
for line in archival.readlines())
archival.close()
return res
def main():
parser = argparse.ArgumentParser(
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
description=__doc__)
parser.add_argument('-s', '--simulate', action='store_true',
help="Output configuration instead of "
"executing commands")
vol_group = parser.add_argument_group("Docker volumes options")
vol_group.add_argument('--volumes-dir',
help="Base directory for the three standard "
"GitLab Docker volumes (default value is the "
"pure tag part of --image-tag, typically 'testing' "
"or 'x-y-testing'")
vol_group.add_argument('--volume-conf', default="etc",
help="Name of the volumes subdirectory for "
"configuration")
vol_group.add_argument('--volume-data', default="var",
help="Name of the volumes subdirectory for data")
vol_group.add_argument('--volume-logs', default="log",
help="Name of the volumes subdirectory for logs")
vol_group.add_argument('--volume-src',
default=os.path.dirname(OMNIBUS_DIR),
help="Additional directory bind-mounted to "
"VOLUME_SRC_TARGET, defaulting to the parent "
"directory of the present omnibus working copy. "
"Assuming your working copies of heptapod, hg-git, "
"etc. are in this VOLUMES_SRC, this makes it easy "
"to update the code running in the container "
"from them."
)
vol_group.add_argument('--volume-src-target', default='/home/heptapod',
help="Where to mount VOLUME_SRC inside the "
"container.")
run_group = parser.add_argument_group("Other Docker run options")
run_group.add_argument('--http-port', type=int, default=81)
run_group.add_argument('--ssh-port', type=int, default=2022)
run_group.add_argument('--container-name', default='heptapod')
img_group = parser.add_argument_group("Docker image options")
img_group.add_argument('--image-tag',
default=DEFAULT_IMAGE_TAG,
help="Tag of the image to run ")
parsed_args = parser.parse_args()
simulate = parsed_args.simulate
volumes_dir = get_volumes_dir(parsed_args, parser)
etc_vol = expand_join(volumes_dir, parsed_args.volume_conf)
var_vol = expand_join(volumes_dir, parsed_args.volume_data)
log_vol = expand_join(volumes_dir, parsed_args.volume_logs)
src_vol = os.path.expanduser(parsed_args.volume_src)
do_build_dev = do_build_base = False
image_tag = parsed_args.image_tag
run_image_tag = image_tag
if simulate:
print_header("Simulation summary", underline_char='=')
print_conf_section("Image",
(("Full tag", image_tag),
))
print_conf_section("Volume bind mounts",
(('Configuration', etc_vol),
('Data', var_vol),
('Logs', log_vol),
('Sources', src_vol),
))
print_header("Commands")
run_cmd = ['docker', 'run', '--detach',
'--hostname', 'heptapod',
'--publish', '%d:80' % parsed_args.http_port,
'--publish', '%d:22' % parsed_args.ssh_port,
'--name', parsed_args.container_name,
]
bind_mounts = ((var_vol, '/var/opt/gitlab'),
(log_vol, '/var/log/gitlab'),
(etc_vol, '/etc/gitlab'),
(src_vol, parsed_args.volume_src_target),
)
for bm in bind_mounts:
run_cmd.extend(('--volume', '%s:%s' % bm))
run_cmd.append(run_image_tag)
print("Docker run command: %r" % run_cmd)
if not simulate:
subprocess.check_call(run_cmd)
print()
if __name__ == '__main__':
main()