annotate contrib/packaging/hg-docker @ 38458:e5916f1236f3

packaging: replace dockerlib.sh with a Python script I want to do some more advanced things with Docker in upcoming commits. Trying to do that with shell scripts will be a bit too painful for my liking. Implementing things in Python will be vastly simpler in the long run. This commit essentially ports dockerlib.sh to a Python script. dockerdeb and dockerrpm have been ported to use the new hg-docker script. hg-docker requires Python 3. I've only tested on Python 3.5. Unlike the local packaging scripts which may need to run on old distros, the Docker packaging scripts don't have these constraints. So I think it is acceptable to require Python 3.5. As part of the transition, the Docker image tags changed slightly. I don't think that's a big deal: the Docker image names are effectively arbitrary and are a means to an end to achieve running commands in Docker containers. The code for resolving the Dockerfile content allows substituting values passed as arguments. This will be used in a subsequent commit. Differential Revision: https://phab.mercurial-scm.org/D3759
author Gregory Szorc <gregory.szorc@gmail.com>
date Sat, 12 May 2018 17:03:47 -0700
parents
children 92b3811fd15f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
38458
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
1 #!/usr/bin/env python3
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
2 #
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
3 # Copyright 2018 Gregory Szorc <gregory.szorc@gmail.com>
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
4 #
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
5 # This software may be used and distributed according to the terms of the
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
6 # GNU General Public License version 2 or any later version.
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
7
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
8 import argparse
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
9 import pathlib
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
10 import shutil
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
11 import subprocess
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
12 import sys
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
13
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
14 def get_docker() -> str:
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
15 docker = shutil.which('docker.io') or shutil.which('docker')
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
16 if not docker:
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
17 print('could not find docker executable')
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
18 return 1
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
19
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
20 try:
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
21 out = subprocess.check_output([docker, '-h'], stderr=subprocess.STDOUT)
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
22
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
23 if b'Jansens' in out:
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
24 print('%s is the Docking System Tray; try installing docker.io' %
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
25 docker)
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
26 sys.exit(1)
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
27 except subprocess.CalledProcessError as e:
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
28 print('error calling `%s -h`: %s' % (docker, e.output))
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
29 sys.exit(1)
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
30
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
31 out = subprocess.check_output([docker, 'version'],
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
32 stderr=subprocess.STDOUT)
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
33
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
34 lines = out.splitlines()
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
35 if not any(l.startswith((b'Client:', b'Client version:')) for l in lines):
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
36 print('`%s version` does not look like Docker' % docker)
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
37 sys.exit(1)
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
38
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
39 if not any(l.startswith((b'Server:', b'Server version:')) for l in lines):
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
40 print('`%s version` does not look like Docker' % docker)
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
41 sys.exit(1)
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
42
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
43 return docker
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
44
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
45 def get_dockerfile(path: pathlib.Path, args: list) -> bytes:
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
46 with path.open('rb') as fh:
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
47 df = fh.read()
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
48
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
49 for k, v in args:
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
50 df = df.replace(b'%%%s%%' % k, v)
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
51
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
52 return df
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
53
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
54 def build_docker_image(dockerfile: pathlib.Path, params: list, tag: str):
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
55 """Build a Docker image from a templatized Dockerfile."""
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
56 docker = get_docker()
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
57
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
58 dockerfile_path = pathlib.Path(dockerfile)
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
59
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
60 dockerfile = get_dockerfile(dockerfile_path, params)
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
61
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
62 print('building Dockerfile:')
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
63 print(dockerfile.decode('utf-8', 'replace'))
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
64
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
65 args = [
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
66 docker,
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
67 'build',
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
68 '--build-arg', 'http_proxy',
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
69 '--build-arg', 'https_proxy',
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
70 '--tag', tag,
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
71 '-',
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
72 ]
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
73
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
74 print('executing: %r' % args)
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
75 subprocess.run(args, input=dockerfile, check=True)
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
76
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
77 def command_build(args):
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
78 build_args = []
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
79 for arg in args.build_arg:
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
80 k, v = arg.split('=', 1)
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
81 build_args.append((k.encode('utf-8'), v.encode('utf-8')))
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
82
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
83 build_docker_image(pathlib.Path(args.dockerfile),
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
84 build_args,
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
85 args.tag)
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
86
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
87 def command_docker(args):
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
88 print(get_docker())
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
89
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
90 def main() -> int:
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
91 parser = argparse.ArgumentParser()
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
92
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
93 subparsers = parser.add_subparsers(title='subcommands')
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
94
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
95 build = subparsers.add_parser('build', help='Build a Docker image')
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
96 build.set_defaults(func=command_build)
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
97 build.add_argument('--build-arg', action='append', default=[],
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
98 help='Substitution to perform in Dockerfile; '
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
99 'format: key=value')
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
100 build.add_argument('dockerfile', help='path to Dockerfile to use')
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
101 build.add_argument('tag', help='Tag to apply to created image')
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
102
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
103 docker = subparsers.add_parser('docker-path', help='Resolve path to Docker')
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
104 docker.set_defaults(func=command_docker)
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
105
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
106 args = parser.parse_args()
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
107
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
108 return args.func(args)
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
109
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
110 if __name__ == '__main__':
e5916f1236f3 packaging: replace dockerlib.sh with a Python script
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
111 sys.exit(main())