9 import pathlib |
9 import pathlib |
10 import shutil |
10 import shutil |
11 import subprocess |
11 import subprocess |
12 import sys |
12 import sys |
13 |
13 |
|
14 |
14 def get_docker() -> str: |
15 def get_docker() -> str: |
15 docker = shutil.which('docker.io') or shutil.which('docker') |
16 docker = shutil.which('docker.io') or shutil.which('docker') |
16 if not docker: |
17 if not docker: |
17 print('could not find docker executable') |
18 print('could not find docker executable') |
18 return 1 |
19 return 1 |
19 |
20 |
20 try: |
21 try: |
21 out = subprocess.check_output([docker, '-h'], stderr=subprocess.STDOUT) |
22 out = subprocess.check_output([docker, '-h'], stderr=subprocess.STDOUT) |
22 |
23 |
23 if b'Jansens' in out: |
24 if b'Jansens' in out: |
24 print('%s is the Docking System Tray; try installing docker.io' % |
25 print( |
25 docker) |
26 '%s is the Docking System Tray; try installing docker.io' |
|
27 % docker |
|
28 ) |
26 sys.exit(1) |
29 sys.exit(1) |
27 except subprocess.CalledProcessError as e: |
30 except subprocess.CalledProcessError as e: |
28 print('error calling `%s -h`: %s' % (docker, e.output)) |
31 print('error calling `%s -h`: %s' % (docker, e.output)) |
29 sys.exit(1) |
32 sys.exit(1) |
30 |
33 |
31 out = subprocess.check_output([docker, 'version'], |
34 out = subprocess.check_output([docker, 'version'], stderr=subprocess.STDOUT) |
32 stderr=subprocess.STDOUT) |
|
33 |
35 |
34 lines = out.splitlines() |
36 lines = out.splitlines() |
35 if not any(l.startswith((b'Client:', b'Client version:')) for l in lines): |
37 if not any(l.startswith((b'Client:', b'Client version:')) for l in lines): |
36 print('`%s version` does not look like Docker' % docker) |
38 print('`%s version` does not look like Docker' % docker) |
37 sys.exit(1) |
39 sys.exit(1) |
40 print('`%s version` does not look like Docker' % docker) |
42 print('`%s version` does not look like Docker' % docker) |
41 sys.exit(1) |
43 sys.exit(1) |
42 |
44 |
43 return docker |
45 return docker |
44 |
46 |
|
47 |
45 def get_dockerfile(path: pathlib.Path, args: list) -> bytes: |
48 def get_dockerfile(path: pathlib.Path, args: list) -> bytes: |
46 with path.open('rb') as fh: |
49 with path.open('rb') as fh: |
47 df = fh.read() |
50 df = fh.read() |
48 |
51 |
49 for k, v in args: |
52 for k, v in args: |
50 df = df.replace(bytes('%%%s%%' % k.decode(), 'utf-8'), v) |
53 df = df.replace(bytes('%%%s%%' % k.decode(), 'utf-8'), v) |
51 |
54 |
52 return df |
55 return df |
|
56 |
53 |
57 |
54 def build_docker_image(dockerfile: pathlib.Path, params: list, tag: str): |
58 def build_docker_image(dockerfile: pathlib.Path, params: list, tag: str): |
55 """Build a Docker image from a templatized Dockerfile.""" |
59 """Build a Docker image from a templatized Dockerfile.""" |
56 docker = get_docker() |
60 docker = get_docker() |
57 |
61 |
63 print(dockerfile.decode('utf-8', 'replace')) |
67 print(dockerfile.decode('utf-8', 'replace')) |
64 |
68 |
65 args = [ |
69 args = [ |
66 docker, |
70 docker, |
67 'build', |
71 'build', |
68 '--build-arg', 'http_proxy', |
72 '--build-arg', |
69 '--build-arg', 'https_proxy', |
73 'http_proxy', |
70 '--tag', tag, |
74 '--build-arg', |
|
75 'https_proxy', |
|
76 '--tag', |
|
77 tag, |
71 '-', |
78 '-', |
72 ] |
79 ] |
73 |
80 |
74 print('executing: %r' % args) |
81 print('executing: %r' % args) |
75 p = subprocess.Popen(args, stdin=subprocess.PIPE) |
82 p = subprocess.Popen(args, stdin=subprocess.PIPE) |
76 p.communicate(input=dockerfile) |
83 p.communicate(input=dockerfile) |
77 if p.returncode: |
84 if p.returncode: |
78 raise subprocess.CalledProcessException( |
85 raise subprocess.CalledProcessException( |
79 p.returncode, 'failed to build docker image: %s %s' |
86 p.returncode, |
80 % (p.stdout, p.stderr)) |
87 'failed to build docker image: %s %s' % (p.stdout, p.stderr), |
|
88 ) |
|
89 |
81 |
90 |
82 def command_build(args): |
91 def command_build(args): |
83 build_args = [] |
92 build_args = [] |
84 for arg in args.build_arg: |
93 for arg in args.build_arg: |
85 k, v = arg.split('=', 1) |
94 k, v = arg.split('=', 1) |
86 build_args.append((k.encode('utf-8'), v.encode('utf-8'))) |
95 build_args.append((k.encode('utf-8'), v.encode('utf-8'))) |
87 |
96 |
88 build_docker_image(pathlib.Path(args.dockerfile), |
97 build_docker_image(pathlib.Path(args.dockerfile), build_args, args.tag) |
89 build_args, |
98 |
90 args.tag) |
|
91 |
99 |
92 def command_docker(args): |
100 def command_docker(args): |
93 print(get_docker()) |
101 print(get_docker()) |
|
102 |
94 |
103 |
95 def main() -> int: |
104 def main() -> int: |
96 parser = argparse.ArgumentParser() |
105 parser = argparse.ArgumentParser() |
97 |
106 |
98 subparsers = parser.add_subparsers(title='subcommands') |
107 subparsers = parser.add_subparsers(title='subcommands') |
99 |
108 |
100 build = subparsers.add_parser('build', help='Build a Docker image') |
109 build = subparsers.add_parser('build', help='Build a Docker image') |
101 build.set_defaults(func=command_build) |
110 build.set_defaults(func=command_build) |
102 build.add_argument('--build-arg', action='append', default=[], |
111 build.add_argument( |
103 help='Substitution to perform in Dockerfile; ' |
112 '--build-arg', |
104 'format: key=value') |
113 action='append', |
|
114 default=[], |
|
115 help='Substitution to perform in Dockerfile; ' 'format: key=value', |
|
116 ) |
105 build.add_argument('dockerfile', help='path to Dockerfile to use') |
117 build.add_argument('dockerfile', help='path to Dockerfile to use') |
106 build.add_argument('tag', help='Tag to apply to created image') |
118 build.add_argument('tag', help='Tag to apply to created image') |
107 |
119 |
108 docker = subparsers.add_parser('docker-path', help='Resolve path to Docker') |
120 docker = subparsers.add_parser('docker-path', help='Resolve path to Docker') |
109 docker.set_defaults(func=command_docker) |
121 docker.set_defaults(func=command_docker) |
110 |
122 |
111 args = parser.parse_args() |
123 args = parser.parse_args() |
112 |
124 |
113 return args.func(args) |
125 return args.func(args) |
114 |
126 |
|
127 |
115 if __name__ == '__main__': |
128 if __name__ == '__main__': |
116 sys.exit(main()) |
129 sys.exit(main()) |