bootstrap/README.md: add README.md
[gd/samba-autobuild/.git] / bootstrap / docker.py
1 #!/usr/bin/env python3
2
3 # Copyright (C) Catalyst.Net Ltd 2019
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18 """
19 Manage dependencies and bootstrap environments for Samba.
20
21 CLI script to build/tag/push docker images.
22
23 Author: Joe Guo <joeg@catalyst.net.nz>
24 """
25
26 import io
27 import os
28 import argparse
29 import logging
30 from os import environ
31 from datetime import date
32 from multiprocessing import Pool
33 from subprocess import check_call
34 from config import DISTS
35
36 logging.basicConfig(level='INFO')
37 log = logging.getLogger(__file__)
38
39 PREFIX_DEFAULT = environ.get('SAMBA_DOCKER_IMAGE_NAME_PREFIX', '')
40
41
42 def run(cmd, cwd=None):
43     # check_call will print to stdout while check_output will not
44     log.info('run cmd: %s', cmd)
45     check_call(cmd.split(), cwd=cwd)
46
47
48 def docker_image_name(prefix='', dist='ubuntu1604', tag='latest'):
49     """
50     Format docker image name.
51
52     Example output:
53     latest: samba-ubuntu1604:latest
54     date: samba-ubuntu1604:20190210
55     docker hub: samba-team/samba-ubuntu:latest
56     gitlab: registry.gitlab.com/samba-team/samba/samba-ubuntu1604:20190401
57     """
58     assert dist, 'dist name is required'
59     if prefix:
60         prefix = prefix + '/'
61
62     name = 'samba-' + dist
63
64     # if empty, use date as tag
65     if not tag:
66         tag = date.today().strftime('%Y%m%d')
67     tag = ':' + tag
68
69     return prefix + name + tag
70
71
72 def docker_build(dist_config):
73     cmd = 'docker build --rm -t {} {}'.format(
74         docker_image_name(dist=dist_config['name']),
75         dist_config['home'])
76     run(cmd)
77
78
79 class Docker(object):
80
81     def __init__(self, dists):
82         self.dists = dists
83
84     def build(self):
85         """Build images in process pool"""
86         with Pool(len(self.dists)) as pool:
87             pool.map(docker_build, self.dists.values())
88         run('docker image prune --force')
89
90     def tag(self, prefix):
91         """Tag images with prefixed and both a latest and date tag"""
92         for dist in self.dists:
93             name = docker_image_name(dist=dist)
94             # wil use date for empty tag
95             for tag in ['', 'latest']:
96                 prefixed = docker_image_name(prefix=prefix,
97                                              dist=dist,
98                                              tag=tag)
99                 cmd = 'docker tag {} {}'.format(name, prefixed)
100                 run(cmd)
101         run('docker image prune --force')
102
103     def push(self, prefix):
104         """Push prefixed docker images to registry with latest and date tag"""
105         for dist in self.dists:
106             # wil use date for empty tag
107             for tag in ['', 'latest']:
108                 prefixed = docker_image_name(prefix=prefix,
109                                              dist=dist,
110                                              tag=tag)
111                 cmd = 'docker push {}'.format(prefixed)
112                 run(cmd)
113
114
115 def main():
116     parser = argparse.ArgumentParser(
117         formatter_class=argparse.ArgumentDefaultsHelpFormatter,
118         description='Render samba docker images for multiple distributions.')
119
120     parser.add_argument(
121         '-b', '--build', action='store_true',
122         help='Build docker images')
123
124     parser.add_argument(
125         '-t', '--tag', action='store_true',
126         help='Tag docker images with --prefix')
127
128     parser.add_argument(
129         '-p', '--push', action='store_true',
130         help='Push docker images with --prefix, requires docker login')
131
132     parser.add_argument(
133         '--prefix', default=PREFIX_DEFAULT,
134         help=('Docker image name prefix, used with --tag and --push. '
135               'defaults to $SAMBA_DOCKER_IMAGE_NAME_PREFIX when defined. '
136               'Example: registry.gitlab.com/samba-team/samba'))
137
138     args = parser.parse_args()
139     if args.tag or args.push:
140         if not args.prefix:
141             parser.error('--prefix must be provided with --tag and --push')
142
143     docker = Docker(DISTS)
144
145     need_help = True
146
147     if args.build:
148         need_help = False
149         docker.build()
150
151     if args.tag or args.push:
152         need_help = False
153         docker.tag(args.prefix)
154
155     if args.push:
156         need_help = False
157         docker.push(args.prefix)
158
159     if need_help:
160         parser.print_help()
161
162
163 if __name__ == '__main__':
164     main()