summaryrefslogtreecommitdiffstats
path: root/tests/packaging/test_packaging.py
diff options
context:
space:
mode:
authorOto Šťáva <oto.stava@nic.cz>2023-06-22 09:43:18 +0200
committerOto Šťáva <oto.stava@nic.cz>2023-06-22 09:52:42 +0200
commit892fb5fd2a38ad633b73fd93204cb4a1f01a66cc (patch)
tree9dd9c0b38fa7bdd148ff0f3359fdd17658889696 /tests/packaging/test_packaging.py
parentdaemon: move connected flag from session to worker (diff)
parentMerge !1416: docker: minor fixes (diff)
downloadknot-resolver-892fb5fd2a38ad633b73fd93204cb4a1f01a66cc.tar.xz
knot-resolver-892fb5fd2a38ad633b73fd93204cb4a1f01a66cc.zip
Merge remote-tracking branch 'origin/6.0' into daemon-refactor-2
Diffstat (limited to 'tests/packaging/test_packaging.py')
-rw-r--r--tests/packaging/test_packaging.py494
1 files changed, 0 insertions, 494 deletions
diff --git a/tests/packaging/test_packaging.py b/tests/packaging/test_packaging.py
deleted file mode 100644
index 1a9bc413..00000000
--- a/tests/packaging/test_packaging.py
+++ /dev/null
@@ -1,494 +0,0 @@
-# SPDX-License-Identifier: GPL-3.0-or-later
-
-import os
-import pytest
-import docker
-import logging
-from pathlib import Path
-from abc import ABC, abstractmethod
-
-
-logging.basicConfig(level=logging.INFO)
-logger = logging.getLogger(__name__)
-logger.setLevel(logging.DEBUG)
-client = docker.from_env()
-
-
-class DockerCmdError(Exception):
- """ Raised when shell command in Docker container failed """
- pass
-
-
-class ContainerHandler():
- def __init__(self, image):
- self.img_id = image
- self.container = None
-
- def run(self):
- self.container = client.containers.run(self.img_id, network_mode='host',
- tty=True, detach=True)
- logger.info('Run container ID={}'.format(self.container))
-
- def stop(self):
- self.container.kill()
-
- def exec_cmd(self, cmd, workdir):
- # workaround: When exec_run is called in GitLab CI/CD workdir argument doesn't work.
- inter_cmd = ''
- if workdir is not None:
- inter_cmd = 'cd {}; '.format(workdir)
-
- rcode, out = self.container.exec_run('/bin/sh -c \'' + inter_cmd + cmd + '\'')
- if rcode != 0:
- raise DockerCmdError(rcode, out)
-
- def getFiles(self, output, path):
- strm, stat = self.container.get_archive(path)
- with open(output, 'wb') as ofile:
- for data in strm:
- ofile.write(data)
-
-
-class DockerImages(ABC):
- def __init__(self, version):
- self.version = version
- self.module = None
- self.distro = None
- self.build_id = None
- self.run_id = None
-
- @abstractmethod
- def cmd_pkgs_install(self):
- raise NotImplementedError
-
- @abstractmethod
- def cmd_kresd_install(self):
- raise NotImplementedError
-
- @abstractmethod
- def cmd_kresd_build(self):
- raise NotImplementedError
-
- def readDependencies(self, deps_file):
- """Read dependencies from file"""
- listf = None
- try:
- with open(deps_file, 'r') as f:
- listf = f.read().splitlines()
- except FileNotFoundError:
- pass
-
- return listf
-
- def __genDockerFile(self, path, from_image=None):
- """Generate Dockerfile for build image"""
- if self.module is None:
- raise AttributeError
-
- if from_image is None:
- if os.path.isfile(os.path.join(self.module, self.distro, 'docker-image-name')):
- with open(os.path.join(self.module, self.distro, 'docker-image-name')) as f:
- from_image = f.read()
- else:
- from_image = '{0}:{1}'.format(self.distro, self.version)
-
- distro_dir = os.path.join(self.module, self.distro, self.version)
-
- dockerf = open(os.path.join(path, 'Dockerfile-build'), 'w')
-
- dockerf.write('FROM {}\n'.format(from_image))
- dockerf.write('WORKDIR /root/kresd\n')
- if self.module == 'daemon/.packaging':
- dockerf.write('COPY . /root/kresd\n')
- # when this file doesn't exists, tzdata needs user interaction
- dockerf.write('RUN if [ ! -f /etc/localtime ];' +
- 'then ln -fs /usr/share/zoneinfo/Europe/Prague /etc/localtime; fi\n')
- if os.path.isfile(os.path.join(distro_dir, 'pre-build.sh')):
- dockerf.write('RUN {}\n'.format(os.path.join(distro_dir, 'pre-build.sh')))
- if os.path.isfile(os.path.join(distro_dir, 'builddeps')):
- dockerf.write('RUN {0} {1}\n'.format(self.cmd_pkgs_install(),
- ' '.join(self.readDependencies(os.path.join(distro_dir, 'builddeps')))))
- if os.path.isfile(os.path.join(distro_dir, 'build.sh')):
- dockerf.write('RUN {}\n'.format(os.path.join(distro_dir, 'build.sh')))
- else:
- dockerf.write('RUN {}\n'.format(self.cmd_kresd_build()))
- if os.path.isfile(os.path.join(distro_dir, 'install.sh')):
- dockerf.write('RUN {}\n'.format(os.path.join(distro_dir, 'install.sh')))
- else:
- dockerf.write('RUN {}\n'.format(self.cmd_kresd_install()))
- if os.path.isfile(os.path.join(distro_dir, 'post-build.sh')):
- dockerf.write('RUN {}\n'.format(os.path.join(distro_dir, 'post-build.sh')))
-
- dockerf.close()
-
- def __genDockerFile_run(self, path, build_id, from_image=None):
- """Generate Dockerfile for run image"""
- if self.module is None:
- raise AttributeError
-
- if from_image is None:
- if os.path.isfile(os.path.join(self.module, self.distro, 'docker-image-name')):
- with open(os.path.join(self.module, self.distro, 'docker-image-name')) as f:
- from_image = f.read()
- else:
- from_image = '{0}:{1}'.format(self.distro, self.version)
-
- distro_dir = os.path.join(self.module, self.distro, self.version)
-
- dockerf = open(os.path.join(path, 'Dockerfile-run'), 'w')
-
- dockerf.write('FROM {}\n'.format(from_image))
- dockerf.write('COPY --from={} /root/kresd /root/kresd\n'.format(build_id))
- dockerf.write('WORKDIR /root/kresd\n')
- if os.path.isfile(os.path.join(distro_dir, 'pre-run.sh')):
- dockerf.write('RUN {}\n'.format(os.path.join(distro_dir, 'pre-run.sh')))
- if os.path.isfile(os.path.join(distro_dir, 'rundeps')):
- dockerf.write('RUN {0} {1}\n'.format(self.cmd_pkgs_install(),
- ' '.join(self.readDependencies(os.path.join(distro_dir, 'rundeps')))))
- if os.path.isfile(os.path.join(distro_dir, 'pre-test.sh')):
- dockerf.write('RUN {}\n'.format(os.path.join(distro_dir, 'pre-test.sh')))
-
- dockerf.close()
-
- def build_printing_errors(self, path, dockerfile, network_mode, tag, rm):
- try:
- return client.images.build(path=path, dockerfile=dockerfile,
- network_mode=network_mode, tag=tag, rm=rm)
- except docker.errors.BuildError as e:
- iterable = iter(e.build_log)
- while True:
- try:
- item = next(iterable)
- if item['stream']:
- for l in item['stream'].splitlines():
- stripped = l.strip()
- if stripped:
- logging.error(stripped)
- except StopIteration:
- break
- raise e
-
- def build(self, tmpdir, tag="", from_image=None):
- self.__genDockerFile(tmpdir, from_image=from_image)
-
- logger.debug('tmpdir={}'.format(tmpdir))
- logger.debug('datadir={}'.format(pytest.KR_ROOT_DIR))
- logger.debug('tag={}'.format(tag))
- image = self.build_printing_errors(path=str(pytest.KR_ROOT_DIR),
- dockerfile=os.path.join(tmpdir, 'Dockerfile-build'),
- network_mode='host', tag=tag, rm=True)
- logger.info('"Build image" ID={} created'.format(image[0].short_id))
- self.build_id = image[0].short_id
- return self.build_id
-
- def build_run(self, tmpdir, build_id, from_image=None, tag=""):
- self.__genDockerFile_run(tmpdir, build_id, from_image=from_image)
-
- logger.debug('tmpdir={}'.format(tmpdir))
- logger.debug('datadir={}'.format(tmpdir))
- logger.debug('tag={}'.format(tag))
- image = self.build_printing_errors(path=str(tmpdir),
- dockerfile=os.path.join(tmpdir, 'Dockerfile-run'),
- network_mode='host', tag=tag, rm=True)
- logger.info('"Run image" ID={} created'.format(image[0].short_id))
- self.run_id = image[0].short_id
- return self.run_id
-
-
-class DebianImage(DockerImages):
- def __init__(self, version):
- super().__init__(version)
- self.distro = 'debian'
-
- def cmd_pkgs_install(self):
- return 'apt-get install -y '
-
- def cmd_kresd_install(self):
- return 'ninja -C build_packaging install >/dev/null'
-
- def cmd_kresd_build(self):
- return """\\
- [ -d /root/kresd/build_packaging ] && rm -rf /root/kresd/build_packaging/; \\
- CFLAGS=\"$CFLAGS -Wall -pedantic -fno-omit-frame-pointer\"; \\
- LDFLAGS=\"$LDFLAGS -Wl,--as-needed\"; \\
- meson build_packaging \\
- --buildtype=plain \\
- --prefix=/root/kresd/install_packaging \\
- --libdir=lib \\
- --default-library=static \\
- -Dsystemd_files=enabled \\
- -Dclient=enabled \\
- -Dkeyfile_default=/usr/share/dns/root.key \\
- -Droot_hints=/usr/share/dns/root.hints \\
- -Dinstall_kresd_conf=enabled \\
- -Dunit_tests=enabled \\
- -Dc_args=\"${CFLAGS}\" \\
- -Dc_link_args=\"${LDFLAGS}\"; \\
- ninja -C build_packaging
- """
-
-
-class UbuntuImage(DebianImage):
- def __init__(self, version):
- super().__init__(version)
- self.distro = 'ubuntu'
-
-
-class CentosImage(DockerImages):
- def __init__(self, version):
- super().__init__(version)
- self.distro = 'centos'
-
- def cmd_pkgs_install(self):
- return "yum install -y "
-
- def cmd_kresd_install(self):
- return 'ninja-build -C build_packaging install'
-
- def cmd_kresd_build(self):
- return """\\
- [ -d /root/kresd/build_packaging ] && rm -rf /root/kresd/build_packaging/; \\
- CFLAGS=\"$CFLAGS -Wall -pedantic -fno-omit-frame-pointer\"; \\
- LDFLAGS=\"$LDFLAGS -Wl,--as-needed\"; \\
- meson build_packaging \\
- --buildtype=plain \\
- --prefix=/root/kresd/install_packaging \\
- --sbindir=sbin \\
- --libdir=lib \\
- --includedir=include \\
- --sysconfdir=etc \\
- --default-library=static \\
- -Dsystemd_files=enabled \\
- -Dclient=enabled \\
- -Dunit_tests=enabled \\
- -Dmanaged_ta=enabled \\
- -Dkeyfile_default=/root/kresd/install_packaging/var/lib/knot-resolver/root.keys \\
- -Dinstall_root_keys=enabled \\
- -Dinstall_kresd_conf=enabled; \\
- ninja-build -C build_packaging
- """
-
-
-class FedoraImage(DockerImages):
- def __init__(self, version):
- super().__init__(version)
- self.distro = 'fedora'
-
- def cmd_pkgs_install(self):
- return "dnf install -y "
-
- def cmd_kresd_install(self):
- return 'ninja -C build_packaging install >/dev/null'
-
- def cmd_kresd_build(self):
- return """\\
- [ -d /root/kresd/build_packaging ] && rm -rf /root/kresd/build_packaging/; \\
- CFLAGS=\"$CFLAGS -Wall -pedantic -fno-omit-frame-pointer\"; \\
- LDFLAGS=\"$LDFLAGS -Wl,--as-needed\"; \\
- meson build_packaging \\
- --buildtype=plain \\
- --prefix=/root/kresd/install_packaging \\
- --sbindir=sbin \\
- --libdir=lib \\
- --includedir=include \\
- --sysconfdir=etc \\
- --default-library=static \\
- -Dsystemd_files=enabled \\
- -Dclient=enabled \\
- -Dunit_tests=enabled \\
- -Dmanaged_ta=enabled \\
- -Dkeyfile_default=/root/kresd/install_packaging/var/lib/knot-resolver/root.keys \\
- -Dinstall_root_keys=enabled \\
- -Dinstall_kresd_conf=enabled; \\
- ninja -C build_packaging
- """
-
-
-class LeapImage(FedoraImage):
- def __init__(self, version):
- super().__init__(version)
- self.distro = 'leap'
-
- def cmd_pkgs_install(self):
- return "zypper install -y "
-
-
-def create_distro_image(name, version):
- img = None
-
- if (name == 'debian'):
- img = DebianImage(version)
- elif (name == 'ubuntu'):
- img = UbuntuImage(version)
- elif (name == 'centos'):
- img = CentosImage(version)
- elif (name == 'fedora'):
- img = FedoraImage(version)
- elif (name == 'leap'):
- img = LeapImage(version)
- else:
- img = None
-
- return img
-
-
-def list_dirs(path, exclude=None):
- """return all 'packaging' directories with full path"""
- filtered_dirs = []
-
- for rootpath, dirs, _ in os.walk(path):
-
- if (os.path.basename(rootpath) == '.packaging'):
- fdir = os.path.relpath(rootpath, path)
- if exclude is not None:
- if fdir not in exclude:
- filtered_dirs.append(fdir)
- else:
- filtered_dirs.append(fdir)
-
- return filtered_dirs
-
-
-def list_tests_dirs():
- """return all 'packaging' directories"""
- return list_dirs(pytest.KR_ROOT_DIR)
-
-
-def list_distro_vers(distro_root):
- """
- return list of { 'name': distro_name, 'version': distro_version)
- pairs found in distro_root
- """
- # transform list of paths like TOP/debian/10 into (debian, 10)
- dist_ver = [{'name': p.parts[-2], 'version': p.parts[-1]} for p
- in Path(distro_root).glob('*/*') if p.is_dir()]
-
- return list(dist_ver)
-
-
-MODULES = list_tests_dirs()
-DISTROS = list_distro_vers(os.path.join(pytest.KR_ROOT_DIR, 'daemon/.packaging'))
-DISTROS_NAMES = ['{0}_{1}'.format(distro['name'], distro['version']) for distro in DISTROS]
-
-
-@pytest.fixture(scope='session', params=DISTROS, ids=DISTROS_NAMES)
-def buildenv(request, tmpdir_factory):
- distro = request.param
-
- logger.debug('Creating main images for "{0} {1}"'.format(distro['name'], distro['version']))
- img = create_distro_image(distro['name'], distro['version'])
- if img is None:
- logger.warning('Unknown distro {}'.format(distro['name']))
- else:
- img.module = 'daemon/.packaging'
- tmpdir = tmpdir_factory.mktemp(distro['name']+distro['version'])
- img.build(tmpdir, tag=pytest.KR_PREFIX+distro['name']+distro['version']+'-build')
- img.build_run(tmpdir, img.build_id,
- tag=pytest.KR_PREFIX+distro['name']+distro['version']+'-run')
-
- yield img
-# client.images.remove(img.run_id)
-# client.images.remove(img.build_id)
-
-
-@pytest.mark.parametrize('module', MODULES)
-def test_collect(module, buildenv, tmp_path):
- logger.info(' ### Run test {} ###'.format(module))
-
- if buildenv is None:
- logger.error('Distro "{0} {1}" isn\'t implemented'.format(buildenv.distro,
- buildenv.version))
- assert False
-
- rcode = None
- buildmod = None
- module_dir = os.path.join(pytest.KR_ROOT_DIR, module)
- distro_dir = os.path.join(module_dir, buildenv.distro, buildenv.version)
-
- if os.path.isfile(os.path.join(distro_dir, 'NOTSUPPORTED')):
- pytest.skip('Unsupported linux distribution ({0} {1}:{2})'.format(buildenv.distro, buildenv.version, module))
-
- try:
- if module == 'daemon/.packaging':
- # use main "run image" without changes
- logging.info('Use main "run image"')
- ch = ContainerHandler(buildenv.run_id)
- ch.run()
- elif buildenv is not None:
- if os.path.isfile(os.path.join(distro_dir, 'pre-build.sh')) \
- or os.path.isfile(os.path.join(distro_dir, 'builddeps')):
- # create module specific "build image"
- logger.info('Create new "build image"')
- buildmod = create_distro_image(buildenv.distro, buildenv.version)
- buildmod.module = module
- buildmod.build(tmp_path, from_image=buildenv.build_id,
- tag=pytest.KR_PREFIX+buildmod.distro+buildmod.version+'-' +
- module.replace('/.packaging', '')+'-build')
-
- if buildmod is not None:
- # new build image was made, create new module specific "run image"
- logger.info('Create module specific "run image" from Dockerfile')
- buildmod.build_run(tmp_path, buildmod.build_id,
- tag=pytest.KR_PREFIX+buildmod.distro+buildmod.version+'-' +
- module.replace('/.packaging', '')+'-run', from_image=buildenv.run_id)
- ch = ContainerHandler(buildmod.run_id)
- ch.run()
- elif os.path.isfile(os.path.join(distro_dir, 'pre-run.sh')) \
- or os.path.isfile(os.path.join(distro_dir, 'rundeps')):
- # use main "run image" and apply module specific changes
- logger.info('Apply module specific changes to "run image"')
- buildmod = buildenv
- ch = ContainerHandler(buildmod.run_id)
- ch.run()
-
- if os.path.isfile(os.path.join(distro_dir, 'pre-run.sh')):
- ch.exec_cmd(os.path.join(module, buildenv.distro, buildenv.version,
- 'pre-run.sh'), '/root/kresd/')
-
- if os.path.isfile(os.path.join(distro_dir, 'rundeps')):
- logger.debug(buildmod.cmd_pkgs_install() + ' '.join(
- buildmod.readDependencies(os.path.join(distro_dir, 'rundeps'))))
- ch.exec_cmd(buildmod.cmd_pkgs_install() + ' '.join(
- buildmod.readDependencies(os.path.join(distro_dir, 'rundeps'))),
- '/root/kresd/')
-
- if os.path.isfile(os.path.join(distro_dir, 'pre-test.sh')):
- ch.exec_cmd(os.path.join(module, buildenv.distro, buildenv.version,
- 'pre-test.sh'), '/root/kresd/')
- else:
- # use main "run image" without changes
- logging.info('Use main "run image"')
- ch = ContainerHandler(buildenv.run_id)
- ch.run()
-
- # run test
- if os.path.isfile(os.path.join(module_dir, 'test.config')):
- ch.exec_cmd('/root/kresd/install_packaging/sbin/kresd -n -c ' + os.path.join('..',
- module, 'test.config'), '/root/kresd/install_packaging/')
- elif os.path.isfile(os.path.join(module_dir, 'test.sh')):
- ch.exec_cmd(os.path.join('..', module, 'test.sh'),
- '/root/kresd/install_packaging/')
- else:
- ch.stop()
- ch.container.remove()
- logger.error('Test file (test.config or test.sh) not found')
- assert False
-
- rcode = 0
-
- if os.path.isfile(os.path.join(distro_dir, 'post-run.sh')):
- ch.exec_cmd(os.path.join(module, buildenv.distro, buildenv.version, 'post-run.sh'),
- '/root/kresd/')
-
- except DockerCmdError as err:
- rcode, out = err.args
- logger.debug('rcode: {}'.format(rcode))
- logger.error(out.decode('utf-8'))
- finally:
- ch.stop()
- ch.container.remove()
- if buildmod is not None and buildmod is not buildenv:
- client.images.remove(buildmod.run_id)
- client.images.remove(buildmod.build_id)
-
- assert(rcode == 0)