Compare commits

..

1 commit

Author SHA1 Message Date
a8f43dbdd5 Unsupported 2019-02-12 22:37:48 +01:00
20 changed files with 1 additions and 2835 deletions

0
.gitignore vendored
View file

File diff suppressed because it is too large Load diff

1
dead.package Normal file
View file

@ -0,0 +1 @@
Unsupported

View file

@ -1,4 +0,0 @@
Autogenerated
enablement
Modularity
Runtime

View file

View file

@ -1,7 +0,0 @@
MODULE_LINT=/usr/share/moduleframework/tools/modulelint/*.py
CMD=MODULE=nspawn python -m avocado run smoke.py $(MODULE_LINT)
check:
$(CMD)
all: check

View file

@ -1,102 +0,0 @@
"""
get configuration parameters for base runtime smoke testing
"""
import os
import logging
from moduleframework import module_framework
def get_mockcfg(self):
"""
Get the path to the base runtime mock configuration file
This is provided by the avocado 'mockcfg' parameter if supplied,
otherwise it is set to "resources/base-runtime-mock.cfg" relative to
the test script directory.
"""
script_dir = os.path.abspath(os.path.dirname(__file__))
self.log.info("running script from directory: %s" % script_dir)
mockcfg = self.params.get('mockcfg', default=os.path.join(
script_dir, "resources", "base-runtime-mock.cfg"))
mockcfg = str(mockcfg)
if not mockcfg.endswith(".cfg"):
self.error("mock configuration file %s must have the extension '.cfg'" %
mockcfg)
if not os.path.isfile(mockcfg):
self.error("mock configuration file %s does not exist" %
mockcfg)
self.log.info("mock configuration file: %s" % mockcfg)
return mockcfg
def get_compiler_test_dir(self):
"""
Get the path to the base runtime compiler test resource directory
This is provided by the avocado 'compiler-test-dir' parameter if supplied,
otherwise it is set to "resources/hello-world" relative to
the test script directory.
"""
script_dir = os.path.abspath(os.path.dirname(__file__))
self.log.info("running script from directory: %s" % script_dir)
compdir = self.params.get(
'compiler-test-dir', default=os.path.join(script_dir, "resources", "hello-world"))
compdir = str(compdir)
if not os.path.isdir(compdir):
self.error("Compiler test resource directory %s does not exist" % compdir)
self.log.info("Compiler test resource directory: %s" % compdir)
return compdir
def get_docker_image_name(self):
"""
Get the name to use for the base runtime docker image
"""
container_helper = module_framework.ContainerHelper()
#It tries to get the name from URL env variable
#If URL is not defined it tries to get the name from config.yaml
image_name = container_helper.getDockerInstanceName()
if not image_name:
self.error("Could not find docker image name to use")
self.log.info("base runtime image name: %s" % image_name)
return image_name
def get_docker_labels(self):
"""
From config file get the labels that should be added to the image
"""
config = module_framework.get_config()
if not config:
self.error("Could not get config file")
if 'module' not in config.keys():
self.error("Config file does not have module section")
if 'docker' not in config['module'].keys():
self.error("Config file does not have docker module section")
docker_cfg = config['module']['docker']
if 'labels' not in docker_cfg.keys():
return None
return docker_cfg['labels']
def get_test_profile(self):
"""
From config file get the labels that should be added to the image
"""
return "container"

View file

@ -1,75 +0,0 @@
"""
cleanup docker container/images and mock root for smoke testing
"""
import logging
import subprocess
import re
log = logging.getLogger('avocado.test')
def cleanup_docker_and_mock(mockcfg, img_name):
# Clean-up old test artifacts (docker containers, image, mock root)
docker_containerlist_cmdline = 'docker ps --filter=ancestor=%s -a -q' % img_name
try:
containerlist = subprocess.check_output(docker_containerlist_cmdline,
stderr = subprocess.STDOUT, shell = True)
except subprocess.CalledProcessError as e:
log.error("command '%s' returned exit status %d; output:\n%s" %
(e.cmd, e.returncode, e.output))
raise
else:
log.info("docker container list with '%s' succeeded with output:\n%s" %
(docker_containerlist_cmdline, containerlist))
if containerlist:
containers = re.sub('[\r\n]+', ' ', containerlist)
log.info("docker containers using image %s need to be removed: %s\n" %
(img_name, containers));
docker_teardown_cmdline = 'docker rm -f %s' % containers
try:
docker_teardown_output = subprocess.check_output(docker_teardown_cmdline,
stderr = subprocess.STDOUT, shell = True)
except subprocess.CalledProcessError as e:
log.error("command '%s' returned exit status %d; output:\n%s" %
(e.cmd, e.returncode, e.output))
raise
else:
log.info("docker container teardown with '%s' succeeded with output:\n%s" %
(docker_teardown_cmdline, docker_teardown_output))
else:
log.info("no docker containers are using image %s\n" % img_name)
docker_teardown_cmdline = 'docker rmi %s' % img_name
try:
docker_teardown_output = subprocess.check_output(docker_teardown_cmdline,
stderr = subprocess.STDOUT, shell = True)
except subprocess.CalledProcessError as e:
if "No such image" not in e.output:
log.error("command '%s' returned exit status %d; output:\n%s" %
(e.cmd, e.returncode, e.output))
raise
else:
log.info("No existing docker image named %s" % img_name)
else:
log.info("docker teardown with '%s' succeeded with output:\n%s" %
(docker_teardown_cmdline, docker_teardown_output))
mock_teardown_cmdline = ['mock', '-r', mockcfg, '--scrub=all']
try:
mock_teardown_output = subprocess.check_output(mock_teardown_cmdline,
stderr = subprocess.STDOUT)
except subprocess.CalledProcessError as e:
log.error("command '%s' returned exit status %d; output:\n%s" %
(e.cmd, e.returncode, e.output))
raise
log.info("mock teardown with '%s' succeeded with output:\n%s" %
(mock_teardown_cmdline, mock_teardown_output))

View file

@ -1,37 +0,0 @@
document: modularity-testing
version: 1
name: baseruntime
modulemd-url: http://pkgs.fedoraproject.org/cgit/modules/base-runtime.git/plain/base-runtime.yaml
service:
port:
packages:
profiles:
- container
rpms:
default_module: docker
module:
docker:
setup: docker inspect base-runtime-smoke || python ./setup.py
start:
labels:
#Short-term solution as there is no bugzilla component yet
com.redhat.component: "https://github.com/fedora-modularity/base-runtime"
name: "base-runtime"
version: "0"
release: "1"
architecture: "x86_64"
usage: "docker run --rm -it base-runtime/base-runtime bash"
summary: "Minimal application runtime environment other modules can build upon."
url: "https://github.com/fedora-modularity/base-runtime"
FGC: "f26-boltron"
source: http://pkgs.fedoraproject.org/cgit/modules/base-runtime.git
container: docker=base-runtime-smoke
rpm:
setup: echo LANG=C.utf8 > {ROOT}/etc/locale.conf
start:
stop:
status:
repo: https://kojipkgs.fedoraproject.org/compose/latest-Fedora-Modular-26/compose/Server/x86_64/os/
test:
processrunnig:
- 'ls / | grep bin'

View file

@ -1,36 +0,0 @@
config_opts['root'] = 'base-runtime-docker'
config_opts['target_arch'] = 'x86_64'
config_opts['legal_host_arches'] = ('x86_64',)
config_opts['chroot_setup_cmd'] = 'install --setopt=tsflags=nodocs bash coreutils-single filesystem glibc-minimal-langpack libcrypt microdnf rpm shadow-utils sssd-client util-linux'
config_opts['dist'] = ''
config_opts['extra_chroot_dirs'] = [ '/run/lock', ]
config_opts['releasever'] = ''
config_opts['package_manager'] = 'dnf'
config_opts['use_bootstrap_container'] = False
config_opts['yum.conf'] = """
[main]
keepcache=1
debuglevel=2
reposdir=/dev/null
logfile=/var/log/yum.log
retries=20
obsoletes=1
gpgcheck=0
assumeyes=1
syslog_ident=mock
syslog_device=
install_weak_deps=0
metadata_expire=3600
mdpolicy=group:primary
# repos
[buildrepo]
name=base-runtime
baseurl=https://kojipkgs.fedoraproject.org/compose/latest-Fedora-Modular-26/compose/Server/x86_64/os/
enabled=1
gpgcheck=0
"""

View file

@ -1,4 +0,0 @@
default: hello
hello: hello.c
gcc -Wall hello.c -o hello

View file

@ -1,15 +0,0 @@
# compiler sanity smoke test for the Base Runtime docker image
The internal workings of this test are as follows:
1. Create a temporary directory.
2. Copy the `hello.sh` script from this resource directory into the temporary directory and make sure it is executable.
3. Place a gzipped tarball of `hello.c` and `Makefile` from this resource directory into the temporary directory with the name `hello.tgz`.
e.g.,
`$ tar czf /tmp/random/hello.tgz hello.c Makefile`
4. Run the docker container binding the temporary directory as `/mnt` and run `/mnt/hello.sh`.
e.g.,
`$ docker run -v /tmp/random:/mnt:z --rm base-runtime /bin/bash -c /mnt/hello.sh`
5. Clean up the temporary directory upon completion.

View file

@ -1,8 +0,0 @@
#include <stdio.h>
int
main (void)
{
printf ("Hello, world!\n");
return 0;
}

View file

@ -1,7 +0,0 @@
#!/bin/bash
set -e # exit immediately on any failure
microdnf install tar make gcc 1>&2
cd /mnt
tar xzvf hello.tgz 1>&2
make 1>&2
./hello

View file

@ -1,115 +0,0 @@
audit-libs
basesystem
bash
bzip2-libs
ca-certificates
chkconfig
coreutils-single
cracklib
crypto-policies
curl
cyrus-sasl-lib
elfutils-libelf
expat
fedora-modular-release
fedora-modular-repos
filesystem
gawk
glib2
glibc
glibc-common
glibc-minimal-langpack
gmp
gnupg2
gnutls
gobject-introspection
gpgme
grep
gzip
info
keyutils-libs
krb5-libs
libacl
libarchive
libassuan
libattr
libblkid
libcap
libcap-ng
libcom_err
libcrypt
libcurl
libdb
libdb-utils
libdnf
libfdisk
libffi
libgcc
libgcrypt
libgpg-error
libidn2
libksba
libmetalink
libmount
libnghttp2
libpeas
libpsl
libpwquality
librepo
libselinux
libsemanage
libsepol
libsigsegv
libsmartcols
libsolv
libssh2
libsss_idmap
libsss_nss_idmap
libtasn1
libunistring
libutempter
libuuid
libverto
libxml2
lua-libs
lz4
lz4-libs
lzo
microdnf
mpfr
ncurses
ncurses-base
ncurses-libs
nettle
npth
nspr
nss
nss-pem
nss-softokn
nss-softokn-freebl
nss-sysinit
nss-tools
nss-util
openldap
openssl-libs
p11-kit
p11-kit-trust
pam
pcre
popt
publicsuffix-list-dafsa
readline
rpm
rpm-libs
rpm-plugin-selinux
sed
setup
shadow-utils
sqlite-libs
sssd-client
systemd-libs
tzdata
ustr
util-linux
xz-libs
zlib

View file

@ -1,150 +0,0 @@
acl
audit-libs
basesystem
bash
binutils
bzip2-libs
ca-certificates
chkconfig
coreutils-single
cpp
cracklib
cracklib-dicts
crypto-policies
cryptsetup-libs
curl
cyrus-sasl-lib
dbus
dbus-libs
device-mapper
device-mapper-libs
diffutils
elfutils-default-yama-scope
elfutils-libelf
elfutils-libs
emacs-filesystem
expat
fedora-modular-release
fedora-modular-repos
filesystem
gawk
gc
gcc
glib2
glibc
glibc-common
glibc-devel
glibc-headers
glibc-minimal-langpack
gmp
gnupg2
gnutls
gobject-introspection
gpgme
grep
guile
gzip
info
iptables-libs
isl
kernel-headers
keyutils-libs
kmod-libs
krb5-libs
libacl
libarchive
libassuan
libatomic_ops
libattr
libblkid
libcap
libcap-ng
libcom_err
libcrypt
libcurl
libdb
libdb-utils
libdnf
libfdisk
libffi
libgcc
libgcrypt
libgomp
libgpg-error
libidn
libidn2
libksba
libmetalink
libmount
libmpc
libnghttp2
libsss_idmap
libsss_nss_idmap
libpcap
libpeas
libpsl
libpwquality
librepo
libseccomp
libselinux
libsemanage
libsepol
libsigsegv
libsmartcols
libsolv
libssh2
libstdc++
libtasn1
libtool-ltdl
libunistring
libutempter
libuuid
libverto
libxml2
lua-libs
lz4
lz4-libs
lzo
make
microdnf
mpfr
ncurses
ncurses-base
ncurses-libs
nettle
npth
nspr
nss
nss-pem
nss-softokn
nss-softokn-freebl
nss-sysinit
nss-tools
nss-util
openldap
openssl-libs
p11-kit
p11-kit-trust
pam
pcre
popt
publicsuffix-list-dafsa
qrencode-libs
readline
rpm
rpm-libs
rpm-plugin-selinux
sed
setup
shadow-utils
sqlite-libs
sssd-client
systemd
systemd-libs
systemd-pam
tar
tzdata
ustr
util-linux
xz-libs
zlib

View file

@ -1,96 +0,0 @@
#!/bin/bash
set -e # exit immediately on any failure
. /etc/os-release
EXP_NAME="Fedora Modular"
EXP_VERSION="26 (Twenty Six)"
EXP_ID="fedora-modular"
EXP_ID_LIKE="fedora"
EXP_VERSION_ID="26"
EXP_PRETTY_NAME="Fedora Modular 26 (Twenty Six)"
EXP_ANSI_COLOR="0;34"
EXP_CPE_NAME="cpe:/o:fedoraproject:fedora-modular:26"
EXP_HOME_URL="https://fedoraproject.org/"
EXP_BUG_REPORT_URL="https://bugzilla.redhat.com/"
EXP_REDHAT_BUGZILLA_PRODUCT="Fedora"
EXP_REDHAT_BUGZILLA_PRODUCT_VERSION="26"
EXP_REDHAT_SUPPORT_PRODUCT="Fedora"
EXP_REDHAT_SUPPORT_PRODUCT_VERSION="26"
EXP_PRIVACY_POLICY_URL="https://fedoraproject.org/wiki/Legal:PrivacyPolicy"
if [[ $NAME != $EXP_NAME ]]; then
echo "FAIL: Expected NAME to be '$EXP_NAME', but it is '$NAME'"
exit 1
fi
if [[ $VERSION != $EXP_VERSION ]]; then
echo "FAIL: Expected VERSION to be '$EXP_VERSION', but it is '$VERSION'"
exit 1
fi
if [[ $ID != $EXP_ID ]]; then
echo "FAIL: Expected ID to be '$EXP_ID', but it is '$ID'"
exit 1
fi
if [[ $ID_LIKE != $EXP_ID_LIKE ]]; then
echo "FAIL: Expected ID_LIKE to be '$EXP_ID_LIKE', but it is '$ID_LIKE'"
exit 1
fi
if [[ $VERSION_ID != $EXP_VERSION_ID ]]; then
echo "FAIL: Expected VERSION_ID to be '$EXP_VERSION_ID', but it is '$VERSION_ID'"
exit 1
fi
if [[ $PRETTY_NAME != $EXP_PRETTY_NAME ]]; then
echo "FAIL: Expected PRETTY_NAME to be '$EXP_PRETTY_NAME', but it is '$PRETTY_NAME'"
exit 1
fi
if [[ $ANSI_COLOR != $EXP_ANSI_COLOR ]]; then
echo "FAIL: Expected ANSI_COLOR to be '$EXP_ANSI_COLOR', but it is '$ANSI_COLOR'"
exit 1
fi
if [[ $CPE_NAME != $EXP_CPE_NAME ]]; then
echo "FAIL: Expected CPE_NAME to be '$EXP_CPE_NAME', but it is '$CPE_NAME'"
exit 1
fi
if [[ $HOME_URL != $EXP_HOME_URL ]]; then
echo "FAIL: Expected HOME_URL to be '$EXP_HOME_URL', but it is '$HOME_URL'"
exit 1
fi
if [[ $BUG_REPORT_URL != $EXP_BUG_REPORT_URL ]]; then
echo "FAIL: Expected BUG_REPORT_URL to be '$EXP_BUG_REPORT_URL', but it is '$BUG_REPORT_URL'"
exit 1
fi
if [[ $REDHAT_BUGZILLA_PRODUCT != $EXP_REDHAT_BUGZILLA_PRODUCT ]]; then
echo "FAIL: Expected REDHAT_BUGZILLA_PRODUCT to be '$EXP_REDHAT_BUGZILLA_PRODUCT', but it is '$REDHAT_BUGZILLA_PRODUCT'"
exit 1
fi
if [[ $REDHAT_BUGZILLA_PRODUCT_VERSION != $EXP_REDHAT_BUGZILLA_PRODUCT_VERSION ]]; then
echo "FAIL: Expected REDHAT_BUGZILLA_PRODUCT_VERSION to be '$EXP_REDHAT_BUGZILLA_PRODUCT_VERSION', but it is '$REDHAT_BUGZILLA_PRODUCT_VERSION'"
exit 1
fi
if [[ $REDHAT_SUPPORT_PRODUCT != $EXP_REDHAT_SUPPORT_PRODUCT ]]; then
echo "FAIL: Expected REDHAT_SUPPORT_PRODUCT to be '$EXP_REDHAT_SUPPORT_PRODUCT', but it is '$REDHAT_SUPPORT_PRODUCT'"
exit 1
fi
if [[ $REDHAT_SUPPORT_PRODUCT_VERSION != $EXP_REDHAT_SUPPORT_PRODUCT_VERSION ]]; then
echo "FAIL: Expected REDHAT_SUPPORT_PRODUCT_VERSION to be '$EXP_REDHAT_SUPPORT_PRODUCT_VERSION', but it is '$REDHAT_SUPPORT_PRODUCT_VERSION'"
exit 1
fi
if [[ $PRIVACY_POLICY_URL != $EXP_PRIVACY_POLICY_URL ]]; then
echo "FAIL: Expected PRIVACY_POLICY_URL to be '$EXP_PRIVACY_POLICY_URL', but it is '$PRIVACY_POLICY_URL'"
exit 1
fi

View file

@ -1,180 +0,0 @@
#!/usr/bin/env python
import os
import subprocess
import re
import sys
import configparser
import tempfile
from avocado import main
from avocado import Test
from moduleframework import module_framework
import cleanup
import brtconfig
class BaseRuntimeSetupDocker(Test, module_framework.CommonFunctions):
def setUp(self):
self.mockcfg = brtconfig.get_mockcfg(self)
self.br_image_name = brtconfig.get_docker_image_name(self)
def _process_mockcfg(self):
profile_name = brtconfig.get_test_profile(self)
mockcfg = self.mockcfg
mock_root = ''
mockcfg_lines = []
#Regex to get packages that are configured on mockcfg to be installed
chroot_setup_pkg_regex = re.compile("config_opts\s*\[\s*'chroot_setup_cmd'\s*\]\s*="
"\s*'install --setopt=tsflags=nodocs\s*(.*)\s*'")
chroot_setup_pkgs = None
with open(mockcfg, 'r') as mock_cfgfile:
found_setup_cmd = False
for line in mock_cfgfile:
mockcfg_lines.append(line)
if re.match("config_opts\s*\[\s*'root'\s*\]", line) is not None:
mock_root = line.split('=')[1].split("'")[1]
if re.match("config_opts\s*\[\s*'chroot_setup_cmd'\s*\]", line) is not None:
found_setup_cmd = True
#Check if there are packages defined on chroot_setup_cmd
m = chroot_setup_pkg_regex.match(line)
if m:
chroot_setup_pkgs = sorted(m.group(1).split())
if len(mock_root) == 0:
self.error("mock configuration file %s does not specify mock root" %
mockcfg)
self.log.info("mock root: %s" % mock_root)
self.mock_root = mock_root
if not found_setup_cmd:
self.error("mock configuration file %s does not define chroot_setup_cmd" % mockcfg)
#Need to get all packages that need to be installed
mod_yaml = self.getModulemdYamlconfig()
if not mod_yaml:
self.error("Could not read modulemd Yaml file")
if "data" not in mod_yaml.keys():
self.error("'data' key was not found in modulemd Yaml file")
if "profiles" not in mod_yaml["data"].keys():
self.error("'profiles' key was not found in 'data' section")
if profile_name not in mod_yaml["data"]["profiles"].keys():
self.error("'%s' key was not found in 'profiles' section" % profile_name)
base_profile = mod_yaml["data"]["profiles"][profile_name]
if "rpms" not in base_profile.keys():
self.error("'rpms' key was not found in '%s' profile" % profile_name)
req_pkgs = base_profile["rpms"]
if not req_pkgs:
self.error("Could not find any package to be installed in the image")
#Only update mockcfg if the list of packages changed
if cmp(chroot_setup_pkgs, sorted(req_pkgs)):
#Need to change chroot_setup_cmd line on mockcfg file
setup_cmd = "install --setopt=tsflags=nodocs "
setup_cmd += " ".join(req_pkgs)
with open(mockcfg, 'w') as mock_cfgfile:
for line in mockcfg_lines:
if re.match("config_opts\s*\[\s*'chroot_setup_cmd'\s*\]", line) is not None:
line = "config_opts['chroot_setup_cmd'] = '%s'\n" % setup_cmd
mock_cfgfile.write(line)
#Test will exit with WARN to inform the config file has changed
self.log.warning("List of packages to be installed by mock changed")
def _run_command(self, cmd):
try:
cmd_output = subprocess.check_output(
cmd, stderr=subprocess.STDOUT, shell=True)
except subprocess.CalledProcessError as e:
self.error("command '%s' returned exit status %d; output:\n%s" %
(e.cmd, e.returncode, e.output))
else:
self.log.info("command '%s' succeeded with output:\n%s" %
(cmd, cmd_output))
def _set_dnf_conf(self):
filename = "/etc/dnf/dnf.conf"
path = "/var/lib/mock/" + self.mock_root + "/root" + filename
conf = "EOF\n"
conf += "[main]\n"
conf += "gpgcheck=1\n"
conf += "installonly_limit=3\n"
conf += "clean_requirements_on_remove=True\n"
conf += "EOF\n"
cmd = "sudo tee %s << %s" % (path, conf)
self._run_command(cmd)
def testCreateDockerImage(self):
self._process_mockcfg()
# Clean-up any old test artifacts (docker containers, image, mock root)
# first:
try:
cleanup.cleanup_docker_and_mock(self.mockcfg, self.br_image_name)
except:
self.error("artifact cleanup failed")
else:
self.log.info("artifact cleanup successful")
# Initialize chroot with mock
self._run_command('mock -r %s --init' % self.mockcfg)
self._set_dnf_conf()
# check if "sudo" allows us to tar up the chroot without a password
# Note: this must be configured in "sudoers" to work!
tar_cmd = "tar -C /var/lib/mock/%s/root -c ." % self.mock_root
try:
cmd_output = subprocess.check_output(
"sudo -n %s >/dev/null" % tar_cmd,
stderr=subprocess.STDOUT, shell=True)
except subprocess.CalledProcessError as e:
# no luck using "sudo", warn and proceed as ordinary user without
# it
self.log.info("command '%s' returned exit status %d; output:\n%s" %
(e.cmd, e.returncode, e.output))
self.log.warning("NO SUDO RIGHTS TO RUN COMMAND '%s' AS ROOT" %
tar_cmd)
self.log.warning("GENERATED DOCKER IMAGE '%s' MAY BE INCOMPLETE!" %
self.br_image_name)
else:
# "sudo" works, so use it
tar_cmd = "sudo -n " + tar_cmd
img_scratch = "%s-scratch" % self.br_image_name
# Import mock chroot as a docker image
self._run_command("%s | docker import - %s" %
(tar_cmd, img_scratch))
docker_labels = brtconfig.get_docker_labels(self)
#Dockerfile to use when building final image
dockerfile = 'EOF\n'
dockerfile += 'FROM %s\n' % img_scratch
#Set default locale to C.utf8
dockerfile += 'ENV LANG C.utf8\n'
if docker_labels:
for key in docker_labels.keys():
dockerfile += 'LABEL %s="%s"\n' % (key, docker_labels[key])
dockerfile += 'EOF\n'
# Build final image with extra information from dockerfile
self._run_command("docker build -t %s - << %s" %
(self.br_image_name, dockerfile))
#Remove temporary image
self._run_command("docker rmi %s" % img_scratch)
if __name__ == "__main__":
main()

View file

@ -1,468 +0,0 @@
#!/usr/bin/env python
import os
import subprocess
import re
import shutil
import stat
import tarfile
import tempfile
from avocado import main
from moduleframework import module_framework
import brtconfig
class BaseRuntimeSmokeTest(module_framework.AvocadoTest):
"""
:avocado: enable
"""
def setUp(self):
super(self.__class__, self).setUp()
self.compiler_resource_dir = brtconfig.get_compiler_test_dir(self)
self.compiler_test_dir = None
def _check_cmd_result(self, cmd, return_code, cmd_output, expect_pass=True):
"""
Check based on return code if command passed or failed as expected
"""
if return_code == 0 and expect_pass:
self.log.info("command '%s' succeeded with output:\n%s" %
(cmd, cmd_output))
return True
elif return_code != 0 and not expect_pass:
self.log.info("command '%s' failed as expected with output:\n%s" %
(cmd, cmd_output))
return True
self.error("command '%s' returned unexpected exit status %d; output:\n%s" %
(cmd, return_code, cmd_output))
return False
def testSmoke(self):
"""
Run several smoke tests
"""
# TODO: fill this "placeholder" with actual, complete, smoke tests:
smoke_pass = [
"echo 'Hello, World!'",
"cat /etc/redhat-release",
"rpm -q glibc"]
smoke_fail = [
"exit 1"]
for cmd in smoke_pass:
cmd_result = self.run("%s" % cmd, ignore_status=True)
cmd_output = cmd_result.stdout + cmd_result.stderr
self._check_cmd_result(cmd, cmd_result.exit_status, cmd_output)
for cmd in smoke_fail:
cmd_result = self.run("%s" % cmd, ignore_status=True)
cmd_output = cmd_result.stdout + cmd_result.stderr
self._check_cmd_result(cmd, cmd_result.exit_status, cmd_output, expect_pass=False)
def _get_all_installed_pkgs(self):
try:
cmd_result = self.run("rpm -qa --qf='%{{name}}\n'")
except BaseException as details:
self.error("Could not get all installed packages (%s)" % details)
except:
self.error("Could not get all installed packages")
output_list = cmd_result.stdout.split("\n")
#remove empty string from the list
return [item for item in output_list if item]
def testRequiredPackages(self):
"""
Check if all required packages defined on yaml file are installed
"""
profile_name = brtconfig.get_test_profile(self)
mod_yaml = self.getModulemdYamlconfig()
if not mod_yaml:
self.error("Could not read modulemd Yaml file")
if "data" not in mod_yaml.keys():
self.error("'data' key was not found in modulemd Yaml file")
if "profiles" not in mod_yaml["data"].keys():
self.error("'profiles' key was not found in 'data' section")
if profile_name not in mod_yaml["data"]["profiles"].keys():
self.error("'%s' key was not found in 'profiles' section" % profile_name)
base_profile = mod_yaml["data"]["profiles"][profile_name]
if "rpms" not in base_profile.keys():
self.error("'rpms' key was not found in '%s' profile" % profile_name)
req_pkgs = base_profile["rpms"]
if not req_pkgs:
self.error("No rpm is defined for container")
installed_pkgs = self._get_all_installed_pkgs()
for req_pkg in req_pkgs:
if req_pkg not in installed_pkgs:
self.error("Required package '%s' is not installed" % req_pkg)
def testInstalledPackages(self):
"""
Check if only the expected packages are installed on module
"""
expected_pkgs = None
if not self.moduleType:
self.error("moduleType is not defined")
all_installed_pkgs_path = ("resources/installed_packages/all_installed_pkgs_%s.txt"
% self.moduleType)
try:
with open(all_installed_pkgs_path) as f:
expected_pkgs = f.read().splitlines()
except:
self.error("Could not read the expected installed packages list")
if not expected_pkgs:
self.error("List of expected installed packages is empty")
installed_pkgs = self._get_all_installed_pkgs()
if not installed_pkgs:
self.error("It seems there is no package installed in the module")
for pkg in installed_pkgs:
if pkg not in expected_pkgs:
self.error("Did not expect to have package '%s' installed" % pkg)
def testInstallAllPackages(self):
"""
Check if all packages that we ship are able to be installed on module
"""
profile_name = brtconfig.get_test_profile(self)
mod_yaml = self.getModulemdYamlconfig()
if not mod_yaml:
self.error("Could not read modulemd Yaml file")
if "data" not in mod_yaml.keys():
self.error("'data' key was not found in modulemd Yaml file")
if "api" not in mod_yaml["data"].keys():
self.error("'api' key was not found in 'data' section")
if "rpms" not in mod_yaml["data"]["api"].keys():
self.error("'rpms' key was not found in 'api'")
all_api_pkgs = mod_yaml["data"]["api"]["rpms"]
repo_path = None
mod_dep = self.getModuleDependencies()
mod_name = "baseruntime"
if mod_dep and mod_name in mod_dep.keys():
if "urls" in mod_dep[mod_name].keys():
if len(mod_dep[mod_name]["urls"]) != 1:
self.error("Expected exactly 1 repo url for %s" % mod_name)
repo_path = mod_dep[mod_name]["urls"][0]
# docker uses the repo defined on mock cfg
if self.moduleType == "docker":
mockcfg = ""
with open(brtconfig.get_mockcfg(self)) as f:
mockcfg = f.read()
for line in mockcfg.split("\n"):
m = re.match("baseurl=(\S+)", line)
if m:
repo_path = m.group(1)
if not repo_path:
self.error("Could not find repo to query the packages")
#Query all available packages in our repo
query_repo_cmd = "repoquery -a --qf '%%{{name}}' --repofrompath=0,%s --repoid=0" % repo_path
all_repo_pkgs = self.runHost(query_repo_cmd).stdout.split("\n")
all_avail_pkgs = []
#Available packages are the ones from API that are available on repo
for pkg in all_api_pkgs:
if pkg in all_repo_pkgs:
all_avail_pkgs.append(pkg)
skip_pkg_image = {}
skip_pkg_image["docker"] = ["kernel", "dracut"]
skip_pkg_image["nspawn"] = ["kernel", "dracut"]
conflict_pkgs = {
"coreutils" : "coreutils-single",
"libcrypt-nss" : "libcrypt"
}
#Try to install packages that have conflicting packages installed
for pkg in conflict_pkgs.keys():
self.run("microdnf remove %s" % conflict_pkgs[pkg])
self.run("rpm -q %s" % pkg)
self.run("microdnf remove %s" % pkg)
self.run("rpm -q %s" % conflict_pkgs[pkg])
pkgs_2_install = []
for pkg in all_avail_pkgs:
if pkg in conflict_pkgs.keys():
continue
#Do not install packages such as dracut* on docker.
skip = False
for skip_pkg in skip_pkg_image[self.moduleType]:
if pkg.startswith(skip_pkg):
skip = True
if not skip:
pkgs_2_install.append(pkg)
self.run("microdnf install %s > /dev/null" % " ".join(pkgs_2_install))
def testUserManipulation(self):
"""
Check if can add, remove and modify user
"""
#We want to run multiple commands using same docker container
new_user = "usertest"
pass_cmds = []
#Create new user
pass_cmds.append("adduser %s" % new_user)
#Make sure user is created
pass_cmds.append("cat /etc/passwd | grep %s" % new_user)
pass_cmds.append("ls /home/%s" % new_user)
#set user password
pass_cmds.append("usermod --password testpassword %s" % new_user)
#Test new user functionality
pass_cmds.append('su - %s -c "touch ~/testfile.txt"' % new_user)
#Make sure the file was created by the correct user
pass_cmds.append("ls -allh /home/%s/testfile.txt | grep '%s %s'" %
(new_user, new_user, new_user))
#Remove user
pass_cmds.append("userdel -r %s" % new_user)
for cmd in pass_cmds:
cmd_result = self.run("%s" % cmd, ignore_status=True)
cmd_output = cmd_result.stdout + cmd_result.stderr
self._check_cmd_result(cmd, cmd_result.exit_status, cmd_output)
fail_cmds = []
#Make sure user is removed
fail_cmds.append("ls /home/%s" % new_user)
fail_cmds.append("cat /etc/passwd | grep usertest")
#relying on __del__ from BaseRuntimeRunCmd to remove container
for cmd in fail_cmds:
cmd_result = self.run("%s" % cmd, ignore_status=True)
cmd_output = cmd_result.stdout + cmd_result.stderr
self._check_cmd_result(cmd, cmd_result.exit_status, cmd_output, expect_pass=False)
def testOsRelease(self):
"""
Check if OS release information is correct
"""
test_path = "resources/os_release/os_release.sh"
dest_path = "/tmp/os_release.sh"
try:
self.copyTo(test_path, dest_path)
except:
self.error("Could not copy test file from %s to module %s" %
(test_path, dest_path))
try:
self.run(dest_path)
except:
self.error("%s failed" % dest_path)
try:
self.run("rm -f %s" % dest_path)
except:
self.error("Could not delete %s" % dest_path)
def test_glibc_i18n(self):
"""
Test glibc support to internationalization
"""
lang_default = {
#cmd : cmd_output
"ls /invalid_path" : "ls: cannot access '/invalid_path': No such file or directory",
"cp invalid_file tmp" : "cp: cannot stat 'invalid_file': No such file or directory",
"date -u -d \"2017-03-31\"" : "Fri Mar 31 00:00:00 UTC 2017",
"touch file; yes | rm -i file" : "rm: remove regular empty file 'file'?",
"numfmt --grouping 1234567890.98" : "1234567890.98"
}
lang_english = {
"LC_ALL=en_US ls /invalid_path" : "ls: cannot access '/invalid_path': No such file or directory",
"LC_ALL=en_US cp invalid_file tmp" : "cp: cannot stat 'invalid_file': No such file or directory",
"LC_ALL=en_US date -u -d \"2017-03-31\"" : "Fri Mar 31 00:00:00 UTC 2017",
"touch file; yes | LC_ALL=en_US rm -i file" : "rm: remove regular empty file 'file'?",
"LC_ALL=en_US numfmt --grouping 1234567890.98" : "1,234,567,890.98"
}
lang_spanish = {
"LC_ALL=es_ES ls /invalid_path" : "No existe el fichero o el directorio",
"LC_ALL=es_ES cp invalid_file tmp" : "No existe el fichero o el directorio",
"LC_ALL=es_ES date -u -d \"2017-03-31\"" : "vie mar 31 00:00:00 UTC 2017",
"LC_ALL=es_ES numfmt --grouping 1234567890,98" : "1.234.567.890,98"
}
langs = {}
langs["default"] = {
"pkg" : "glibc-minimal-langpack",
"cmds" : lang_default
}
langs["english"] = {
"pkg" : "glibc-langpack-en",
"cmds" : lang_english
}
langs["spanish"] = {
"pkg" : "glibc-langpack-es",
"cmds" : lang_spanish
}
#Check if C.utf8 is the default locale
self.run("echo $LANG | grep 'C.utf8'")
for i18n in langs.keys():
lang = langs[i18n]
self.log.info("Testing %s" % lang["pkg"])
install_package = True
# glibc-minimal-langpack is installed by default
if lang["pkg"] == "glibc-minimal-langpack":
install_package = False
if install_package:
try:
self.run("microdnf install %s" % lang["pkg"])
except:
self.error("Could not install %s" % lang["pkg"])
for cmd in lang["cmds"].keys():
cmd_result = self.run("%s" % cmd, ignore_status=True)
output = cmd_result.stdout
output += cmd_result.stderr
output = output.strip()
#search for pattern as Spanish might have special characters
if not re.search(lang["cmds"][cmd], output):
self.error("'%s'expected output '%s', but got '%s'" %
(cmd, lang["cmds"][cmd], output))
if install_package:
try:
self.run("microdnf remove %s" % lang["pkg"])
except:
self.error("Could not remove %s" % lang["pkg"])
def test_dnf(self):
"""
Check if DNF is able to install a package
"""
package = "tar"
self.run("microdnf install dnf")
self.run("dnf install -y %s" % package)
self.run("dnf remove -y %s" % package)
self.run("microdnf remove dnf")
def _prepare_compiler_test_directory(self):
# create a temporary directory
tmpdir = tempfile.mkdtemp()
self.log.info("Compiler test temporary directory is %s" % tmpdir)
# Copy the `hello.sh` script from this resource directory into the
# temporary directory
src = os.path.join(self.compiler_resource_dir, "hello.sh")
dest = os.path.join(tmpdir, "hello.sh")
try:
shutil.copy(src, dest)
except shutil.Error as e:
self.log.info('Error: %s' % e)
except IOError as e:
self.log.info('Error: %s' % e.strerror)
# make sure destination script is executable
st = os.stat(dest)
os.chmod(dest, st.st_mode | stat.S_IEXEC)
# Place a gzipped tarball of `hello.c` and `Makefile` from the
# resource directory into the temporary directory with the name
# `hello.tgz`.
dest = os.path.join(tmpdir, "hello.tgz")
tar = tarfile.open(dest, "w:gz")
for f in ["hello.c", "Makefile"]:
src = os.path.join(self.compiler_resource_dir, f)
tar.add(src, arcname=f)
tar.close()
self.compiler_test_dir = tmpdir
def _cleanup_compiler_test_directory(self):
# clean up the temporary directory
if self.compiler_test_dir:
self.log.info("cleaning up compiler test directory")
shutil.rmtree(self.compiler_test_dir, ignore_errors=True)
def testCompiler(self):
"""
Run a basic C compiler test on our docker image.
This actually tests the integration of several things, including the
ability to install packages, extract a gzipped tarball, run make to
compile a very simple C program, and run the compiled executable.
"""
self._prepare_compiler_test_directory()
#The test dir should be the same one used on hello.sh
mod_compiler_test_dir = "/mnt"
#Make sure there is a container running
#TODO: Remove start() once https://pagure.io/modularity-testing-framework/issue/8 is fixed
self.start()
try:
self.copyTo("%s/." % self.compiler_test_dir, mod_compiler_test_dir)
except:
self.error("Could not copy test files from %s to module %s" %
(self.compiler_test_dir, mod_compiler_test_dir))
cmdline = "%s/hello.sh" % mod_compiler_test_dir
cmd_result = self.run("%s" % cmdline, ignore_status=True)
test_stdout = cmd_result.stdout
test_stderr = cmd_result.stderr
if cmd_result.exit_status:
self.error("command '%s' returned exit status %d; output:\n%s\nstderr:\n%s" %
(cmdline, cmd_result.exit_status, test_stdout, test_stderr))
self.log.info("command '%s' succeeded with output:\n%s\nstderr:\n%s" %
(cmdline, test_stdout, test_stderr))
# make sure we get exactly what we expect on stdout
# (all other output from commands in the script were sent to stderr)
expected_stdout = 'Hello, world!\n'
self.log.info("checking that compiler test returned expected output: %s" %
repr(expected_stdout))
if test_stdout != expected_stdout:
self.error("compiler test did not return unexpected output: %s" %
repr(test_stdout))
def tearDown(self):
"""
Tear-down
"""
super(self.__class__, self).tearDown()
self._cleanup_compiler_test_directory()
if __name__ == "__main__":
main()

View file

@ -1,32 +0,0 @@
#!/usr/bin/env python
import os
import subprocess
import re
from avocado import main
from avocado import Test
import cleanup
import brtconfig
class BaseRuntimeTeardownDocker(Test):
def setUp(self):
self.mockcfg = brtconfig.get_mockcfg(self)
self.br_image_name = brtconfig.get_docker_image_name(self)
def testRemoveDockerImage(self):
# Clean-up old test artifacts (docker containers, image, mock root)
try:
cleanup.cleanup_docker_and_mock(self.mockcfg, self.br_image_name)
except:
self.error("artifact cleanup failed")
else:
self.log.info("artifact cleanup successful")
if __name__ == "__main__":
main()