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