s3: tests: Add new test_stream_dir_rename.sh test.
[Samba.git] / bootstrap / config.py
blobd2ad4503430faf8cd7278ac0eafd471915a9470d
1 #!/usr/bin/env python3
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/>.
18 """
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>
27 """
28 import os
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
36 COMMON = [
37 'acl',
38 'attr',
39 'autoconf',
40 'binutils',
41 'bison',
42 'ccache',
43 'curl',
44 'chrpath',
45 'flex',
46 'gcc',
47 'gdb',
48 'git',
49 'gzip',
50 'hostname',
51 'htop',
52 'jq',
53 'lcov',
54 'make',
55 'patch',
56 'perl',
57 'psmisc', # for pstree in test
58 'rng-tools',
59 'rsync',
60 'sed',
61 'sudo', # docker images has no sudo by default
62 'tar',
63 'tree',
64 'wget',
68 # define pkgs for all packaging systems in parallel
69 # make it easier to find missing ones
70 # use latest ubuntu and fedora as defaults
71 # deb, rpm, ...
72 PKGS = [
73 # NAME1-dev, NAME2-devel
74 ('lmdb-utils', 'lmdb'),
75 ('mingw-w64', 'mingw64-gcc'),
76 ('zlib1g-dev', 'zlib-devel'),
77 ('libbsd-dev', 'libbsd-devel'),
78 ('liburing-dev', 'liburing-devel'),
79 ('libarchive-dev', 'libarchive-devel'),
80 ('libblkid-dev', 'libblkid-devel'),
81 ('libcap-dev', 'libcap-devel'),
82 ('libacl1-dev', 'libacl-devel'),
83 ('libattr1-dev', 'libattr-devel'),
85 # libNAME1-dev, NAME2-devel
86 ('libpopt-dev', 'popt-devel'),
87 ('libreadline-dev', 'readline-devel'),
88 ('libjansson-dev', 'jansson-devel'),
89 ('liblmdb-dev', 'lmdb-devel'),
90 ('libncurses5-dev', 'ncurses-devel'),
91 # NOTE: Debian 7+ or Ubuntu 16.04+
92 ('libsystemd-dev', 'systemd-devel'),
93 ('libkrb5-dev', 'krb5-devel'),
94 ('libldap2-dev', 'openldap-devel'),
95 ('libcups2-dev', 'cups-devel'),
96 ('libpam0g-dev', 'pam-devel'),
97 ('libgpgme11-dev', 'gpgme-devel'),
98 # NOTE: Debian 8+ and Ubuntu 14.04+
99 ('libgnutls28-dev', 'gnutls-devel'),
100 ('libtasn1-bin', 'libtasn1-tools'),
101 ('libtasn1-dev', 'libtasn1-devel'),
102 ('', 'quota-devel'),
103 ('uuid-dev', 'libuuid-devel'),
104 ('libjs-jquery', ''),
105 ('libavahi-common-dev', 'avahi-devel'),
106 ('libdbus-1-dev', 'dbus-devel'),
107 ('libpcap-dev', 'libpcap-devel'),
108 ('libunwind-dev', 'libunwind-devel'), # for back trace
109 ('libglib2.0-dev', 'glib2-devel'),
110 ('libicu-dev', 'libicu-devel'),
111 ('heimdal-multidev', ''),
113 # NAME1, NAME2
114 # for debian, locales provide locale support with language packs
115 # ubuntu split language packs to language-pack-xx
116 # for centos, glibc-common provide locale support with language packs
117 # fedora split language packs to glibc-langpack-xx
118 ('locales', 'glibc-common'), # required for locale
119 ('language-pack-en', 'glibc-langpack-en'), # we need en_US.UTF-8
120 ('bind9utils', 'bind-utils'),
121 ('dnsutils', ''),
122 ('xsltproc', 'libxslt'),
123 ('krb5-user', 'krb5-workstation'),
124 ('krb5-config', ''),
125 ('krb5-kdc', 'krb5-server'),
126 ('apt-utils', 'yum-utils'),
127 ('pkg-config', 'pkgconfig'),
128 ('procps', 'procps-ng'), # required for the free cmd in tests
129 ('lsb-release', 'lsb-release'), # we need lsb_release to show info
130 ('', 'rpcgen'), # required for test
131 # refer: https://fedoraproject.org/wiki/Changes/SunRPCRemoval
132 ('', 'libtirpc-devel'), # for <rpc/rpc.h> header on fedora
133 ('', 'rpcsvc-proto-devel'), # for <rpcsvc/rquota.h> header
134 ('mawk', 'gawk'),
135 ('', 'mold'),
136 ('', 'ShellCheck'),
137 ('', 'shfmt'),
139 ('python3', 'python3'),
140 ('python3-cryptography', 'python3-cryptography'), # for krb5 tests
141 ('python3-dev', 'python3-devel'),
142 ('python3-dbg', ''),
143 ('python3-iso8601', 'python3-iso8601'),
144 ('python3-gpg', 'python3-gpg'), # defaults to ubuntu/fedora latest
145 ('python3-markdown', 'python3-markdown'),
146 ('python3-dnspython', 'python3-dns'),
147 ('python3-pexpect', ''), # for wintest only
148 ('python3-pyasn1', 'python3-pyasn1'), # for krb5 tests
149 ('python3-setproctitle', 'python3-setproctitle'),
150 ('python3-requests', 'python3-requests'), # for cert auto enroll
152 ('', 'python3-libsemanage'),
153 ('', 'python3-policycoreutils'),
155 # perl
156 ('libparse-yapp-perl', 'perl-Parse-Yapp'),
157 ('libjson-perl', 'perl-JSON'),
158 ('', 'perl-JSON-Parse'),
159 ('perl-modules', ''),
160 ('', 'perl-FindBin'),
161 ('', 'perl-Archive-Tar'),
162 ('', 'perl-ExtUtils-MakeMaker'),
163 ('', 'perl-Test-Base'),
164 ('', 'perl-generators'),
165 ('', 'perl-interpreter'),
167 # fs
168 ('xfslibs-dev', 'xfsprogs-devel'), # for xfs quota support
169 ('', 'glusterfs-api-devel'),
170 ('glusterfs-common', 'glusterfs-devel'),
171 ('libcephfs-dev', 'libcephfs-devel'),
173 # spotlight
174 ('libtracker-sparql-2.0-dev', 'tracker-devel'),
176 # misc
177 # @ means group for rpm, use fedora as rpm default
178 ('build-essential', '@development-tools'),
179 ('debhelper', ''),
180 # rpm has no pkg for docbook-xml
181 ('docbook-xml', 'docbook-dtds'),
182 ('docbook-xsl', 'docbook-style-xsl'),
183 ('', 'keyutils-libs-devel'),
184 ('', 'which'),
185 ('xz-utils', 'xz')
189 DEB_PKGS = COMMON + [pkg for pkg, _ in PKGS if pkg]
190 RPM_PKGS = COMMON + [pkg for _, pkg in PKGS if pkg]
192 GENERATED_MARKER = r"""
194 # This file is generated by 'bootstrap/template.py --render'
195 # See also bootstrap/config.py
200 APT_BOOTSTRAP = r"""
201 #!/bin/bash
202 {GENERATED_MARKER}
203 set -xueo pipefail
205 export DEBIAN_FRONTEND=noninteractive
206 apt-get -y update
208 apt-get -y install \
209 {pkgs}
211 apt-get -y autoremove
212 apt-get -y autoclean
213 apt-get -y clean
217 YUM_BOOTSTRAP = r"""
218 #!/bin/bash
219 {GENERATED_MARKER}
220 set -xueo pipefail
222 yum update -y
223 yum install -y epel-release
224 yum install -y yum-plugin-copr
225 yum copr enable -y sergiomb/SambaAD
226 yum update -y
228 yum install -y \
229 {pkgs}
231 yum clean all
233 if [ ! -f /usr/bin/python3 ]; then
234 ln -sf /usr/bin/python3.6 /usr/bin/python3
238 CENTOS8S_YUM_BOOTSTRAP = r"""
239 #!/bin/bash
240 {GENERATED_MARKER}
241 set -xueo pipefail
243 yum update -y
244 yum install -y dnf-plugins-core
245 yum install -y epel-release
247 yum -v repolist all
248 yum config-manager --set-enabled powertools -y
250 yum update -y
252 yum install -y \
253 --setopt=install_weak_deps=False \
254 {pkgs}
256 yum clean all
259 DNF_BOOTSTRAP = r"""
260 #!/bin/bash
261 {GENERATED_MARKER}
262 set -xueo pipefail
264 dnf update -y
266 dnf install -y \
267 --setopt=install_weak_deps=False \
268 {pkgs}
270 dnf clean all
273 DNF_BOOTSTRAP_MIT = r"""
274 #!/bin/bash
275 {GENERATED_MARKER}
276 set -xueo pipefail
278 dnf update -y
279 dnf install -y dnf-plugins-core
280 dnf copr -y enable abbra/krb5-test
281 dnf update -y
283 dnf install -y \
284 --setopt=install_weak_deps=False \
285 {pkgs}
287 dnf clean all
290 ZYPPER_BOOTSTRAP = r"""
291 #!/bin/bash
292 {GENERATED_MARKER}
293 set -xueo pipefail
295 zypper --non-interactive refresh
296 zypper --non-interactive update
297 zypper --non-interactive install \
298 --no-recommends \
299 system-user-nobody \
300 {pkgs}
302 zypper --non-interactive clean
304 if [ -f /usr/lib/mit/bin/krb5-config ]; then
305 ln -sf /usr/lib/mit/bin/krb5-config /usr/bin/krb5-config
309 # A generic shell script to setup locale
310 LOCALE_SETUP = r"""
311 #!/bin/bash
312 {GENERATED_MARKER}
313 set -xueo pipefail
315 # refer to /usr/share/i18n/locales
316 INPUTFILE=en_US
317 # refer to /usr/share/i18n/charmaps
318 CHARMAP=UTF-8
319 # locale to generate in /usr/lib/locale
320 # glibc/localedef will normalize UTF-8 to utf8, follow the naming style
321 LOCALE=$INPUTFILE.utf8
323 # if locale is already correct, exit
324 ( locale | grep LC_ALL | grep -i $LOCALE ) && exit 0
326 # if locale not available, generate locale into /usr/lib/locale
327 if ! ( locale --all-locales | grep -i $LOCALE )
328 then
329 # no-archive means create its own dir
330 localedef --inputfile $INPUTFILE --charmap $CHARMAP --no-archive $LOCALE
333 # update locale conf and global env file
334 # set both LC_ALL and LANG for safe
336 # update conf for Debian family
337 FILE=/etc/default/locale
338 if [ -f $FILE ]
339 then
340 echo LC_ALL="$LOCALE" > $FILE
341 echo LANG="$LOCALE" >> $FILE
344 # update conf for RedHat family
345 FILE=/etc/locale.conf
346 if [ -f $FILE ]
347 then
348 # LC_ALL is not valid in this file, set LANG only
349 echo LANG="$LOCALE" > $FILE
352 # update global env file
353 FILE=/etc/environment
354 if [ -f $FILE ]
355 then
356 # append LC_ALL if not exist
357 grep LC_ALL $FILE || echo LC_ALL="$LOCALE" >> $FILE
358 # append LANG if not exist
359 grep LANG $FILE || echo LANG="$LOCALE" >> $FILE
364 DOCKERFILE = r"""
365 {GENERATED_MARKER}
366 FROM {docker_image}
368 # pass in with --build-arg while build
369 ARG SHA1SUM
370 RUN [ -n $SHA1SUM ] && echo $SHA1SUM > /sha1sum.txt
372 ADD *.sh /tmp/
373 # need root permission, do it before USER samba
374 RUN /tmp/bootstrap.sh && /tmp/locale.sh
376 # if ld.gold exists, force link it to ld
377 RUN set -x; ! LD_GOLD=$(which ld.gold) || {{ LD=$(which ld) && ln -sf $LD_GOLD $LD && test -x $LD && echo "$LD is now $LD_GOLD"; }}
378 # if ld.mold exists, force link it to ld (prefer mold over gold! ;-)
379 RUN set -x; ! LD_MOLD=$(which ld.mold) || {{ LD=$(which ld) && ln -sf $LD_MOLD $LD && test -x $LD && echo "$LD is now $LD_MOLD"; }}
381 # make test can not work with root, so we have to create a new user
382 RUN useradd -m -U -s /bin/bash samba && \
383 mkdir -p /etc/sudoers.d && \
384 echo "samba ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/samba
386 USER samba
387 WORKDIR /home/samba
388 # samba tests rely on this
389 ENV USER=samba LC_ALL=en_US.utf8 LANG=en_US.utf8
392 # Vagrantfile snippet for each dist
393 VAGRANTFILE_SNIPPET = r"""
394 config.vm.define "{name}" do |v|
395 v.vm.box = "{vagrant_box}"
396 v.vm.hostname = "{name}"
397 v.vm.provision :shell, path: "{name}/bootstrap.sh"
398 v.vm.provision :shell, path: "{name}/locale.sh"
402 # global Vagrantfile with snippets for all dists
403 VAGRANTFILE_GLOBAL = r"""
404 {GENERATED_MARKER}
406 Vagrant.configure("2") do |config|
407 config.ssh.insert_key = false
409 {vagrantfile_snippets}
415 DEB_DISTS = {
416 'debian11': {
417 'docker_image': 'debian:11',
418 'vagrant_box': 'debian/bullseye64',
419 'replace': {
420 'language-pack-en': '', # included in locales
423 'ubuntu1804': {
424 'docker_image': 'ubuntu:18.04',
425 'vagrant_box': 'ubuntu/bionic64',
426 'replace': {
427 'liburing-dev': '', # not available
430 'ubuntu1804-32bit': {
431 'docker_image': 'registry-1.docker.io/i386/ubuntu:18.04',
432 'vagrant_box': 'ubuntu/bionic32',
433 'replace': {
434 'liburing-dev': '', # not available
437 'ubuntu2004': {
438 'docker_image': 'ubuntu:20.04',
439 'vagrant_box': 'ubuntu/focal64',
440 'replace': {
441 'liburing-dev': '', # not available
444 'ubuntu2204': {
445 'docker_image': 'ubuntu:22.04',
446 'vagrant_box': 'ubuntu/jammy64',
447 'replace': {
448 'libtracker-sparql-2.0-dev': '', # only tracker 3.x is available
454 RPM_DISTS = {
455 'centos7': {
456 'docker_image': 'centos:7',
457 'vagrant_box': 'centos/7',
458 'bootstrap': YUM_BOOTSTRAP,
459 'replace': {
460 'lsb-release': 'redhat-lsb',
461 'python3': 'python36',
462 'python3-cryptography': 'python36-cryptography',
463 'python3-devel': 'python36-devel',
464 'python3-dns': 'python36-dns',
465 'python3-pyasn1': 'python36-pyasn1',
466 'python3-gpg': 'python36-gpg',
467 'python3-iso8601' : 'python36-iso8601',
468 'python3-markdown': 'python36-markdown',
469 'python3-requests': 'python36-requests',
470 # although python36-devel is available
471 # after epel-release installed
472 # however, all other python3 pkgs are still python36-ish
473 'python2-gpg': 'pygpgme',
474 '@development-tools': '"@Development Tools"', # add quotes
475 'glibc-langpack-en': '', # included in glibc-common
476 'glibc-locale-source': '', # included in glibc-common
477 # update perl core modules on centos
478 # fix: Can't locate Archive/Tar.pm in @INC
479 'perl': 'perl-core',
480 'perl-FindBin': '',
481 'rpcsvc-proto-devel': '',
482 'glusterfs-api-devel': '',
483 'glusterfs-devel': '',
484 'libcephfs-devel': '',
485 'gnutls-devel': 'compat-gnutls37-devel',
486 'liburing-devel': '', # not available
487 'python3-setproctitle': 'python36-setproctitle',
488 'tracker-devel': '', # do not install
489 'mold': '',
490 'ShellCheck': '',
491 'shfmt': '',
494 'centos8s': {
495 'docker_image': 'quay.io/centos/centos:stream8',
496 'vagrant_box': 'centos/stream8',
497 'bootstrap': CENTOS8S_YUM_BOOTSTRAP,
498 'replace': {
499 'lsb-release': 'redhat-lsb',
500 '@development-tools': '"@Development Tools"', # add quotes
501 'lcov': '', # does not exist
502 'perl-JSON-Parse': '', # does not exist?
503 'perl-Test-Base': 'perl-Test-Simple',
504 'perl-FindBin': '',
505 'liburing-devel': '', # not available yet, Add me back, once available!
506 'mold': '',
507 'ShellCheck': '',
508 'shfmt': '',
511 'fedora37': {
512 'docker_image': 'quay.io/fedora/fedora:37',
513 'vagrant_box': 'fedora/37-cloud-base',
514 'bootstrap': DNF_BOOTSTRAP,
515 'replace': {
516 'lsb-release': 'redhat-lsb',
517 'perl-FindBin': '',
518 'python3-iso8601': 'python3-dateutil',
519 'libtracker-sparql-2.0-dev': '', # only tracker 3.x is available
522 'f37mit120': {
523 'docker_image': 'quay.io/fedora/fedora:37',
524 'vagrant_box': 'fedora/37-cloud-base',
525 'bootstrap': DNF_BOOTSTRAP_MIT,
526 'replace': {
527 'lsb-release': 'redhat-lsb',
528 'perl-FindBin': '',
529 'python3-iso8601': 'python3-dateutil',
530 'libtracker-sparql-2.0-dev': '', # only tracker 3.x is available
533 'opensuse154': {
534 'docker_image': 'opensuse/leap:15.4',
535 'vagrant_box': 'opensuse/openSUSE-15.4-x86_64',
536 'bootstrap': ZYPPER_BOOTSTRAP,
537 'replace': {
538 '@development-tools': '',
539 'dbus-devel': 'dbus-1-devel',
540 'docbook-style-xsl': 'docbook-xsl-stylesheets',
541 'glibc-common': 'glibc-locale',
542 'glibc-locale-source': 'glibc-i18ndata',
543 'glibc-langpack-en': '',
544 'jansson-devel': 'libjansson-devel',
545 'keyutils-libs-devel': 'keyutils-devel',
546 'krb5-workstation': 'krb5-client',
547 'python3-libsemanage': 'python3-semanage',
548 'openldap-devel': 'openldap2-devel',
549 'perl-Archive-Tar': 'perl-Archive-Tar-Wrapper',
550 'perl-JSON-Parse': 'perl-JSON-XS',
551 'perl-generators': '',
552 'perl-interpreter': '',
553 'perl-FindBin': '',
554 'procps-ng': 'procps',
555 'python3-iso8601': 'python3-python-dateutil',
556 'python3-dns': 'python3-dnspython',
557 'python3-markdown': 'python3-Markdown',
558 'quota-devel': '',
559 'glusterfs-api-devel': '',
560 'libtasn1-tools': '', # asn1Parser is part of libtasn1
561 'mold': '',
562 'shfmt': '',
563 'yum-utils': '',
569 DEB_FAMILY = {
570 'name': 'deb',
571 'pkgs': DEB_PKGS,
572 'bootstrap': APT_BOOTSTRAP, # family default
573 'dists': DEB_DISTS,
577 RPM_FAMILY = {
578 'name': 'rpm',
579 'pkgs': RPM_PKGS,
580 'bootstrap': YUM_BOOTSTRAP, # family default
581 'dists': RPM_DISTS,
585 YML_HEADER = r"""
587 packages:
591 def expand_family_dists(family):
592 dists = {}
593 for name, config in family['dists'].items():
594 config = config.copy()
595 config['name'] = name
596 config['home'] = join(OUT, name)
597 config['family'] = family['name']
598 config['GENERATED_MARKER'] = GENERATED_MARKER
600 # replace dist specific pkgs
601 replace = config.get('replace', {})
602 pkgs = []
603 for pkg in family['pkgs']:
604 pkg = replace.get(pkg, pkg) # replace if exists or get self
605 if pkg:
606 pkgs.append(pkg)
607 pkgs.sort()
609 lines = [' - {}'.format(pkg) for pkg in pkgs]
610 config['packages.yml'] = YML_HEADER.lstrip() + os.linesep.join(lines)
612 sep = ' \\' + os.linesep + ' '
613 config['pkgs'] = sep.join(pkgs)
615 # get dist bootstrap template or fall back to family default
616 bootstrap_template = config.get('bootstrap', family['bootstrap'])
617 config['bootstrap.sh'] = bootstrap_template.format(**config).strip()
618 config['locale.sh'] = LOCALE_SETUP.format(**config).strip()
620 config['Dockerfile'] = DOCKERFILE.format(**config).strip()
621 # keep the indent, no strip
622 config['vagrantfile_snippet'] = VAGRANTFILE_SNIPPET.format(**config)
624 dists[name] = config
625 return dists
628 # expanded config for dists
629 DEB_DISTS_EXP = expand_family_dists(DEB_FAMILY)
630 RPM_DISTS_EXP = expand_family_dists(RPM_FAMILY)
632 # assemble all together
633 DISTS = {}
634 DISTS.update(DEB_DISTS_EXP)
635 DISTS.update(RPM_DISTS_EXP)
638 def render_vagrantfile(dists):
640 Render all snippets for each dist into global Vagrantfile.
642 Vagrant supports multiple vms in one Vagrantfile.
643 This make it easier to manage the fleet, e.g:
645 start all: vagrant up
646 start one: vagrant up ubuntu1804
648 All other commands apply to above syntax, e.g.: status, destroy, provision
650 # sort dists by name and put all vagrantfile snippets together
651 snippets = [
652 dists[dist]['vagrantfile_snippet']
653 for dist in sorted(dists.keys())]
655 return VAGRANTFILE_GLOBAL.format(
656 vagrantfile_snippets=''.join(snippets),
657 GENERATED_MARKER=GENERATED_MARKER
661 VAGRANTFILE = render_vagrantfile(DISTS)
664 # data we need to expose
665 __all__ = ['DISTS', 'VAGRANTFILE', 'OUT']