bootstrap: Remove nettle-devel from package list
[metze/samba-autobuild/.git] / bootstrap / config.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 Config file for packages and templates.
22
23 Author: Joe Guo <joeg@catalyst.net.nz>
24 """
25 import os
26 from os.path import abspath, dirname, join
27 HERE = abspath(dirname(__file__))
28 # output dir for rendered files
29 OUT = join(HERE, 'generated-dists')
30
31
32 # pkgs with same name in all packaging systems
33 COMMON = [
34     'acl',
35     'attr',
36     'autoconf',
37     'binutils',
38     'bison',
39     'curl',
40     'flex',
41     'gcc',
42     'gdb',
43     'git',
44     'gzip',
45     'hostname',
46     'htop',
47     'lcov',
48     'make',
49     'patch',
50     'perl',
51     'psmisc',  # for pstree in test
52     'rng-tools',
53     'rsync',
54     'sed',
55     'sudo',  # docker images has no sudo by default
56     'tar',
57     'tree',
58 ]
59
60
61 # define pkgs for all packaging systems in parallel
62 # make it easier to find missing ones
63 # use latest ubuntu and fedora as defaults
64 # deb, rpm, ...
65 PKGS = [
66     # NAME1-dev, NAME2-devel
67     ('lmdb-utils', 'lmdb'),
68     ('mingw-w64', 'mingw64-gcc'),
69     ('zlib1g-dev', 'zlib-devel'),
70     ('libbsd-dev', 'libbsd-devel'),
71     ('libaio-dev', 'libaio-devel'),
72     ('libarchive-dev', 'libarchive-devel'),
73     ('libblkid-dev', 'libblkid-devel'),
74     ('libcap-dev', 'libcap-devel'),
75     ('libacl1-dev', 'libacl-devel'),
76     ('libattr1-dev', 'libattr-devel'),
77
78     # libNAME1-dev, NAME2-devel
79     ('libpopt-dev', 'popt-devel'),
80     ('libreadline-dev', 'readline-devel'),
81     ('libjansson-dev', 'jansson-devel'),
82     ('liblmdb-dev', 'lmdb-devel'),
83     ('libncurses5-dev', 'ncurses-devel'),
84     # NOTE: Debian 7+ or Ubuntu 16.04+
85     ('libsystemd-dev', 'systemd-devel'),
86     ('libkrb5-dev', 'krb5-devel'),
87     ('libldap2-dev', 'openldap-devel'),
88     ('libcups2-dev', 'cups-devel'),
89     ('libpam0g-dev', 'pam-devel'),
90     ('libgpgme11-dev', 'gpgme-devel'),
91     # NOTE: Debian 8+ and Ubuntu 14.04+
92     ('libgnutls28-dev', 'gnutls-devel'),
93     ('libtasn1-bin', 'libtasn1-tools'),
94     ('libtasn1-dev', 'libtasn1-devel'),
95     ('', 'quota-devel'),
96     ('uuid-dev', 'libuuid-devel'),
97     ('libjs-jquery', ''),
98     ('libavahi-common-dev', 'avahi-devel'),
99     ('libdbus-1-dev', 'dbus-devel'),
100     ('libpcap-dev', 'libpcap-devel'),
101     ('libunwind-dev', 'libunwind-devel'),  # for back trace
102     ('libglib2.0-dev', 'glib2-devel'),
103     ('libicu-dev', 'libicu-devel'),
104
105     # NAME1, NAME2
106     # for debian, locales provide locale support with language packs
107     # ubuntu split language packs to language-pack-xx
108     # for centos, glibc-common provide locale support with language packs
109     # fedora split language packs  to glibc-langpack-xx
110     ('locales', 'glibc-common'),  # required for locale
111     ('language-pack-en', 'glibc-langpack-en'),  # we need en_US.UTF-8
112     ('bind9utils', 'bind-utils'),
113     ('dnsutils', ''),
114     ('xsltproc', 'libxslt'),
115     ('krb5-user', ''),
116     ('krb5-config', ''),
117     ('krb5-kdc', 'krb5-server'),
118     ('apt-utils', 'yum-utils'),
119     ('pkg-config', 'pkgconfig'),
120     ('procps', 'procps-ng'),  # required for the free cmd in tests
121     ('lsb-release', 'lsb-release'),  # we need lsb_relase to show info
122     ('', 'rpcgen'),  # required for test
123     # refer: https://fedoraproject.org/wiki/Changes/SunRPCRemoval
124     ('', 'libtirpc-devel'),  # for <rpc/rpc.h> header on fedora
125     ('', 'libnsl2-devel'),  # for <rpcsvc/yp_prot.h> header on fedora
126     ('', 'rpcsvc-proto-devel'), # for <rpcsvc/rquota.h> header
127     ('mawk', 'gawk'),
128
129     ('python3', 'python3'),
130     ('python3-dev', 'python3-devel'),
131     ('python3-dbg', ''),
132     ('python3-iso8601', ''),
133     ('python3-gpg', 'python3-gpg'),  # defaults to ubuntu/fedora latest
134     ('python3-crypto', 'python3-crypto'),
135     ('python3-markdown', 'python3-markdown'),
136     ('python3-matplotlib', ''),
137     ('python3-dnspython', 'python3-dns'),
138     ('python3-pexpect', ''),  # for wintest only
139
140     ('', 'libsemanage-python'),
141     ('', 'policycoreutils-python'),
142
143     # perl
144     ('libparse-yapp-perl', 'perl-Parse-Yapp'),
145     ('libjson-perl', 'perl-JSON-Parse'),
146     ('perl-modules', ''),
147     ('', 'perl-Archive-Tar'),
148     ('', 'perl-ExtUtils-MakeMaker'),
149     ('', 'perl-Test-Base'),
150     ('', 'perl-generators'),
151     ('', 'perl-interpreter'),
152
153     # fs
154     ('xfslibs-dev', 'xfsprogs-devel'), # for xfs quota support
155     ('', 'glusterfs-api-devel'),
156     ('glusterfs-common', 'glusterfs-devel'),
157     ('libcephfs-dev', 'libcephfs-devel'),
158
159     # misc
160     # @ means group for rpm, use fedora as rpm default
161     ('build-essential', '@development-tools'),
162     ('debhelper', ''),
163     # rpm has no pkg for docbook-xml
164     ('docbook-xml', 'docbook-dtds'),
165     ('docbook-xsl', 'docbook-style-xsl'),
166     ('', 'keyutils-libs-devel'),
167     ('', 'which'),
168 ]
169
170
171 DEB_PKGS = COMMON + [pkg for pkg, _ in PKGS if pkg]
172 RPM_PKGS = COMMON + [pkg for _, pkg in PKGS if pkg]
173
174 GENERATED_MARKER = r"""
175 #
176 # This file is generated by 'bootstrap/template.py --render'
177 # See also bootstrap/config.py
178 #
179 """
180
181
182 APT_BOOTSTRAP = r"""
183 #!/bin/bash
184 {GENERATED_MARKER}
185 set -xueo pipefail
186
187 export DEBIAN_FRONTEND=noninteractive
188 apt-get -y update
189
190 apt-get -y install \
191     {pkgs}
192
193 apt-get -y autoremove
194 apt-get -y autoclean
195 apt-get -y clean
196 """
197
198
199 YUM_BOOTSTRAP = r"""
200 #!/bin/bash
201 {GENERATED_MARKER}
202 set -xueo pipefail
203
204 yum update -y
205 yum install -y epel-release
206 yum install -y yum-plugin-copr
207 yum copr enable -y sergiomb/SambaAD
208 yum update -y
209
210 yum install -y \
211     {pkgs}
212
213 yum clean all
214
215 if [ ! -f /usr/bin/python3 ]; then
216     ln -sf /usr/bin/python3.6 /usr/bin/python3
217 fi
218 """
219
220 CENTOS8_YUM_BOOTSTRAP = r"""
221 #!/bin/bash
222 {GENERATED_MARKER}
223 set -xueo pipefail
224
225 yum update -y
226 yum install -y dnf-plugins-core
227 yum install -y epel-release
228 yum config-manager --set-enabled PowerTools -y
229 yum update -y
230
231 yum install -y \
232     --setopt=install_weak_deps=False \
233     {pkgs}
234
235 yum clean all
236 """
237
238 DNF_BOOTSTRAP = r"""
239 #!/bin/bash
240 {GENERATED_MARKER}
241 set -xueo pipefail
242
243 dnf update -y
244
245 dnf install -y \
246     --setopt=install_weak_deps=False \
247     {pkgs}
248
249 dnf clean all
250 """
251
252 ZYPPER_BOOTSTRAP = r"""
253 #!/bin/bash
254 {GENERATED_MARKER}
255 set -xueo pipefail
256
257 zypper --non-interactive refresh
258 zypper --non-interactive update
259 zypper --non-interactive install \
260     --no-recommends \
261     system-user-nobody \
262     {pkgs}
263
264 zypper --non-interactive clean
265
266 if [ -f /usr/lib/mit/bin/krb5-config ]; then
267     ln -sf /usr/lib/mit/bin/krb5-config /usr/bin/krb5-config
268 fi
269 """
270
271 # A generic shell script to setup locale
272 LOCALE_SETUP = r"""
273 #!/bin/bash
274 {GENERATED_MARKER}
275 set -xueo pipefail
276
277 # refer to /usr/share/i18n/locales
278 INPUTFILE=en_US
279 # refer to /usr/share/i18n/charmaps
280 CHARMAP=UTF-8
281 # locale to generate in /usr/lib/locale
282 # glibc/localedef will normalize UTF-8 to utf8, follow the naming style
283 LOCALE=$INPUTFILE.utf8
284
285 # if locale is already correct, exit
286 ( locale | grep LC_ALL | grep -i $LOCALE ) && exit 0
287
288 # if locale not available, generate locale into /usr/lib/locale
289 if ! ( locale --all-locales | grep -i $LOCALE )
290 then
291     # no-archive means create its own dir
292     localedef --inputfile $INPUTFILE --charmap $CHARMAP --no-archive $LOCALE
293 fi
294
295 # update locale conf and global env file
296 # set both LC_ALL and LANG for safe
297
298 # update conf for Debian family
299 FILE=/etc/default/locale
300 if [ -f $FILE ]
301 then
302     echo LC_ALL="$LOCALE" > $FILE
303     echo LANG="$LOCALE" >> $FILE
304 fi
305
306 # update conf for RedHat family
307 FILE=/etc/locale.conf
308 if [ -f $FILE ]
309 then
310     # LC_ALL is not valid in this file, set LANG only
311     echo LANG="$LOCALE" > $FILE
312 fi
313
314 # update global env file
315 FILE=/etc/environment
316 if [ -f $FILE ]
317 then
318     # append LC_ALL if not exist
319     grep LC_ALL $FILE || echo LC_ALL="$LOCALE" >> $FILE
320     # append LANG if not exist
321     grep LANG $FILE || echo LANG="$LOCALE" >> $FILE
322 fi
323 """
324
325
326 DOCKERFILE = r"""
327 {GENERATED_MARKER}
328 FROM {docker_image}
329
330 # pass in with --build-arg while build
331 ARG SHA1SUM
332 RUN [ -n $SHA1SUM ] && echo $SHA1SUM > /sha1sum.txt
333
334 ADD *.sh /tmp/
335 # need root permission, do it before USER samba
336 RUN /tmp/bootstrap.sh && /tmp/locale.sh
337
338 # if ld.gold exists, force link it to ld
339 RUN set -x; LD=$(which ld); LD_GOLD=$(which ld.gold); test -x $LD_GOLD && ln -sf $LD_GOLD $LD && test -x $LD && echo "$LD is now $LD_GOLD"
340
341 # make test can not work with root, so we have to create a new user
342 RUN useradd -m -U -s /bin/bash samba && \
343     mkdir -p /etc/sudoers.d && \
344     echo "samba ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/samba
345
346 USER samba
347 WORKDIR /home/samba
348 # samba tests rely on this
349 ENV USER=samba LC_ALL=en_US.utf8 LANG=en_US.utf8
350 """
351
352 # Vagrantfile snippet for each dist
353 VAGRANTFILE_SNIPPET = r"""
354     config.vm.define "{name}" do |v|
355         v.vm.box = "{vagrant_box}"
356         v.vm.hostname = "{name}"
357         v.vm.provision :shell, path: "{name}/bootstrap.sh"
358         v.vm.provision :shell, path: "{name}/locale.sh"
359     end
360 """
361
362 # global Vagrantfile with snippets for all dists
363 VAGRANTFILE_GLOBAL = r"""
364 {GENERATED_MARKER}
365
366 Vagrant.configure("2") do |config|
367     config.ssh.insert_key = false
368
369 {vagrantfile_snippets}
370
371 end
372 """
373
374
375 DEB_DISTS = {
376     'debian7': {
377         'docker_image': 'debian:7',
378         'vagrant_box': 'debian/wheezy64',
379         'replace': {
380             'libgnutls28-dev': 'libgnutls-dev',
381             'libsystemd-dev': '',  # not available, remove
382             'lmdb-utils': '',  # not available, remove
383             'liblmdb-dev': '',  # not available, remove
384             'python-gpg': 'python-gpgme',
385             'python3-gpg': '',  # no python3 gpg pkg available, remove
386             'language-pack-en': '',   # included in locales
387         }
388     },
389     'debian8': {
390         'docker_image': 'debian:8',
391         'vagrant_box': 'debian/jessie64',
392         'replace': {
393             'python-gpg': 'python-gpgme',
394             'python3-gpg': 'python3-gpgme',
395             'language-pack-en': '',   # included in locales
396         }
397     },
398     'debian9': {
399         'docker_image': 'debian:9',
400         'vagrant_box': 'debian/stretch64',
401         'replace': {
402             'language-pack-en': '',   # included in locales
403         }
404     },
405     'ubuntu1404': {
406         'docker_image': 'ubuntu:14.04',
407         'vagrant_box': 'ubuntu/trusty64',
408         'replace': {
409             'libsystemd-dev': '',  # remove
410             'libgnutls28-dev': 'libgnutls-dev',
411             'python-gpg': 'python-gpgme',
412             'python3-gpg': 'python3-gpgme',
413             'lmdb-utils': 'lmdb-utils/trusty-backports',
414             'liblmdb-dev': 'liblmdb-dev/trusty-backports',
415             'libunwind-dev': 'libunwind8-dev',
416             'glusterfs-common': '',
417             'libcephfs-dev': '',
418         }
419     },
420     'ubuntu1604': {
421         'docker_image': 'ubuntu:16.04',
422         'vagrant_box': 'ubuntu/xenial64',
423         'replace': {
424             'python-gpg': 'python-gpgme',
425             'python3-gpg': 'python3-gpgme',
426             'glusterfs-common': '',
427             'libcephfs-dev': '',
428         }
429     },
430     'ubuntu1804': {
431         'docker_image': 'ubuntu:18.04',
432         'vagrant_box': 'ubuntu/bionic64',
433     },
434 }
435
436
437 RPM_DISTS = {
438     'centos6': {
439         'docker_image': 'centos:6',
440         'vagrant_box': 'centos/6',
441         'bootstrap': YUM_BOOTSTRAP,
442         'replace': {
443             'lsb-release': 'redhat-lsb',
444             'python3': 'python36',
445             'python3-devel': 'python36-devel',
446             'python2-gpg': 'pygpgme',
447             'python3-gpg': '',  # no python3-gpg yet
448             '@development-tools': '"@Development Tools"',  # add quotes
449             'glibc-langpack-en': '',  # included in glibc-common
450             'glibc-locale-source': '',  # included in glibc-common
451             'procps-ng': 'procps',  # centos6 still use old name
452             # update perl core modules on centos
453             # fix: Can't locate Archive/Tar.pm in @INC
454             'perl': 'perl-core',
455             'rpcsvc-proto-devel': '',
456             'glusterfs-api-devel': '',
457             'glusterfs-devel': '',
458             'libcephfs-devel': '',
459         }
460     },
461     'centos7': {
462         'docker_image': 'centos:7',
463         'vagrant_box': 'centos/7',
464         'bootstrap': YUM_BOOTSTRAP,
465         'replace': {
466             'lsb-release': 'redhat-lsb',
467             'python3': 'python36',
468             'python3-crypto': 'python36-crypto',
469             'python3-devel': 'python36-devel',
470             'python3-dns': 'python36-dns',
471             'python3-gpg': 'python36-gpg',
472             'python3-iso8601' : 'python36-iso8601',
473             'python3-markdown': 'python36-markdown',
474             # although python36-devel is available
475             # after epel-release installed
476             # however, all other python3 pkgs are still python36-ish
477             'python2-gpg': 'pygpgme',
478             'python3-gpg': '',  # no python3-gpg yet
479             '@development-tools': '"@Development Tools"',  # add quotes
480             'glibc-langpack-en': '',  # included in glibc-common
481             'glibc-locale-source': '',  # included in glibc-common
482             # update perl core modules on centos
483             # fix: Can't locate Archive/Tar.pm in @INC
484             'perl': 'perl-core',
485             'rpcsvc-proto-devel': '',
486             'glusterfs-api-devel': '',
487             'glusterfs-devel': '',
488             'libcephfs-devel': '',
489             'gnutls-devel': 'compat-gnutls34-devel',
490         }
491     },
492     'centos8': {
493         'docker_image': 'centos:8',
494         'vagrant_box': 'centos/8',
495         'bootstrap': CENTOS8_YUM_BOOTSTRAP,
496         'replace': {
497             'lsb-release': 'redhat-lsb',
498             '@development-tools': '"@Development Tools"',  # add quotes
499             'libsemanage-python': 'python3-libsemanage',
500             'lcov': '', # does not exist
501             'perl-JSON-Parse': '', # does not exist?
502             'perl-Test-Base': 'perl-Test-Simple',
503             'policycoreutils-python': 'python3-policycoreutils',
504             'python3-crypto': '',
505             'quota-devel': '', # FIXME: Add me back, once available!
506         }
507     },
508     'fedora29': {
509         'docker_image': 'fedora:29',
510         'vagrant_box': 'fedora/29-cloud-base',
511         'bootstrap': DNF_BOOTSTRAP,
512         'replace': {
513             'lsb-release': 'redhat-lsb',
514         }
515     },
516     'fedora30': {
517         'docker_image': 'fedora:30',
518         'vagrant_box': 'fedora/30-cloud-base',
519         'bootstrap': DNF_BOOTSTRAP,
520         'replace': {
521             'lsb-release': 'redhat-lsb',
522         }
523     },
524     'fedora31': {
525         'docker_image': 'fedora:31',
526         'vagrant_box': 'fedora/31-cloud-base',
527         'bootstrap': DNF_BOOTSTRAP,
528         'replace': {
529             'lsb-release': 'redhat-lsb',
530             'libsemanage-python': 'python3-libsemanage',
531             'policycoreutils-python': 'python3-policycoreutils',
532         }
533     },
534     'opensuse150': {
535         'docker_image': 'opensuse/leap:15.0',
536         'vagrant_box': 'opensuse/openSUSE-15.0-x86_64',
537         'bootstrap': ZYPPER_BOOTSTRAP,
538         'replace': {
539             '@development-tools': '',
540             'dbus-devel': 'dbus-1-devel',
541             'docbook-style-xsl': 'docbook-xsl-stylesheets',
542             'glibc-common': 'glibc-locale',
543             'glibc-locale-source': 'glibc-i18ndata',
544             'glibc-langpack-en': '',
545             'jansson-devel': 'libjansson-devel',
546             'keyutils-libs-devel': 'keyutils-devel',
547             'krb5-workstation': 'krb5-client',
548             'libnsl2-devel': 'libnsl-devel',
549             'libsemanage-python': 'python2-semanage',
550             'openldap-devel': 'openldap2-devel',
551             'perl-Archive-Tar': 'perl-Archive-Tar-Wrapper',
552             'perl-JSON-Parse': 'perl-JSON-XS',
553             'perl-generators': '',
554             'perl-interpreter': '',
555             'procps-ng': 'procps',
556             'python-dns': 'python2-dnspython',
557             'python3-crypto': 'python3-pycrypto',
558             'python3-dns': 'python3-dnspython',
559             'python3-markdown': 'python3-Markdown',
560             'quota-devel': '',
561             'glusterfs-api-devel': '',
562             'libtasn1-tools': '', # asn1Parser is part of libtasn1
563             'mingw64-gcc': '', # doesn't exist
564         }
565     },
566     'opensuse151': {
567         'docker_image': 'opensuse/leap:15.1',
568         'vagrant_box': 'opensuse/openSUSE-15.1-x86_64',
569         'bootstrap': ZYPPER_BOOTSTRAP,
570         'replace': {
571             '@development-tools': '',
572             'dbus-devel': 'dbus-1-devel',
573             'docbook-style-xsl': 'docbook-xsl-stylesheets',
574             'glibc-common': 'glibc-locale',
575             'glibc-locale-source': 'glibc-i18ndata',
576             'glibc-langpack-en': '',
577             'jansson-devel': 'libjansson-devel',
578             'keyutils-libs-devel': 'keyutils-devel',
579             'krb5-workstation': 'krb5-client',
580             'libnsl2-devel': 'libnsl-devel',
581             'libsemanage-python': 'python2-semanage',
582             'openldap-devel': 'openldap2-devel',
583             'perl-Archive-Tar': 'perl-Archive-Tar-Wrapper',
584             'perl-JSON-Parse': 'perl-JSON-XS',
585             'perl-generators': '',
586             'perl-interpreter': '',
587             'procps-ng': 'procps',
588             'python-dns': 'python2-dnspython',
589             'python3-crypto': 'python3-pycrypto',
590             'python3-dns': 'python3-dnspython',
591             'python3-markdown': 'python3-Markdown',
592             'quota-devel': '',
593             'glusterfs-api-devel': '',
594             'libtasn1-tools': '', # asn1Parser is part of libtasn1
595             'mingw64-gcc': '', # doesn't exist
596         }
597     }
598 }
599
600
601 DEB_FAMILY = {
602     'name': 'deb',
603     'pkgs': DEB_PKGS,
604     'bootstrap': APT_BOOTSTRAP,  # family default
605     'dists': DEB_DISTS,
606 }
607
608
609 RPM_FAMILY = {
610     'name': 'rpm',
611     'pkgs': RPM_PKGS,
612     'bootstrap': YUM_BOOTSTRAP,  # family default
613     'dists': RPM_DISTS,
614 }
615
616
617 YML_HEADER = r"""
618 ---
619 packages:
620 """
621
622
623 def expand_family_dists(family):
624     dists = {}
625     for name, config in family['dists'].items():
626         config = config.copy()
627         config['name'] = name
628         config['home'] = join(OUT, name)
629         config['family'] = family['name']
630         config['GENERATED_MARKER'] = GENERATED_MARKER
631
632         # replace dist specific pkgs
633         replace = config.get('replace', {})
634         pkgs = []
635         for pkg in family['pkgs']:
636             pkg = replace.get(pkg, pkg)  # replace if exists or get self
637             if pkg:
638                 pkgs.append(pkg)
639         pkgs.sort()
640
641         lines = ['  - {}'.format(pkg) for pkg in pkgs]
642         config['packages.yml'] = YML_HEADER.lstrip() + os.linesep.join(lines)
643
644         sep = ' \\' + os.linesep + '    '
645         config['pkgs'] = sep.join(pkgs)
646
647         # get dist bootstrap template or fall back to family default
648         bootstrap_template = config.get('bootstrap', family['bootstrap'])
649         config['bootstrap.sh'] = bootstrap_template.format(**config).strip()
650         config['locale.sh'] = LOCALE_SETUP.format(**config).strip()
651
652         config['Dockerfile'] = DOCKERFILE.format(**config).strip()
653         # keep the indent, no strip
654         config['vagrantfile_snippet'] = VAGRANTFILE_SNIPPET.format(**config)
655
656         dists[name] = config
657     return dists
658
659
660 # expanded config for dists
661 DEB_DISTS_EXP = expand_family_dists(DEB_FAMILY)
662 RPM_DISTS_EXP = expand_family_dists(RPM_FAMILY)
663
664 # assemble all together
665 DISTS = {}
666 DISTS.update(DEB_DISTS_EXP)
667 DISTS.update(RPM_DISTS_EXP)
668
669
670 def render_vagrantfile(dists):
671     """
672     Render all snippets for each dist into global Vagrantfile.
673
674     Vagrant supports multiple vms in one Vagrantfile.
675     This make it easier to manage the fleet, e.g:
676
677     start all: vagrant up
678     start one: vagrant up ubuntu1804
679
680     All other commands apply to above syntax, e.g.: status, destroy, provision
681     """
682     # sort dists by name and put all vagrantfile snippets together
683     snippets = [
684         dists[dist]['vagrantfile_snippet']
685         for dist in sorted(dists.keys())]
686
687     return VAGRANTFILE_GLOBAL.format(
688             vagrantfile_snippets=''.join(snippets),
689             GENERATED_MARKER=GENERATED_MARKER
690             )
691
692
693 VAGRANTFILE = render_vagrantfile(DISTS)
694
695
696 # data we need to expose
697 __all__ = ['DISTS', 'VAGRANTFILE', 'OUT']