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 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..59abeece05 --- /dev/null +++ b/tests/integration/runk/runk-tests.bats @@ -0,0 +1,123 @@ +#!/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="quay.io/prometheus/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 + # 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)" + 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