Skip to content

Commit

Permalink
tests/compose: Target FCOS 31, move off of PAPR
Browse files Browse the repository at this point in the history
Again, a lot going on here, but essentially, we adapt the compose tests
to run either privileged or fully unprivileged via supermin, just like
cosa.

I actually got more than halfway through this initially using `cosa
build` directly for testing. But in the end, we simply need more
flexibility than that. We want to be able to manipulate exactly how
rpm-ostree is called, and cosa is very opinionated about this (and may
also change from under us in the future).

(Another big difference for example is that cosa doesn't care about
non-unified mode, whereas we *need* to have coverage for this until we
fully kill it.)

Really, the most important bit we want from there is the
unprivileged-via-supermin bits. So we copy and adapt that here. One
obvious improvement then is sharing this code more easily (e.g. a
`cosa runasroot` or something?)

However, we still use the FCOS manifest (frozen at a specific tag). It's
a realistic example, and because of the lockfiles and pool, we get good
reproducibility.
  • Loading branch information
jlebon committed Dec 21, 2019
1 parent 92416f6 commit fd4061f
Show file tree
Hide file tree
Showing 28 changed files with 802 additions and 737 deletions.
39 changes: 36 additions & 3 deletions .cci.jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ stage("Build FCOS") {
}


stage("Run vmcheck") {
stage("Test") {
parallel vmcheck: {
def nhosts = 6
def mem = (nhosts * 1024) + 512
coreos.pod(image: COSA_IMAGE, runAsUser: 0, kvm: true, memory: "${mem}Mi", cpu: "${nhosts}") {
Expand All @@ -100,7 +101,7 @@ stage("Run vmcheck") {
set -xeuo pipefail
fcos=\$(ls builds/latest/*/*.qcow2) # */
ln -sf "\$(realpath \${fcos})" tests/vmcheck/image.qcow2
NHOSTS=${nhosts} tests/vmcheck.sh
JOBS=${nhosts} tests/vmcheck.sh
"""
}
} finally {
Expand All @@ -112,4 +113,36 @@ stage("Run vmcheck") {
archiveArtifacts allowEmptyArchive: true, artifacts: 'vmcheck-logs.tar.xz'
}
}
}
},
compose: {
def parallelize = 5
def mem = (parallelize * 1536) + 512
coreos.pod(image: COSA_IMAGE, runAsUser: 0, emptyDirs: ["/srv/tmpdir"], kvm: true, memory: "${mem}Mi", cpu: "${parallelize}") {
checkout scm
unstash 'rpms'
sh """
set -euo pipefail
ci/installdeps.sh # really, we just need test deps, but meh...

# install our built rpm-ostree
find packaging/ ! -name '*.src.rpm' -name '*.rpm' | xargs dnf install -y
rm -rf packaging
"""
try {
timeout(time: 30, unit: 'MINUTES') {
sh """
set -xeuo pipefail
mkdir compose-logs
TMPDIR=/srv/tmpdir JOBS=${parallelize} ./tests/compose.sh
"""
}
} finally {
sh """
if [ -d compose-logs ]; then
tar -C compose-logs -cf- . | xz -c9 > compose-logs.tar.xz
fi
"""
archiveArtifacts allowEmptyArchive: true, artifacts: 'compose-logs.tar.xz'
}
}
}}
46 changes: 0 additions & 46 deletions .papr.yml

This file was deleted.

48 changes: 48 additions & 0 deletions tests/common/libtest-core.sh
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,51 @@ skip() {
echo "1..0 # SKIP" "$@"
exit 0
}

# https://github.com/coreos/coreos-assembler/pull/632. Ideally, we'd also cap
# based on memory available to us, but that's notoriously difficult to do for
# containers (see:
# https://fabiokung.com/2014/03/13/memory-inside-linux-containers/). We make an
# assumption here that we have at least e.g. 1G of RAM we can use per CPU
# available to us.
ncpus() {
if ! grep -q kubepods /proc/1/cgroup; then
# this might be a developer laptop; leave one cpu free to be nice
echo $(($(nproc) - 1))
return 0
fi

quota=$(cat /sys/fs/cgroup/cpu/cpu.cfs_quota_us)
period=$(cat /sys/fs/cgroup/cpu/cpu.cfs_period_us)
if [[ ${quota} != -1 ]] && [[ ${period} -gt 0 ]]; then
echo $(("${quota}" / "${period}"))
fi

# just fallback to 1
echo 1
}

filter_tests() {
local tests_dir=$1; shift
local skipped=0

local selected_tests=()
for tf in $(find "${tests_dir}" -name 'test-*.sh' | shuf); do
tfbn=$(basename "$tf" .sh)
tfbn=" ${tfbn#test-} "
if [ -n "${TESTS+ }" ]; then
if [[ " $TESTS " != *$tfbn* ]]; then
skipped=$((skipped + 1))
continue
fi
fi

selected_tests+=("${tfbn}")
done

if [ ${skipped} -gt 0 ]; then
echo "Skipping ${skipped} tests" >&2
fi

echo "${selected_tests[*]}"
}
6 changes: 5 additions & 1 deletion tests/common/libtest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ _cleanup_tmpdir () {

# Create a tmpdir if we're running as a local test (i.e. through `make check`)
# or as a `vmcheck` test, which also needs some scratch space on the host.
if ( test -n "${UNINSTALLEDTESTS:-}" || test -n "${VMTESTS:-}" ) && ! test -f $PWD/.test; then
if { test -n "${UNINSTALLEDTESTS:-}" || \
test -n "${VMTESTS:-}" || \
test -n "${COMPOSETESTS:-}"; } && ! test -f "$PWD/.test"; then
# Use --tmpdir to keep it in /tmp. This also keeps paths short; this is
# important if we want to create UNIX sockets under there.
test_tmpdir=$(mktemp -d test.XXXXXX --tmpdir)
Expand Down Expand Up @@ -404,6 +406,8 @@ EOF
case $section in
requires)
echo "Requires: $arg" >> $spec;;
recommends)
echo "Recommends: $arg" >> $spec;;
provides)
echo "Provides: $arg" >> $spec;;
conflicts)
Expand Down
144 changes: 63 additions & 81 deletions tests/compose.sh
Original file line number Diff line number Diff line change
@@ -1,96 +1,78 @@
#!/bin/bash
set -euo pipefail

dn=$(cd $(dirname $0) && pwd)
# freeze on a specific commit for tests for reproducibility and since it should
# always work to target older treefiles
FEDORA_COREOS_CONFIG_COMMIT=088fc2dec535aca392958e9c30c17cf19ef4b568

export topsrcdir=$(cd $dn/.. && pwd)
. ${dn}/common/libtest-core.sh
. ${dn}/common/libtestrepos.sh
dn=$(cd "$(dirname "$0")" && pwd)
topsrcdir=$(cd "$dn/.." && pwd)
commondir=$(cd "$dn/common" && pwd)
export topsrcdir commondir

# avoid refetching yum metadata everytime
export RPMOSTREE_USE_CACHED_METADATA=1
# shellcheck source=common/libtest-core.sh
. "${commondir}/libtest-core.sh"

export LOGDIR=${LOGDIR:-$(pwd)/test-compose-logs}
mkdir -p ${LOGDIR}

colour_print() {
colour=$1; shift
[ ! -t 1 ] || echo -en "\e[${colour}m"
echo -n "$@"
[ ! -t 1 ] || echo -en "\e[0m"
echo
}
read -r -a tests <<< "$(filter_tests "${topsrcdir}/tests/compose")"
if [ ${#tests[*]} -eq 0 ]; then
echo "No tests selected; mistyped filter?"
exit 0
fi

pass_print() {
colour_print 32 "$@" # green
}
JOBS=${JOBS:-$(ncpus)}

fail_print() {
colour_print 31 "$@" # red
}
# re-use the same FCOS config and RPMs if it already exists
if [ ! -d compose-cache ]; then
mkdir -p compose-cache

skip_print() {
colour_print 34 "$@" # blue
}
# first, download all the RPMs into a directory
echo "Caching test fixtures in compose-cache/"

uid=$(id -u)
test_compose_datadir=/var/tmp/rpmostree-compose-cache-${uid}
export test_compose_datadir
mkdir -p ${test_compose_datadir}
datadir_owner=$(stat -c '%u' ${test_compose_datadir})
test ${uid} = ${datadir_owner}
# Really want to use cosa fetch for this and just share the pkgcache repo.
# Though for now we still need to support non-unified mode. Once we don't, we
# can clean this up.
pushd compose-cache
git clone https://github.com/coreos/fedora-coreos-config config
pushd config
git checkout "${FEDORA_COREOS_CONFIG_COMMIT}"
# we flatten the treefile to make it easier to manipulate in tests (we have
# lots of tests that check for include logic already)
rpm-ostree compose tree --print-only manifest.yaml > manifest.json
rm manifest.yaml
mv manifests/{passwd,group} .
rm -rf manifests/
popd

# Create a consistent cache of the RPMs
echo "Preparing compose tests... $(date)"
tmp_repo=${test_compose_datadir}/tmp-repo
if test -z "${RPMOSTREE_COMPOSE_CACHEONLY:-}"; then
setup_rpmmd_repos ${dn}/composedata
ostree --repo=${tmp_repo} init --mode=bare-user
# Ensure all subsequent tests have the RPMs
mkdir -p ${test_compose_datadir}/{fedora-local,cache}
rpm-ostree compose --repo=${tmp_repo} tree --download-only-rpms --cachedir=${test_compose_datadir}/cache ${dn}/composedata/fedora-base.json
find ${test_compose_datadir}/cache/ -name '*.rpm' | while read f; do
mv $f ${test_compose_datadir}/fedora-local
done
(cd ${test_compose_datadir}/fedora-local && createrepo_c .)
mkdir cachedir
# we just need a repo so we can download stuff (but see note above about
# sharing pkgcache repo in the future)
ostree init --repo=repo --mode=archive
rpm-ostree compose tree --unified-core --download-only-rpms --repo=repo \
config/manifest.json --cachedir cachedir \
--ex-lockfile config/manifest-lock.x86_64.json \
--ex-lockfile config/manifest-lock.overrides.x86_64.yaml
rm -rf repo
(cd cachedir && createrepo_c .)
echo -e "[cache]\nbaseurl=$(pwd)/cachedir\ngpgcheck=0" > config/cache.repo
pushd config
python3 -c '
import sys, json
y = json.load(sys.stdin)
y["repos"] = ["cache"]
json.dump(y, sys.stdout)' < manifest.json > manifest.json.new
mv manifest.json{.new,}
git add .
git -c user.email="composetest@localhost.com" -c user.name="composetest" \
commit -am 'modifications for tests'
popd
popd
fi
echo "Done preparing compose tests! $(date)"
rm ${tmp_repo} -rf

total=0
pass=0
fail=0
skip=0
all_tests="$(cd ${dn}/compose-tests && ls test-*.sh | sort)"
if [ "${RPMOSTREE_COMPOSE_TEST_FILTER:-}" == odd ]; then
# https://superuser.com/a/101760/237392
all_tests="$(sed -n 'p;n' <<< ${all_tests})"
elif [ "${RPMOSTREE_COMPOSE_TEST_FILTER:-}" == even ]; then
all_tests="$(sed -n 'n;p' <<< ${all_tests})"
fi
tests=""
if [ -n "${TESTS+ }" ]; then
for tf in ${all_tests}; do
tfbn=$(basename "$tf" .sh)
tfbn=" ${tfbn#test-} "
if [[ " $TESTS " != *$tfbn* ]]; then
echo "Skipping: ${tf}"
continue
fi
tests="${tests} ${tf}"
done
else
tests="${all_tests}"
fi
echo "Running ${#tests[*]} tests ${JOBS} at a time"

if test -z "${tests}"; then
fatal "error: No tests match ${TESTS}"
fi
outputdir="${topsrcdir}/compose-logs"
fixtures="$(pwd)/compose-cache"
echo "Test results outputting to ${outputdir}/"

echo "Compose tests starting: $(date)"
echo "Executing: ${tests}"
echo "Writing logs to ${LOGDIR}"
(for tf in ${tests}; do echo $tf; done) | \
parallel -v -j +1 --progress --halt soon,fail=1 \
--results ${LOGDIR}/parallel --quote /bin/sh -c "${dn}/compose-tests/run-test.sh {}"
echo "$(date): All tests passed"
echo -n "${tests[*]}" | parallel -d' ' -j "${JOBS}" --line-buffer \
"${topsrcdir}/tests/compose/runtest.sh" "${outputdir}" "${fixtures}"

0 comments on commit fd4061f

Please sign in to comment.