From 3cf35785034506a5366d06cde2814e7389a2da8b Mon Sep 17 00:00:00 2001 From: Renaud Gaubert Date: Thu, 14 May 2020 00:56:55 +0000 Subject: [PATCH] Add integration tests for the new runc hooks This patch adds a test based on real world usage of runc hooks (libnvidia-container). We verify that mounting a library inside a container and running ldconfig succeeds. Signed-off-by: Renaud Gaubert --- Dockerfile | 18 +++++++++ Vagrantfile.fedora32 | 11 +++-- libcontainer/configs/config_test.go | 2 +- tests/integration/helpers.bash | 31 ++++++++++++++ tests/integration/hooks.bats | 63 +++++++++++++++++++++++++++++ tests/integration/multi-arch.bash | 40 +++++++++++++----- 6 files changed, 152 insertions(+), 13 deletions(-) create mode 100644 tests/integration/hooks.bats diff --git a/Dockerfile b/Dockerfile index 6a17ceb5e83..bcff5f5ac1d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -67,6 +67,19 @@ RUN mkdir -p /usr/src/criu \ && cd - \ && rm -rf /usr/src/criu +# install skopeo +RUN echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/Debian_Unstable/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list \ + && wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/Debian_Unstable/Release.key -O- | sudo apt-key add - \ + && apt-get update \ + && apt-get install -y --no-install-recommends skopeo \ + && rm -rf /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list \ + && apt-get clean \ + && rm -rf /var/cache/apt /var/lib/apt/lists/*; + +# install umoci +RUN curl -o /usr/local/bin/umoci -fsSL https://github.com/openSUSE/umoci/releases/download/v0.4.5/umoci.amd64 \ + && chmod +x /usr/local/bin/umoci + COPY script/tmpmount / WORKDIR /go/src/github.com/opencontainers/runc ENTRYPOINT ["/tmpmount"] @@ -78,4 +91,9 @@ RUN mkdir -p "${ROOTFS}" RUN . tests/integration/multi-arch.bash \ && curl -fsSL `get_busybox` | tar xfJC - "${ROOTFS}" +ENV DEBIAN_ROOTFS /debian +RUN mkdir -p "${DEBIAN_ROOTFS}" +RUN . tests/integration/multi-arch.bash \ + && get_and_extract_debian "$DEBIAN_ROOTFS" + COPY . . diff --git a/Vagrantfile.fedora32 b/Vagrantfile.fedora32 index cb4e02860ac..3fa3600f582 100644 --- a/Vagrantfile.fedora32 +++ b/Vagrantfile.fedora32 @@ -17,7 +17,7 @@ Vagrant.configure("2") do |config| config exclude kernel,kernel-core config install_weak_deps false update -install iptables gcc make golang-go libseccomp-devel bats jq git-core criu +install iptables gcc make golang-go libseccomp-devel bats jq git-core criu skopeo ts run EOF dnf clean all @@ -31,10 +31,15 @@ EOF cat /root/rootless.key.pub >> /home/rootless/.ssh/authorized_keys chown -R rootless.rootless /home/rootless + # Install umoci + curl -o /usr/local/bin/umoci -fsSL https://github.com/openSUSE/umoci/releases/download/v0.4.5/umoci.amd64 + chmod +x /usr/local/bin/umoci + # Add busybox for libcontainer/integration tests . /vagrant/tests/integration/multi-arch.bash \ - && mkdir /busybox \ - && curl -fsSL $(get_busybox) | tar xfJC - /busybox + && mkdir /busybox /debian \ + && curl -fsSL $(get_busybox) | tar xfJC - /busybox \ + && get_and_extract_debian /debian # Delegate cgroup v2 controllers to rootless user via --systemd-cgroup mkdir -p /etc/systemd/system/user@.service.d diff --git a/libcontainer/configs/config_test.go b/libcontainer/configs/config_test.go index db9ccaee6ab..7d66575db72 100644 --- a/libcontainer/configs/config_test.go +++ b/libcontainer/configs/config_test.go @@ -35,7 +35,7 @@ func TestUnmarshalHooks(t *testing.T) { t.Fatal(err) } - if !reflect.DeepEqual(hooks[hookName], hookCmd) { + if !reflect.DeepEqual(hooks[hookName], configs.HookList{hookCmd}) { t.Errorf("Expected %s to equal %+v but it was %+v", hookName, hookCmd, hooks[hookName]) } } diff --git a/tests/integration/helpers.bash b/tests/integration/helpers.bash index 5db99320150..6fd22aed43e 100644 --- a/tests/integration/helpers.bash +++ b/tests/integration/helpers.bash @@ -21,6 +21,9 @@ HELLO_FILE=`get_hello` HELLO_IMAGE="$TESTDATA/$HELLO_FILE" HELLO_BUNDLE="$BATS_TMPDIR/hello-world" +# debian image +DEBIAN_BUNDLE="$BATS_TMPDIR/debiantest" + # CRIU PATH CRIU="$(which criu 2>/dev/null || true)" @@ -422,6 +425,27 @@ function setup_hello() { update_config '(.. | select(.? == "sh")) |= "/hello"' } +function setup_debian() { + # skopeo and umoci are not installed on the travis runner + if [ -n "${RUNC_USE_SYSTEMD}" ]; then + return + fi + + setup_recvtty + run mkdir "$DEBIAN_BUNDLE" + + if [ ! -d "$DEBIAN_ROOTFS/rootfs" ]; then + get_and_extract_debian "$DEBIAN_BUNDLE" + fi + + # Use the cached version + if [ ! -d "$DEBIAN_BUNDLE/rootfs" ]; then + cp -r "$DEBIAN_ROOTFS"/* "$DEBIAN_BUNDLE/" + fi + + cd "$DEBIAN_BUNDLE" +} + function teardown_running_container() { runc list # $1 should be a container name such as "test_busybox" @@ -459,3 +483,10 @@ function teardown_hello() { teardown_running_container test_hello run rm -f -r "$HELLO_BUNDLE" } + +function teardown_debian() { + cd "$INTEGRATION_ROOT" + teardown_recvtty + teardown_running_container test_debian + run rm -f -r "$DEBIAN_BUNDLE" +} diff --git a/tests/integration/hooks.bats b/tests/integration/hooks.bats new file mode 100644 index 00000000000..aa2f70bec9e --- /dev/null +++ b/tests/integration/hooks.bats @@ -0,0 +1,63 @@ +#!/usr/bin/env bats + +load helpers + +# CR = CreateRuntime +# CC = CreataContainer +HOOKLIBCR=librunc-hooks-create-runtime.so +HOOKLIBCC=librunc-hooks-create-container.so +LIBPATH="$DEBIAN_BUNDLE/rootfs/lib/" + +function setup() { + umount $LIBPATH/$HOOKLIBCR.1.0.0 &> /dev/null || true + umount $LIBPATH/$HOOKLIBCC.1.0.0 &> /dev/null || true + + teardown_debian + setup_debian +} + +function teardown() { + umount $LIBPATH/$HOOKLIBCR.1.0.0 &> /dev/null || true + umount $LIBPATH/$HOOKLIBCC.1.0.0 &> /dev/null || true + + rm -f $HOOKLIBCR.1.0.0 $HOOKLIBCC.1.0.0 + teardown_debian +} + +@test "runc run (hooks library tests)" { + requires root + requires no_systemd + + # setup some dummy libs + gcc -shared -Wl,-soname,librunc-hooks-create-runtime.so.1 -o "$HOOKLIBCR.1.0.0" + gcc -shared -Wl,-soname,librunc-hooks-create-container.so.1 -o "$HOOKLIBCC.1.0.0" + + current_pwd="$(pwd)" + + # To mount $HOOKLIBCR we need to do that in the container namespace + create_runtime_hook=$(cat <<-EOF + pid=\$(cat - | jq -r '.pid') + touch "$LIBPATH/$HOOKLIBCR.1.0.0" + nsenter -m \$ns -t \$pid mount --bind "$current_pwd/$HOOKLIBCR.1.0.0" "$LIBPATH/$HOOKLIBCR.1.0.0" + EOF) + + create_container_hook="touch ./lib/$HOOKLIBCC.1.0.0 && mount --bind $current_pwd/$HOOKLIBCC.1.0.0 ./lib/$HOOKLIBCC.1.0.0" + + CONFIG=$(jq --arg create_runtime_hook "$create_runtime_hook" --arg create_container_hook "$create_container_hook" ' + .hooks |= . + {"createRuntime": [{"path": "/bin/sh", "args": ["/bin/sh", "-c", $create_runtime_hook]}]} | + .hooks |= . + {"createContainer": [{"path": "/bin/sh", "args": ["/bin/sh", "-c", $create_container_hook]}]} | + .hooks |= . + {"startContainer": [{"path": "/bin/sh", "args": ["/bin/sh", "-c", "ldconfig"]}]} | + .process.args = ["/bin/sh", "-c", "ldconfig -p | grep librunc"]' $DEBIAN_BUNDLE/config.json) + echo "${CONFIG}" > config.json + + runc run test_debian + [ "$status" -eq 0 ] + + echo "Checking create-runtime library" + echo $output | grep $HOOKLIBCR + [ "$?" -eq 0 ] + + echo "Checking create-container library" + echo $output | grep $HOOKLIBCC + [ "$?" -eq 0 ] +} diff --git a/tests/integration/multi-arch.bash b/tests/integration/multi-arch.bash index 5616bf7e100..c0519146b0b 100644 --- a/tests/integration/multi-arch.bash +++ b/tests/integration/multi-arch.bash @@ -1,5 +1,5 @@ #!/bin/bash -get_busybox(){ +get_busybox() { case $(go env GOARCH) in arm64) echo 'https://github.com/docker-library/busybox/raw/dist-arm64v8/glibc/busybox.tar.xz' @@ -10,13 +10,35 @@ get_busybox(){ esac } -get_hello(){ +get_hello() { case $(go env GOARCH) in - arm64) - echo 'hello-world-aarch64.tar' - ;; - *) - echo 'hello-world.tar' - ;; - esac + arm64) + echo 'hello-world-aarch64.tar' + ;; + *) + echo 'hello-world.tar' + ;; + esac +} + +get_and_extract_debian() { + tmp=$(mktemp -d) + cd "$tmp" + + debian="debian:3.11.6" + + case $(go env GOARCH) in + arm64) + skopeo copy docker://arm64v8/debian:buster "oci:$debian" + ;; + *) + skopeo copy docker://amd64/debian:buster "oci:$debian" + ;; + esac + + args="$([ -z "${ROOTLESS_TESTPATH+x}" ] && echo "--rootless")" + umoci unpack $args --image "$debian" "$1" + + cd - + rm -rf "$tmp" }