diff options
author | Oto Šťáva <oto.stava@nic.cz> | 2023-06-22 09:43:18 +0200 |
---|---|---|
committer | Oto Šťáva <oto.stava@nic.cz> | 2023-06-22 09:52:42 +0200 |
commit | 892fb5fd2a38ad633b73fd93204cb4a1f01a66cc (patch) | |
tree | 9dd9c0b38fa7bdd148ff0f3359fdd17658889696 /tests/packaging/test_packaging.py | |
parent | daemon: move connected flag from session to worker (diff) | |
parent | Merge !1416: docker: minor fixes (diff) | |
download | knot-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.py | 494 |
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) |