From 8a606eb94dc14b38ff57e2a14cc2a227532dab08 Mon Sep 17 00:00:00 2001 From: Wainer dos Santos Moschetta Date: Fri, 2 Feb 2024 16:12:33 -0300 Subject: [PATCH 1/4] tests/runk: convert to bats Migrated runk tests from pure shell script to bats to be consistent with other test suites. The install_dependencies() will install the bats tool locally. Signed-off-by: Wainer dos Santos Moschetta --- tests/integration/runk/gha-run.sh | 6 +- tests/integration/runk/runk-tests.bats | 121 +++++++++++++++++++++++++ tests/integration/runk/runk-tests.sh | 103 --------------------- 3 files changed, 126 insertions(+), 104 deletions(-) create mode 100644 tests/integration/runk/runk-tests.bats delete mode 100755 tests/integration/runk/runk-tests.sh diff --git a/tests/integration/runk/gha-run.sh b/tests/integration/runk/gha-run.sh index 3f97c63aab..2fcddedcec 100755 --- a/tests/integration/runk/gha-run.sh +++ b/tests/integration/runk/gha-run.sh @@ -12,6 +12,7 @@ set -o pipefail kata_tarball_dir="${2:-kata-artifacts}" runk_dir="$(dirname "$(readlink -f "$0")")" source "${runk_dir}/../../common.bash" +source "${runk_dir}/../../gha-run-k8s-common.sh" function install_dependencies() { info "Installing the dependencies needed for running the runk tests" @@ -38,12 +39,15 @@ function install_dependencies() { IFS=":" read -r -a dep <<< "${github_dep}" install_${dep[0]} "${dep[1]}" done + + # Requires bats to run the tests + install_bats } function run() { info "Running runk tests using" - bash -c ${runk_dir}/runk-tests.sh + bats "${runk_dir}/runk-tests.bats" } function main() { diff --git a/tests/integration/runk/runk-tests.bats b/tests/integration/runk/runk-tests.bats new file mode 100644 index 0000000000..f1f5e5d41b --- /dev/null +++ b/tests/integration/runk/runk-tests.bats @@ -0,0 +1,121 @@ +#!/usr/bin/env bats +# +# Copyright (c) 2023,2024 Kata Contributors +# +# SPDX-License-Identifier: Apache-2.0 +# +# This test will validate runk with containerd + +load "${BATS_TEST_DIRNAME}/../../common.bash" +load "${BATS_TEST_DIRNAME}/../../metrics/lib/common.bash" + +setup_file() { + export RUNK_BIN_PATH="/usr/local/bin/runk" + export TEST_IMAGE="docker.io/library/busybox:latest" + export CONTAINER_ID="id1" + export PID_FILE="${CONTAINER_ID}.pid" + export WORK_DIR="${BATS_FILE_TMPDIR}" + + echo "pull container image" + check_images ${TEST_IMAGE} +} + +setup() { + # Bind mount ${WORK_DIR}:/tmp. Tests below will store files in this dir and check them when container is frozon. + sudo ctr run --pid-file ${PID_FILE} -d \ + --mount type=bind,src=${WORK_DIR},dst=/tmp,options=rbind:rw \ + --runc-binary ${RUNK_BIN_PATH} \ + ${TEST_IMAGE} \ + ${CONTAINER_ID} + read CID PID STATUS <<< $(sudo ctr t ls | grep ${CONTAINER_ID}) + # Check the pid is consistent + [ "${PID}" == "$(cat "${PID_FILE}")" ] + # Check the container status is RUNNING + [ "${STATUS}" == "RUNNING" ] +} + +teardown() { + echo "delete the container" + if sudo ctr t list -q | grep -q "${CONTAINER_ID}"; then + stop_container + fi + sudo ctr c rm "${CONTAINER_ID}" + sudo rm -f "${PID_FILE}" +} + +stop_container() { + local cmd + sudo ctr t kill --signal SIGKILL --all "${CONTAINER_ID}" + # poll for a while until the task receives signal and exit + cmd='[ "STOPPED" == "$(sudo ctr t ls | grep ${CONTAINER_ID} | awk "{print \$3}")" ]' + waitForProcess 10 1 "${cmd}" + + echo "check the container is stopped" + # there is only title line of ps command + [ "1" == "$(sudo ctr t ps ${CONTAINER_ID} | wc -l)" ] +} + +@test "start container with runk" { +} + +@test "exec process in a container" { + sudo ctr t exec --exec-id id1 "${CONTAINER_ID}" sh -c "echo hello > /tmp/foo" + # Check exec succeeded + [ "hello" == "$(sudo ctr t exec --exec-id id1 "${CONTAINER_ID}" cat /tmp/foo)" ] +} + +@test "run ps command" { + sudo ctr t exec --detach --exec-id id1 "${CONTAINER_ID}" sh + ps_out="$(sudo ctr t ps ${CONTAINER_ID})" || die "ps command failed" + printf "ps output:\n%s\n" "${ps_out}" + lines_no="$(printf "%s\n" "${ps_out}" | wc -l)" + echo "ps output lines: ${lines_no}" + # one line is the titles, and the other 2 lines are process info + [ "3" == "${lines_no}" ] +} + +@test "pause and resume the container" { + # The process outputs lines into /tmp/{CONTAINER_ID}, which can be read in host when it's frozon. + sudo ctr t exec --detach --exec-id id2 ${CONTAINER_ID} \ + sh -c "while true; do echo hello >> /tmp/${CONTAINER_ID}; sleep 0.1; done" + # sleep for 1s to make sure the process outputs some lines + sleep 1 + sudo ctr t pause "${CONTAINER_ID}" + # Check the status is PAUSED + [ "PAUSED" == "$(sudo ctr t ls | grep ${CONTAINER_ID} | grep -o PAUSED)" ] + echo "container is paused" + local TMP_FILE="${WORK_DIR}/${CONTAINER_ID}" + local lines1=$(cat ${TMP_FILE} | wc -l) + # sleep for a while and check the lines are not changed. + sleep 1 + local lines2=$(cat ${TMP_FILE} | wc -l) + # Check the paused container is not running the process (paused indeed) + [ ${lines1} == ${lines2} ] + sudo ctr t resume ${CONTAINER_ID} + # Check the resumed container has status of RUNNING + [ "RUNNING" == "$(sudo ctr t ls | grep ${CONTAINER_ID} | grep -o RUNNING)" ] + echo "container is resumed" + # sleep for a while and check the lines are changed. + sleep 1 + local lines3=$(cat ${TMP_FILE} | wc -l) + # Check the process is running again + [ ${lines2} -lt ${lines3} ] +} + +@test "kill the container and poll until it is stopped" { + stop_container +} + +@test "kill --all is allowed regardless of the container state" { + # High-level container runtimes such as containerd call the kill command with + # --all option in order to terminate all processes inside the container + # even if the container already is stopped. Hence, a low-level runtime + # should allow kill --all regardless of the container state like runc. + echo "test kill --all is allowed regardless of the container state" + # Check kill should fail because the container is paused + stop_container + run sudo ctr t kill --signal SIGKILL ${CONTAINER_ID} + [ $status -eq 1 ] + # Check kill --all should not fail + sudo ctr t kill --signal SIGKILL --all "${CONTAINER_ID}" +} diff --git a/tests/integration/runk/runk-tests.sh b/tests/integration/runk/runk-tests.sh deleted file mode 100755 index 210c60d845..0000000000 --- a/tests/integration/runk/runk-tests.sh +++ /dev/null @@ -1,103 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2023 Kata Contributors -# -# SPDX-License-Identifier: Apache-2.0 -# -# This test will validate runk with containerd - -set -o errexit -set -o nounset -set -o pipefail -set -o errtrace - -tracing_dir="$(dirname "$(readlink -f "$0")")" -source "${tracing_dir}/../../common.bash" -source "${tracing_dir}/../../metrics/lib/common.bash" - -RUNK_BIN_PATH="/usr/local/bin/runk" -TEST_IMAGE="docker.io/library/busybox:latest" -CONTAINER_ID="id1" -PID_FILE="${CONTAINER_ID}.pid" -WORK_DIR="$(mktemp -d --tmpdir runk.XXXXX)" - -setup() { - echo "pull container image" - check_images ${TEST_IMAGE} -} - -test_runk() { - echo "start container with runk" - # Bind mount ${WORK_DIR}:/tmp. Tests below will store files in this dir and check them when container is frozon. - sudo ctr run --pid-file ${PID_FILE} -d --runc-binary ${RUNK_BIN_PATH} --mount type=bind,src=${WORK_DIR},dst=/tmp,options=rbind:rw ${TEST_IMAGE} ${CONTAINER_ID} - read CID PID STATUS <<< $(sudo ctr t ls | grep ${CONTAINER_ID}) - [ ${PID} == $(cat ${PID_FILE}) ] || die "pid is not consistent" - [ ${STATUS} == "RUNNING" ] || die "container status is not RUNNING" - - echo "exec process in a container" - sudo ctr t exec --exec-id id1 ${CONTAINER_ID} sh -c "echo hello > /tmp/foo" - [ "hello" == "$(sudo ctr t exec --exec-id id1 ${CONTAINER_ID} cat /tmp/foo)" ] || die "exec process failed" - - echo "test ps command" - sudo ctr t exec --detach --exec-id id1 ${CONTAINER_ID} sh - ps_out="$(sudo ctr t ps ${CONTAINER_ID})" || die "ps command failed" - printf "ps output:\n%s\n" "${ps_out}" - lines_no="$(printf "%s\n" "${ps_out}" | wc -l)" - echo "ps output lines: ${lines_no}" - # one line is the titles, and the other 2 lines are process info - [ "3" == "${lines_no}" ] || die "unexpected ps command output" - - echo "test pause and resume" - # The process outputs lines into /tmp/{CONTAINER_ID}, which can be read in host when it's frozon. - sudo ctr t exec --detach --exec-id id2 ${CONTAINER_ID} sh -c "while true; do echo hello >> /tmp/${CONTAINER_ID}; sleep 0.1; done" - # sleep for 1s to make sure the process outputs some lines - sleep 1 - sudo ctr t pause ${CONTAINER_ID} - [ "PAUSED" == "$(sudo ctr t ls | grep ${CONTAINER_ID} | grep -o PAUSED)" ] || die "status is not PAUSED" - echo "container is paused" - local TMP_FILE="${WORK_DIR}/${CONTAINER_ID}" - local lines1=$(cat ${TMP_FILE} | wc -l) - # sleep for a while and check the lines are not changed. - sleep 1 - local lines2=$(cat ${TMP_FILE} | wc -l) - [ ${lines1} == ${lines2} ] || die "paused container is still running" - sudo ctr t resume ${CONTAINER_ID} - [ "RUNNING" == "$(sudo ctr t ls | grep ${CONTAINER_ID} | grep -o RUNNING)" ] || die "status is not RUNNING" - echo "container is resumed" - # sleep for a while and check the lines are changed. - sleep 1 - local lines3=$(cat ${TMP_FILE} | wc -l) - [ ${lines2} -lt ${lines3} ] || die "resumed container is not running" - - echo "kill the container and poll until it is stopped" - sudo ctr t kill --signal SIGKILL --all ${CONTAINER_ID} - # poll for a while until the task receives signal and exit - local cmd='[ "STOPPED" == "$(sudo ctr t ls | grep ${CONTAINER_ID} | awk "{print \$3}")" ]' - waitForProcess 10 1 "${cmd}" || die "failed to kill task" - - echo "check the container is stopped" - # there is only title line of ps command - [ "1" == "$(sudo ctr t ps ${CONTAINER_ID} | wc -l)" ] || die "kill command failed" - - # High-level container runtimes such as containerd call the kill command with - # --all option in order to terminate all processes inside the container - # even if the container already is stopped. Hence, a low-level runtime - # should allow kill --all regardless of the container state like runc. - echo "test kill --all is allowed regardless of the container state" - sudo ctr t kill --signal SIGKILL ${CONTAINER_ID} && die "kill should fail" - sudo ctr t kill --signal SIGKILL --all ${CONTAINER_ID} || die "kill --all should not fail" - - echo "delete the container" - sudo ctr t rm ${CONTAINER_ID} - [ -z "$(sudo ctr t ls | grep ${CONTAINER_ID})" ] || die "failed to delete task" - sudo ctr c rm ${CONTAINER_ID} || die "failed to delete container" -} - -clean_up() { - rm -f ${PID_FILE} - rm -rf ${WORK_DIR} -} - -setup -test_runk -clean_up From 28a63070f7a75cc3f4215de487dc636251df6929 Mon Sep 17 00:00:00 2001 From: Wainer dos Santos Moschetta Date: Fri, 2 Feb 2024 16:25:36 -0300 Subject: [PATCH 2/4] gha: fix step name in run-runk-tests Likely copied from the tracing workflow by mistake. Signed-off-by: Wainer dos Santos Moschetta --- .github/workflows/run-runk-tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-runk-tests.yaml b/.github/workflows/run-runk-tests.yaml index 36c111218a..51f457b9b1 100644 --- a/.github/workflows/run-runk-tests.yaml +++ b/.github/workflows/run-runk-tests.yaml @@ -42,5 +42,5 @@ jobs: - name: Install kata run: bash tests/integration/runk/gha-run.sh install-kata kata-artifacts - - name: Run tracing tests + - name: Run runk tests run: bash tests/integration/runk/gha-run.sh run From bba8b5b2b460121a5e9acb392881985f67522511 Mon Sep 17 00:00:00 2001 From: Wainer dos Santos Moschetta Date: Fri, 2 Feb 2024 16:34:15 -0300 Subject: [PATCH 3/4] tests/runk: fix flaky test The "run ps command" test has failed once in a while because it doesn't wait the sh command to start within the container, consequently `ps` won't report the amount of lines expected. Fixes #8975 Signed-off-by: Manabu Sugimoto Signed-off-by: Wainer dos Santos Moschetta --- tests/integration/runk/runk-tests.bats | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/integration/runk/runk-tests.bats b/tests/integration/runk/runk-tests.bats index f1f5e5d41b..6f987235e6 100644 --- a/tests/integration/runk/runk-tests.bats +++ b/tests/integration/runk/runk-tests.bats @@ -66,6 +66,8 @@ stop_container() { @test "run ps command" { sudo ctr t exec --detach --exec-id id1 "${CONTAINER_ID}" sh + # Give some time for the sh process to start within the container. + sleep 1 ps_out="$(sudo ctr t ps ${CONTAINER_ID})" || die "ps command failed" printf "ps output:\n%s\n" "${ps_out}" lines_no="$(printf "%s\n" "${ps_out}" | wc -l)" From 0f0ce9a81b6ef2797a1faded31b9c55dbfe599da Mon Sep 17 00:00:00 2001 From: Wainer dos Santos Moschetta Date: Mon, 26 Feb 2024 11:11:05 -0300 Subject: [PATCH 4/4] tests/runk: replace the busybox image It's recommended to avoid images from docker.io to avoid errors related with hitting the pull limits that happens mostly on bare-metal machines. So this replaced the docker.io's busybox with quay.io/prometheus/busybox. Signed-off-by: Wainer dos Santos Moschetta --- tests/integration/runk/runk-tests.bats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/runk/runk-tests.bats b/tests/integration/runk/runk-tests.bats index 6f987235e6..59abeece05 100644 --- a/tests/integration/runk/runk-tests.bats +++ b/tests/integration/runk/runk-tests.bats @@ -11,7 +11,7 @@ load "${BATS_TEST_DIRNAME}/../../metrics/lib/common.bash" setup_file() { export RUNK_BIN_PATH="/usr/local/bin/runk" - export TEST_IMAGE="docker.io/library/busybox:latest" + export TEST_IMAGE="quay.io/prometheus/busybox:latest" export CONTAINER_ID="id1" export PID_FILE="${CONTAINER_ID}.pid" export WORK_DIR="${BATS_FILE_TMPDIR}"