3 # Copyright (C) Catalyst.Net Ltd 2019
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.
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.
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/>.
19 Manage dependencies and bootstrap environments for Samba.
21 Config file for packages and templates.
23 Update the lists in this file to require new packages in the
24 container images used in GitLab CI
26 Author: Joe Guo <joeg@catalyst.net.nz>
29 from os.path import abspath, dirname, join
30 HERE = abspath(dirname(__file__))
31 # output dir for rendered files
32 OUT = join(HERE, 'generated-dists')
35 # pkgs with same name in all packaging systems
56 'psmisc', # for pstree in test
60 'sudo', # docker images has no sudo by default
67 # define pkgs for all packaging systems in parallel
68 # make it easier to find missing ones
69 # use latest ubuntu and fedora as defaults
72 # NAME1-dev, NAME2-devel
73 ('lmdb-utils', 'lmdb'),
74 ('mingw-w64', 'mingw64-gcc'),
75 ('zlib1g-dev', 'zlib-devel'),
76 ('libbsd-dev', 'libbsd-devel'),
77 ('liburing-dev', 'liburing-devel'),
78 ('libarchive-dev', 'libarchive-devel'),
79 ('libblkid-dev', 'libblkid-devel'),
80 ('libcap-dev', 'libcap-devel'),
81 ('libacl1-dev', 'libacl-devel'),
82 ('libattr1-dev', 'libattr-devel'),
84 # libNAME1-dev, NAME2-devel
85 ('libpopt-dev', 'popt-devel'),
86 ('libreadline-dev', 'readline-devel'),
87 ('libjansson-dev', 'jansson-devel'),
88 ('liblmdb-dev', 'lmdb-devel'),
89 ('libncurses5-dev', 'ncurses-devel'),
90 # NOTE: Debian 7+ or Ubuntu 16.04+
91 ('libsystemd-dev', 'systemd-devel'),
92 ('libkrb5-dev', 'krb5-devel'),
93 ('libldap2-dev', 'openldap-devel'),
94 ('libcups2-dev', 'cups-devel'),
95 ('libpam0g-dev', 'pam-devel'),
96 ('libgpgme11-dev', 'gpgme-devel'),
97 # NOTE: Debian 8+ and Ubuntu 14.04+
98 ('libgnutls28-dev', 'gnutls-devel'),
99 ('libtasn1-bin', 'libtasn1-tools'),
100 ('libtasn1-dev', 'libtasn1-devel'),
102 ('uuid-dev', 'libuuid-devel'),
103 ('libjs-jquery', ''),
104 ('libavahi-common-dev', 'avahi-devel'),
105 ('libdbus-1-dev', 'dbus-devel'),
106 ('libpcap-dev', 'libpcap-devel'),
107 ('libunwind-dev', 'libunwind-devel'), # for back trace
108 ('libglib2.0-dev', 'glib2-devel'),
109 ('libicu-dev', 'libicu-devel'),
110 ('heimdal-multidev', ''),
113 # for debian, locales provide locale support with language packs
114 # ubuntu split language packs to language-pack-xx
115 # for centos, glibc-common provide locale support with language packs
116 # fedora split language packs to glibc-langpack-xx
117 ('locales', 'glibc-common'), # required for locale
118 ('language-pack-en', 'glibc-langpack-en'), # we need en_US.UTF-8
119 ('bind9utils', 'bind-utils'),
121 ('xsltproc', 'libxslt'),
122 ('krb5-user', 'krb5-workstation'),
124 ('krb5-kdc', 'krb5-server'),
125 ('apt-utils', 'yum-utils'),
126 ('pkg-config', 'pkgconfig'),
127 ('procps', 'procps-ng'), # required for the free cmd in tests
128 ('lsb-release', 'lsb-release'), # we need lsb_relase to show info
129 ('', 'rpcgen'), # required for test
130 # refer: https://fedoraproject.org/wiki/Changes/SunRPCRemoval
131 ('', 'libtirpc-devel'), # for <rpc/rpc.h> header on fedora
132 ('', 'rpcsvc-proto-devel'), # for <rpcsvc/rquota.h> header
136 ('python3', 'python3'),
137 ('python3-cryptography', 'python3-cryptography'), # for krb5 tests
138 ('python3-dev', 'python3-devel'),
140 ('python3-iso8601', 'python3-iso8601'),
141 ('python3-gpg', 'python3-gpg'), # defaults to ubuntu/fedora latest
142 ('python3-markdown', 'python3-markdown'),
143 ('python3-dnspython', 'python3-dns'),
144 ('python3-pexpect', ''), # for wintest only
145 ('python3-pyasn1', 'python3-pyasn1'), # for krb5 tests
146 ('python3-setproctitle', 'python3-setproctitle'),
147 ('python3-requests', 'python3-requests'), # for cert auto enroll
149 ('', 'python3-libsemanage'),
150 ('', 'python3-policycoreutils'),
153 ('libparse-yapp-perl', 'perl-Parse-Yapp'),
154 ('libjson-perl', 'perl-JSON'),
155 ('', 'perl-JSON-Parse'),
156 ('perl-modules', ''),
157 ('', 'perl-FindBin'),
158 ('', 'perl-Archive-Tar'),
159 ('', 'perl-ExtUtils-MakeMaker'),
160 ('', 'perl-Test-Base'),
161 ('', 'perl-generators'),
162 ('', 'perl-interpreter'),
165 ('xfslibs-dev', 'xfsprogs-devel'), # for xfs quota support
166 ('', 'glusterfs-api-devel'),
167 ('glusterfs-common', 'glusterfs-devel'),
168 ('libcephfs-dev', 'libcephfs-devel'),
171 ('libtracker-sparql-2.0-dev', 'tracker-devel'),
174 # @ means group for rpm, use fedora as rpm default
175 ('build-essential', '@development-tools'),
177 # rpm has no pkg for docbook-xml
178 ('docbook-xml', 'docbook-dtds'),
179 ('docbook-xsl', 'docbook-style-xsl'),
180 ('', 'keyutils-libs-devel'),
185 DEB_PKGS = COMMON + [pkg for pkg, _ in PKGS if pkg]
186 RPM_PKGS = COMMON + [pkg for _, pkg in PKGS if pkg]
188 GENERATED_MARKER = r"""
190 # This file is generated by 'bootstrap/template.py --render'
191 # See also bootstrap/config.py
201 export DEBIAN_FRONTEND=noninteractive
207 apt-get -y autoremove
219 yum install -y epel-release
220 yum install -y yum-plugin-copr
221 yum copr enable -y sergiomb/SambaAD
229 if [ ! -f /usr/bin/python3 ]; then
230 ln -sf /usr/bin/python3.6 /usr/bin/python3
234 CENTOS8S_YUM_BOOTSTRAP = r"""
240 yum install -y dnf-plugins-core
241 yum install -y epel-release
244 yum config-manager --set-enabled powertools -y || \
245 yum config-manager --set-enabled powertools -y
250 --setopt=install_weak_deps=False \
264 --setopt=install_weak_deps=False \
270 DNF_BOOTSTRAP_MIT = r"""
276 dnf install -y dnf-plugins-core
277 dnf copr -y enable abbra/krb5-test
281 --setopt=install_weak_deps=False \
287 ZYPPER_BOOTSTRAP = r"""
292 zypper --non-interactive refresh
293 zypper --non-interactive update
294 zypper --non-interactive install \
299 zypper --non-interactive clean
301 if [ -f /usr/lib/mit/bin/krb5-config ]; then
302 ln -sf /usr/lib/mit/bin/krb5-config /usr/bin/krb5-config
306 # A generic shell script to setup locale
312 # refer to /usr/share/i18n/locales
314 # refer to /usr/share/i18n/charmaps
316 # locale to generate in /usr/lib/locale
317 # glibc/localedef will normalize UTF-8 to utf8, follow the naming style
318 LOCALE=$INPUTFILE.utf8
320 # if locale is already correct, exit
321 ( locale | grep LC_ALL | grep -i $LOCALE ) && exit 0
323 # if locale not available, generate locale into /usr/lib/locale
324 if ! ( locale --all-locales | grep -i $LOCALE )
326 # no-archive means create its own dir
327 localedef --inputfile $INPUTFILE --charmap $CHARMAP --no-archive $LOCALE
330 # update locale conf and global env file
331 # set both LC_ALL and LANG for safe
333 # update conf for Debian family
334 FILE=/etc/default/locale
337 echo LC_ALL="$LOCALE" > $FILE
338 echo LANG="$LOCALE" >> $FILE
341 # update conf for RedHat family
342 FILE=/etc/locale.conf
345 # LC_ALL is not valid in this file, set LANG only
346 echo LANG="$LOCALE" > $FILE
349 # update global env file
350 FILE=/etc/environment
353 # append LC_ALL if not exist
354 grep LC_ALL $FILE || echo LC_ALL="$LOCALE" >> $FILE
355 # append LANG if not exist
356 grep LANG $FILE || echo LANG="$LOCALE" >> $FILE
365 # pass in with --build-arg while build
367 RUN [ -n $SHA1SUM ] && echo $SHA1SUM > /sha1sum.txt
370 # need root permission, do it before USER samba
371 RUN /tmp/bootstrap.sh && /tmp/locale.sh
373 # if ld.gold exists, force link it to ld
374 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"
375 # if ld.mold exists, force link it to ld (prefer mold over gold! ;-)
376 RUN set -x; LD=$(which ld); LD_MOLD=$(which ld.mold); test -x $LD_MOLD && ln -sf $LD_MOLD $LD && test -x $LD && echo "$LD is now $LD_MOLD"
378 # make test can not work with root, so we have to create a new user
379 RUN useradd -m -U -s /bin/bash samba && \
380 mkdir -p /etc/sudoers.d && \
381 echo "samba ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/samba
385 # samba tests rely on this
386 ENV USER=samba LC_ALL=en_US.utf8 LANG=en_US.utf8
389 # Vagrantfile snippet for each dist
390 VAGRANTFILE_SNIPPET = r"""
391 config.vm.define "{name}" do |v|
392 v.vm.box = "{vagrant_box}"
393 v.vm.hostname = "{name}"
394 v.vm.provision :shell, path: "{name}/bootstrap.sh"
395 v.vm.provision :shell, path: "{name}/locale.sh"
399 # global Vagrantfile with snippets for all dists
400 VAGRANTFILE_GLOBAL = r"""
403 Vagrant.configure("2") do |config|
404 config.ssh.insert_key = false
406 {vagrantfile_snippets}
414 'docker_image': 'debian:11',
415 'vagrant_box': 'debian/bullseye64',
417 'language-pack-en': '', # included in locales
421 'docker_image': 'ubuntu:18.04',
422 'vagrant_box': 'ubuntu/bionic64',
424 'liburing-dev': '', # not available
428 'docker_image': 'ubuntu:20.04',
429 'vagrant_box': 'ubuntu/focal64',
431 'liburing-dev': '', # not available
439 'docker_image': 'centos:7',
440 'vagrant_box': 'centos/7',
441 'bootstrap': YUM_BOOTSTRAP,
443 'lsb-release': 'redhat-lsb',
444 'python3': 'python36',
445 'python3-cryptography': 'python36-cryptography',
446 'python3-devel': 'python36-devel',
447 'python3-dns': 'python36-dns',
448 'python3-pyasn1': 'python36-pyasn1',
449 'python3-gpg': 'python36-gpg',
450 'python3-iso8601' : 'python36-iso8601',
451 'python3-markdown': 'python36-markdown',
452 'python3-requests': 'python36-requests',
453 # although python36-devel is available
454 # after epel-release installed
455 # however, all other python3 pkgs are still python36-ish
456 'python2-gpg': 'pygpgme',
457 'python3-gpg': '', # no python3-gpg yet
458 '@development-tools': '"@Development Tools"', # add quotes
459 'glibc-langpack-en': '', # included in glibc-common
460 'glibc-locale-source': '', # included in glibc-common
461 # update perl core modules on centos
462 # fix: Can't locate Archive/Tar.pm in @INC
465 'rpcsvc-proto-devel': '',
466 'glusterfs-api-devel': '',
467 'glusterfs-devel': '',
468 'libcephfs-devel': '',
469 'gnutls-devel': 'compat-gnutls37-devel',
470 'liburing-devel': '', # not available
471 'python3-setproctitle': 'python36-setproctitle',
472 'tracker-devel': '', # do not install
477 'docker_image': 'quay.io/centos/centos:stream8',
478 'vagrant_box': 'centos/stream8',
479 'bootstrap': CENTOS8S_YUM_BOOTSTRAP,
481 'lsb-release': 'redhat-lsb',
482 '@development-tools': '"@Development Tools"', # add quotes
483 'lcov': '', # does not exist
484 'perl-JSON-Parse': '', # does not exist?
485 'perl-Test-Base': 'perl-Test-Simple',
487 'liburing-devel': '', # not available yet, Add me back, once available!
492 'docker_image': 'fedora:36',
493 'vagrant_box': 'fedora/36-cloud-base',
494 'bootstrap': DNF_BOOTSTRAP,
496 'lsb-release': 'redhat-lsb',
498 'python3-iso8601': 'python3-dateutil',
499 'libtracker-sparql-2.0-dev': '', # only tracker 3.x is available
503 'docker_image': 'fedora:36',
504 'vagrant_box': 'fedora/36-cloud-base',
505 'bootstrap': DNF_BOOTSTRAP_MIT,
507 'lsb-release': 'redhat-lsb',
509 'python3-iso8601': 'python3-dateutil',
510 'libtracker-sparql-2.0-dev': '', # only tracker 3.x is available
514 'docker_image': 'opensuse/leap:15.3',
515 'vagrant_box': 'opensuse/openSUSE-15.3-x86_64',
516 'bootstrap': ZYPPER_BOOTSTRAP,
518 '@development-tools': '',
519 'dbus-devel': 'dbus-1-devel',
520 'docbook-style-xsl': 'docbook-xsl-stylesheets',
521 'glibc-common': 'glibc-locale',
522 'glibc-locale-source': 'glibc-i18ndata',
523 'glibc-langpack-en': '',
524 'jansson-devel': 'libjansson-devel',
525 'keyutils-libs-devel': 'keyutils-devel',
526 'krb5-workstation': 'krb5-client',
527 'python3-libsemanage': 'python2-semanage',
528 'openldap-devel': 'openldap2-devel',
529 'perl-Archive-Tar': 'perl-Archive-Tar-Wrapper',
530 'perl-JSON-Parse': 'perl-JSON-XS',
531 'perl-generators': '',
532 'perl-interpreter': '',
534 'procps-ng': 'procps',
535 'python3-iso8601': 'python3-python-dateutil',
536 'python3-dns': 'python3-dnspython',
537 'python3-markdown': 'python3-Markdown',
539 'glusterfs-api-devel': '',
540 'libtasn1-tools': '', # asn1Parser is part of libtasn1
550 'bootstrap': APT_BOOTSTRAP, # family default
558 'bootstrap': YUM_BOOTSTRAP, # family default
569 def expand_family_dists(family):
571 for name, config in family['dists'].items():
572 config = config.copy()
573 config['name'] = name
574 config['home'] = join(OUT, name)
575 config['family'] = family['name']
576 config['GENERATED_MARKER'] = GENERATED_MARKER
578 # replace dist specific pkgs
579 replace = config.get('replace', {})
581 for pkg in family['pkgs']:
582 pkg = replace.get(pkg, pkg) # replace if exists or get self
587 lines = [' - {}'.format(pkg) for pkg in pkgs]
588 config['packages.yml'] = YML_HEADER.lstrip() + os.linesep.join(lines)
590 sep = ' \\' + os.linesep + ' '
591 config['pkgs'] = sep.join(pkgs)
593 # get dist bootstrap template or fall back to family default
594 bootstrap_template = config.get('bootstrap', family['bootstrap'])
595 config['bootstrap.sh'] = bootstrap_template.format(**config).strip()
596 config['locale.sh'] = LOCALE_SETUP.format(**config).strip()
598 config['Dockerfile'] = DOCKERFILE.format(**config).strip()
599 # keep the indent, no strip
600 config['vagrantfile_snippet'] = VAGRANTFILE_SNIPPET.format(**config)
606 # expanded config for dists
607 DEB_DISTS_EXP = expand_family_dists(DEB_FAMILY)
608 RPM_DISTS_EXP = expand_family_dists(RPM_FAMILY)
610 # assemble all together
612 DISTS.update(DEB_DISTS_EXP)
613 DISTS.update(RPM_DISTS_EXP)
616 def render_vagrantfile(dists):
618 Render all snippets for each dist into global Vagrantfile.
620 Vagrant supports multiple vms in one Vagrantfile.
621 This make it easier to manage the fleet, e.g:
623 start all: vagrant up
624 start one: vagrant up ubuntu1804
626 All other commands apply to above syntax, e.g.: status, destroy, provision
628 # sort dists by name and put all vagrantfile snippets together
630 dists[dist]['vagrantfile_snippet']
631 for dist in sorted(dists.keys())]
633 return VAGRANTFILE_GLOBAL.format(
634 vagrantfile_snippets=''.join(snippets),
635 GENERATED_MARKER=GENERATED_MARKER
639 VAGRANTFILE = render_vagrantfile(DISTS)
642 # data we need to expose
643 __all__ = ['DISTS', 'VAGRANTFILE', 'OUT']