From ba38383a394b4b616b13ceab8f009bbc7a380f66 Mon Sep 17 00:00:00 2001 From: Aleksa Sarai Date: Wed, 11 May 2016 17:45:00 +1000 Subject: [PATCH] tests: add rootless integration tests This adds targets for rootless integration tests, as well as all of the required setup in order to get the tests to run. This includes quite a few changes, because of a lot of assumptions about things running as root within the bats scripts (which is not true when setting up rootless containers). Signed-off-by: Aleksa Sarai --- Dockerfile | 7 +++++ Makefile | 11 +++++-- tests/integration/checkpoint.bats | 5 ++-- tests/integration/delete.bats | 2 ++ tests/integration/events.bats | 12 ++++++++ tests/integration/exec.bats | 3 ++ tests/integration/help.bats | 1 + tests/integration/helpers.bash | 23 +++++++++++---- tests/integration/ps.bats | 11 ++++++- tests/integration/spec.bats | 4 +-- tests/integration/start_detached.bats | 3 ++ tests/integration/start_hello.bats | 3 ++ tests/integration/state.bats | 42 ++++++++++++++++++++------- tests/integration/tty.bats | 14 +++++++++ 14 files changed, 117 insertions(+), 24 deletions(-) diff --git a/Dockerfile b/Dockerfile index c971448c..fd9be94c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,6 +6,7 @@ RUN echo 'deb http://httpredir.debian.org/debian jessie-backports main' > /etc/a RUN apt-get update && apt-get install -y \ build-essential \ curl \ + sudo \ gawk \ iptables \ jq \ @@ -22,6 +23,12 @@ RUN apt-get update && apt-get install -y \ --no-install-recommends \ && apt-get clean +# Add a dummy user for the rootless integration tests. While runC does +# not require an entry in /etc/passwd to operate, one of the tests uses +# `git clone` -- and `git clone` does not allow you to clone a +# repository if the current uid does not have an entry in /etc/passwd. +RUN useradd -u1000 -m -d/home/rootless -s/bin/bash rootless + # install bats RUN cd /tmp \ && git clone https://github.com/sstephenson/bats.git \ diff --git a/Makefile b/Makefile index 5fff5151..1cecca17 100644 --- a/Makefile +++ b/Makefile @@ -79,10 +79,10 @@ runcimage: docker build -t $(RUNC_IMAGE) . test: - make unittest integration + make unittest integration rootlessintegration localtest: - make localunittest localintegration + make localunittest localintegration localrootlessintegration unittest: runcimage docker run -e TESTFLAGS -t --privileged --rm -v $(CURDIR):/go/src/$(PROJECT) $(RUNC_IMAGE) make localunittest @@ -96,6 +96,13 @@ integration: runcimage localintegration: all bats -t tests/integration${TESTFLAGS} +rootlessintegration: runcimage + docker run -e TESTFLAGS -t --privileged --rm -v $(CURDIR):/go/src/$(PROJECT) --cap-drop=ALL -u rootless $(RUNC_IMAGE) make localintegration + +# FIXME: This should not be separate from rootlessintegration's method of running. +localrootlessintegration: all + sudo -u rootless -H PATH="${PATH}" bats -t tests/integration${TESTFLAGS} + shell: all docker run -e TESTFLAGS -ti --privileged --rm -v $(CURDIR):/go/src/$(PROJECT) $(RUNC_IMAGE) bash diff --git a/tests/integration/checkpoint.bats b/tests/integration/checkpoint.bats index e91fd651..cd969a80 100644 --- a/tests/integration/checkpoint.bats +++ b/tests/integration/checkpoint.bats @@ -59,8 +59,9 @@ function teardown() { [[ "${output}" == *"running"* ]] } -@test "checkpoint(pre-dump) and restore" { - requires criu +@test "checkpoint --pre-dump and restore" { + # XXX: currently criu require root containers. + requires criu root # criu does not work with external terminals so.. # setting terminal and root:readonly: to false diff --git a/tests/integration/delete.bats b/tests/integration/delete.bats index cdadd7dc..2c11e79b 100644 --- a/tests/integration/delete.bats +++ b/tests/integration/delete.bats @@ -22,11 +22,13 @@ function teardown() { testcontainer test_busybox running runc kill test_busybox KILL + [ "$status" -eq 0 ] # wait for busybox to be in the destroyed state retry 10 1 eval "__runc state test_busybox | grep -q 'stopped'" # delete test_busybox runc delete test_busybox + [ "$status" -eq 0 ] runc state test_busybox [ "$status" -ne 0 ] diff --git a/tests/integration/events.bats b/tests/integration/events.bats index 182b721b..23500733 100644 --- a/tests/integration/events.bats +++ b/tests/integration/events.bats @@ -12,6 +12,9 @@ function teardown() { } @test "events --stats" { + # XXX: currently cgroups require root containers. + requires root + # run busybox detached runc run -d --console-socket $CONSOLE_SOCKET test_busybox [ "$status" -eq 0 ] @@ -27,6 +30,9 @@ function teardown() { } @test "events --interval default " { + # XXX: currently cgroups require root containers. + requires root + # run busybox detached runc run -d --console-socket $CONSOLE_SOCKET test_busybox [ "$status" -eq 0 ] @@ -54,6 +60,9 @@ function teardown() { } @test "events --interval 1s " { + # XXX: currently cgroups require root containers. + requires root + # run busybox detached runc run -d --console-socket $CONSOLE_SOCKET test_busybox [ "$status" -eq 0 ] @@ -80,6 +89,9 @@ function teardown() { } @test "events --interval 100ms " { + # XXX: currently cgroups require root containers. + requires root + # run busybox detached runc run -d --console-socket $CONSOLE_SOCKET test_busybox [ "$status" -eq 0 ] diff --git a/tests/integration/exec.bats b/tests/integration/exec.bats index ba60ea17..f172f9bd 100644 --- a/tests/integration/exec.bats +++ b/tests/integration/exec.bats @@ -112,6 +112,9 @@ function teardown() { } @test "runc exec --user" { + # --user can't work in rootless containers + requires root + # run busybox detached runc run -d --console-socket $CONSOLE_SOCKET test_busybox [ "$status" -eq 0 ] diff --git a/tests/integration/help.bats b/tests/integration/help.bats index ca404f34..163de2d3 100644 --- a/tests/integration/help.bats +++ b/tests/integration/help.bats @@ -57,6 +57,7 @@ load helpers [ "$status" -eq 0 ] [[ ${lines[1]} =~ runc\ resume+ ]] + # We don't use runc_spec here, because we're just testing the help page. runc spec -h [ "$status" -eq 0 ] [[ ${lines[1]} =~ runc\ spec+ ]] diff --git a/tests/integration/helpers.bash b/tests/integration/helpers.bash index 65483332..fc8c2904 100644 --- a/tests/integration/helpers.bash +++ b/tests/integration/helpers.bash @@ -4,7 +4,7 @@ INTEGRATION_ROOT=$(dirname "$(readlink -f "$BASH_SOURCE")") RUNC="${INTEGRATION_ROOT}/../../runc" RECVTTY="${INTEGRATION_ROOT}/../../contrib/cmd/recvtty/recvtty" -GOPATH="${INTEGRATION_ROOT}/../../../.." +GOPATH="$(mktemp -d --tmpdir runc-integration-gopath.XXXXXX)" # Test data path. TESTDATA="${INTEGRATION_ROOT}/testdata" @@ -27,7 +27,7 @@ KERNEL_MINOR="${KERNEL_VERSION#$KERNEL_MAJOR.}" KERNEL_MINOR="${KERNEL_MINOR%%.*}" # Root state path. -ROOT="$BATS_TMPDIR/runc" +ROOT=$(mktemp -d "$BATS_TMPDIR/runc.XXXXXX") # Path to console socket. CONSOLE_SOCKET="$BATS_TMPDIR/console.sock" @@ -58,6 +58,17 @@ function __runc() { "$RUNC" --root "$ROOT" "$@" } +# Wrapper for runc spec. +function runc_spec() { + local args="" + + if [ "$ROOTLESS" -ne 0 ]; then + args+="--rootless" + fi + + runc spec $args "$@" +} + # Fails the current test, providing the error given. function fail() { echo "$@" >&2 @@ -187,18 +198,18 @@ function setup_busybox() { if [ ! -e $BUSYBOX_IMAGE ]; then curl -o $BUSYBOX_IMAGE -sSL 'https://github.com/docker-library/busybox/raw/a0558a9006ce0dd6f6ec5d56cfd3f32ebeeb815f/glibc/busybox.tar.xz' fi - tar -C "$BUSYBOX_BUNDLE"/rootfs -xf "$BUSYBOX_IMAGE" + tar --exclude './dev/*' -C "$BUSYBOX_BUNDLE"/rootfs -xf "$BUSYBOX_IMAGE" cd "$BUSYBOX_BUNDLE" - runc spec + runc_spec } function setup_hello() { setup_recvtty run mkdir "$HELLO_BUNDLE" run mkdir "$HELLO_BUNDLE"/rootfs - tar -C "$HELLO_BUNDLE"/rootfs -xf "$HELLO_IMAGE" + tar --exclude './dev/*' -C "$HELLO_BUNDLE"/rootfs -xf "$HELLO_IMAGE" cd "$HELLO_BUNDLE" - runc spec + runc_spec sed -i 's;"sh";"/hello";' config.json } diff --git a/tests/integration/ps.bats b/tests/integration/ps.bats index 7a200150..c000af66 100644 --- a/tests/integration/ps.bats +++ b/tests/integration/ps.bats @@ -12,6 +12,9 @@ function teardown() { } @test "ps" { + # ps is not supported, it requires cgroups + requires root + # start busybox detached runc run -d --console-socket $CONSOLE_SOCKET test_busybox [ "$status" -eq 0 ] @@ -24,10 +27,13 @@ function teardown() { runc ps test_busybox [ "$status" -eq 0 ] [[ ${lines[0]} =~ UID\ +PID\ +PPID\ +C\ +STIME\ +TTY\ +TIME\ +CMD+ ]] - [[ "${lines[1]}" == *"root"*[0-9]* ]] + [[ "${lines[1]}" == *"$(id -un 2>/dev/null)"*[0-9]* ]] } @test "ps -f json" { + # ps is not supported, it requires cgroups + requires root + # start busybox detached runc run -d --console-socket $CONSOLE_SOCKET test_busybox [ "$status" -eq 0 ] @@ -43,6 +49,9 @@ function teardown() { } @test "ps -e -x" { + # ps is not supported, it requires cgroups + requires root + # start busybox detached runc run -d --console-socket $CONSOLE_SOCKET test_busybox [ "$status" -eq 0 ] diff --git a/tests/integration/spec.bats b/tests/integration/spec.bats index 79bb6907..e9f28fbf 100644 --- a/tests/integration/spec.bats +++ b/tests/integration/spec.bats @@ -26,7 +26,7 @@ function teardown() { [ ! -e config.json ] # test generation of spec does not return an error - runc spec + runc_spec [ "$status" -eq 0 ] # test generation of spec created our config.json (spec) @@ -51,7 +51,7 @@ function teardown() { [ ! -e "$HELLO_BUNDLE"/config.json ] # test generation of spec does not return an error - runc spec --bundle "$HELLO_BUNDLE" + runc_spec --bundle "$HELLO_BUNDLE" [ "$status" -eq 0 ] # test generation of spec created our config.json (spec) diff --git a/tests/integration/start_detached.bats b/tests/integration/start_detached.bats index 605fde22..08036ddd 100644 --- a/tests/integration/start_detached.bats +++ b/tests/integration/start_detached.bats @@ -23,6 +23,9 @@ function teardown() { } @test "runc run detached ({u,g}id != 0)" { + # cannot start containers as another user in rootless setup + requires root + # replace "uid": 0 with "uid": 1000 # and do a similar thing for gid. sed -i 's;"uid": 0;"uid": 1000;g' config.json diff --git a/tests/integration/start_hello.bats b/tests/integration/start_hello.bats index 6de65e07..2e935728 100644 --- a/tests/integration/start_hello.bats +++ b/tests/integration/start_hello.bats @@ -21,6 +21,9 @@ function teardown() { } @test "runc run ({u,g}id != 0)" { + # cannot start containers as another user in rootless setup + requires root + # replace "uid": 0 with "uid": 1000 # and do a similar thing for gid. sed -i 's;"uid": 0;"uid": 1000;g' config.json diff --git a/tests/integration/state.bats b/tests/integration/state.bats index eed2eb3c..3772c1e5 100644 --- a/tests/integration/state.bats +++ b/tests/integration/state.bats @@ -11,7 +11,37 @@ function teardown() { teardown_busybox } -@test "state" { +@test "state (kill + delete)" { + runc state test_busybox + [ "$status" -ne 0 ] + + # run busybox detached + runc run -d --console-socket $CONSOLE_SOCKET test_busybox + [ "$status" -eq 0 ] + + # check state + wait_for_container 15 1 test_busybox + + testcontainer test_busybox running + + runc kill test_busybox KILL + [ "$status" -eq 0 ] + + # wait for busybox to be in the destroyed state + retry 10 1 eval "__runc state test_busybox | grep -q 'stopped'" + + # delete test_busybox + runc delete test_busybox + [ "$status" -eq 0 ] + + runc state test_busybox + [ "$status" -ne 0 ] +} + +@test "state (pause + resume)" { + # XXX: pause and resume require cgroups. + requires root + runc state test_busybox [ "$status" -ne 0 ] @@ -37,14 +67,4 @@ function teardown() { # test state of busybox is back to running testcontainer test_busybox running - - runc kill test_busybox KILL - # wait for busybox to be in the destroyed state - retry 10 1 eval "__runc state test_busybox | grep -q 'stopped'" - - # delete test_busybox - runc delete test_busybox - - runc state test_busybox - [ "$status" -ne 0 ] } diff --git a/tests/integration/tty.bats b/tests/integration/tty.bats index b9a1f108..9e817dbf 100644 --- a/tests/integration/tty.bats +++ b/tests/integration/tty.bats @@ -24,6 +24,10 @@ function teardown() { } @test "runc run [tty owner]" { + # tty chmod is not doable in rootless containers. + # TODO: this can be made as a change to the gid test. + requires root + # Replace sh script with stat. sed -i 's/"sh"/"sh", "-c", "stat -c %u:%g $(tty) | tr : \\\\\\\\n"/' config.json @@ -36,6 +40,9 @@ function teardown() { } @test "runc run [tty owner] ({u,g}id != 0)" { + # tty chmod is not doable in rootless containers. + requires root + # replace "uid": 0 with "uid": 1000 # and do a similar thing for gid. sed -i 's;"uid": 0;"uid": 1000;g' config.json @@ -72,6 +79,10 @@ function teardown() { } @test "runc exec [tty owner]" { + # tty chmod is not doable in rootless containers. + # TODO: this can be made as a change to the gid test. + requires root + # run busybox detached runc run -d --console-socket $CONSOLE_SOCKET test_busybox [ "$status" -eq 0 ] @@ -90,6 +101,9 @@ function teardown() { } @test "runc exec [tty owner] ({u,g}id != 0)" { + # tty chmod is not doable in rootless containers. + requires root + # replace "uid": 0 with "uid": 1000 # and do a similar thing for gid. sed -i 's;"uid": 0;"uid": 1000;g' config.json