github.com/opencontainers/runc@v1.2.0-rc.1.0.20240520010911-492dc558cdd6/tests/integration/delete.bats (about)

     1  #!/usr/bin/env bats
     2  
     3  load helpers
     4  
     5  function setup() {
     6  	setup_busybox
     7  }
     8  
     9  function teardown() {
    10  	teardown_bundle
    11  }
    12  
    13  # See also: "kill KILL [host pidns + init gone]" test in kill.bats.
    14  #
    15  # This needs to be placed at the top of the bats file to work around
    16  # a shellcheck bug. See <https://github.com/koalaman/shellcheck/issues/2873>.
    17  function test_runc_delete_host_pidns() {
    18  	requires cgroups_freezer
    19  
    20  	update_config '	  .linux.namespaces -= [{"type": "pid"}]'
    21  	set_cgroups_path
    22  	if [ $EUID -ne 0 ]; then
    23  		requires rootless_cgroup
    24  		# Apparently, for rootless test, when using systemd cgroup manager,
    25  		# newer versions of systemd clean up the container as soon as its init
    26  		# process is gone. This is all fine and dandy, except it prevents us to
    27  		# test this case, thus we skip the test.
    28  		#
    29  		# It is not entirely clear which systemd version got this feature:
    30  		# v245 works fine, and v249 does not.
    31  		if [ -v RUNC_USE_SYSTEMD ] && [ "$(systemd_version)" -gt 245 ]; then
    32  			skip "rootless+systemd conflicts with systemd > 245"
    33  		fi
    34  		# Can't mount real /proc when rootless + no pidns,
    35  		# so change it to a bind-mounted one from the host.
    36  		update_config '	  .mounts |= map((select(.type == "proc")
    37  					| .type = "none"
    38  					| .source = "/proc"
    39  					| .options = ["rbind", "nosuid", "nodev", "noexec"]
    40  				  ) // .)'
    41  	fi
    42  
    43  	runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
    44  	[ "$status" -eq 0 ]
    45  	cgpath=$(get_cgroup_path "pids")
    46  	init_pid=$(cat "$cgpath"/cgroup.procs)
    47  
    48  	# Start a few more processes.
    49  	for _ in 1 2 3 4 5; do
    50  		__runc exec -d test_busybox sleep 1h
    51  	done
    52  
    53  	# Now kill the container's init process. Since the container do
    54  	# not have own PID ns, its init is no special and the container
    55  	# will still be up and running.
    56  	kill -9 "$init_pid"
    57  	wait_pids_gone 10 0.2 "$init_pid"
    58  
    59  	# Get the list of all container processes.
    60  	mapfile -t pids < <(cat "$cgpath"/cgroup.procs)
    61  	echo "pids:" "${pids[@]}"
    62  	# Sanity check -- make sure all processes exist.
    63  	for p in "${pids[@]}"; do
    64  		kill -0 "$p"
    65  	done
    66  
    67  	# Must kill those processes and remove container.
    68  	runc delete "$@" test_busybox
    69  	[ "$status" -eq 0 ]
    70  
    71  	runc state test_busybox
    72  	[ "$status" -ne 0 ] # "Container does not exist"
    73  
    74  	# Wait and check that all the processes are gone.
    75  	wait_pids_gone 10 0.2 "${pids[@]}"
    76  
    77  	# Make sure cgroup.procs is empty.
    78  	mapfile -t pids < <(cat "$cgpath"/cgroup.procs || true)
    79  	if [ ${#pids[@]} -gt 0 ]; then
    80  		echo "expected empty cgroup.procs, got:" "${pids[@]}" 1>&2
    81  		return 1
    82  	fi
    83  }
    84  
    85  @test "runc delete" {
    86  	# Need a permission to create a cgroup.
    87  	# XXX(@kolyshkin): currently this test does not handle rootless when
    88  	# fs cgroup driver is used, because in this case cgroup (with a
    89  	# predefined name) is created by tests/rootless.sh, not by runc.
    90  	[ $EUID -ne 0 ] && requires systemd
    91  	set_resources_limit
    92  
    93  	runc run -d --console-socket "$CONSOLE_SOCKET" testbusyboxdelete
    94  	[ "$status" -eq 0 ]
    95  
    96  	testcontainer testbusyboxdelete running
    97  	# Ensure the find statement used later is correct.
    98  	output=$(find /sys/fs/cgroup -name testbusyboxdelete -o -name \*-testbusyboxdelete.scope 2>/dev/null || true)
    99  	if [ -z "$output" ]; then
   100  		fail "expected cgroup not found"
   101  	fi
   102  
   103  	runc kill testbusyboxdelete KILL
   104  	[ "$status" -eq 0 ]
   105  	wait_for_container 10 1 testbusyboxdelete stopped
   106  
   107  	runc delete testbusyboxdelete
   108  	[ "$status" -eq 0 ]
   109  
   110  	runc state testbusyboxdelete
   111  	[ "$status" -ne 0 ]
   112  
   113  	output=$(find /sys/fs/cgroup -name testbusyboxdelete -o -name \*-testbusyboxdelete.scope 2>/dev/null || true)
   114  	[ "$output" = "" ] || fail "cgroup not cleaned up correctly: $output"
   115  }
   116  
   117  @test "runc delete --force" {
   118  	# run busybox detached
   119  	runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
   120  	[ "$status" -eq 0 ]
   121  
   122  	# check state
   123  	testcontainer test_busybox running
   124  
   125  	# force delete test_busybox
   126  	runc delete --force test_busybox
   127  
   128  	runc state test_busybox
   129  	[ "$status" -ne 0 ]
   130  }
   131  
   132  @test "runc delete --force ignore not exist" {
   133  	runc delete --force notexists
   134  	[ "$status" -eq 0 ]
   135  }
   136  
   137  # Issue 4047, case "runc delete".
   138  @test "runc delete [host pidns + init gone]" {
   139  	test_runc_delete_host_pidns
   140  }
   141  
   142  # Issue 4047, case "runc delete --force" (different code path).
   143  @test "runc delete --force [host pidns + init gone]" {
   144  	test_runc_delete_host_pidns --force
   145  }
   146  
   147  @test "runc delete --force [paused container]" {
   148  	runc run -d --console-socket "$CONSOLE_SOCKET" ct1
   149  	[ "$status" -eq 0 ]
   150  	testcontainer ct1 running
   151  
   152  	runc pause ct1
   153  	runc delete --force ct1
   154  	[ "$status" -eq 0 ]
   155  }
   156  
   157  @test "runc delete --force in cgroupv1 with subcgroups" {
   158  	requires cgroups_v1 root cgroupns
   159  	set_cgroups_path
   160  	set_cgroup_mount_writable
   161  	# enable cgroupns
   162  	update_config '.linux.namespaces += [{"type": "cgroup"}]'
   163  
   164  	local subsystems="memory freezer"
   165  
   166  	runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
   167  	[ "$status" -eq 0 ]
   168  
   169  	testcontainer test_busybox running
   170  
   171  	__runc exec -d test_busybox sleep 1d
   172  
   173  	# find the pid of sleep
   174  	pid=$(__runc exec test_busybox ps -a | grep 1d | awk '{print $1}')
   175  	[[ ${pid} =~ [0-9]+ ]]
   176  
   177  	# create a sub-cgroup
   178  	cat <<EOF | runc exec test_busybox sh
   179  set -e -u -x
   180  for s in ${subsystems}; do
   181    cd /sys/fs/cgroup/\$s
   182    mkdir foo
   183    cd foo
   184    echo ${pid} > tasks
   185    cat tasks
   186  done
   187  EOF
   188  	[ "$status" -eq 0 ]
   189  	[[ "$output" =~ [0-9]+ ]]
   190  
   191  	for s in ${subsystems}; do
   192  		name=CGROUP_${s^^}_BASE_PATH
   193  		eval path=\$"${name}${REL_CGROUPS_PATH}/foo"
   194  		# shellcheck disable=SC2154
   195  		[ -d "${path}" ] || fail "test failed to create memory sub-cgroup ($path not found)"
   196  	done
   197  
   198  	runc delete --force test_busybox
   199  
   200  	runc state test_busybox
   201  	[ "$status" -ne 0 ]
   202  
   203  	output=$(find /sys/fs/cgroup -wholename '*testbusyboxdelete*' -type d 2>/dev/null || true)
   204  	[ "$output" = "" ] || fail "cgroup not cleaned up correctly: $output"
   205  }
   206  
   207  @test "runc delete --force in cgroupv2 with subcgroups" {
   208  	requires cgroups_v2 root
   209  	set_cgroups_path
   210  	set_cgroup_mount_writable
   211  
   212  	# run busybox detached
   213  	runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
   214  	[ "$status" -eq 0 ]
   215  
   216  	# check state
   217  	testcontainer test_busybox running
   218  
   219  	# create a sub process
   220  	__runc exec -d test_busybox sleep 1d
   221  
   222  	# find the pid of sleep
   223  	pid=$(__runc exec test_busybox ps -a | grep 1d | awk '{print $1}')
   224  	[[ ${pid} =~ [0-9]+ ]]
   225  
   226  	# create subcgroups
   227  	cat <<EOF >nest.sh
   228    set -e -u -x
   229    cd /sys/fs/cgroup
   230    echo +pids > cgroup.subtree_control
   231    mkdir foo
   232    cd foo
   233    echo threaded > cgroup.type
   234    echo ${pid} > cgroup.threads
   235    cat cgroup.threads
   236  EOF
   237  	runc exec test_busybox sh <nest.sh
   238  	[ "$status" -eq 0 ]
   239  	[[ "$output" =~ [0-9]+ ]]
   240  
   241  	# check create subcgroups success
   242  	[ -d "$CGROUP_V2_PATH"/foo ]
   243  
   244  	# force delete test_busybox
   245  	runc delete --force test_busybox
   246  
   247  	runc state test_busybox
   248  	[ "$status" -ne 0 ]
   249  
   250  	# check delete subcgroups success
   251  	[ ! -d "$CGROUP_V2_PATH"/foo ]
   252  }
   253  
   254  @test "runc delete removes failed systemd unit" {
   255  	requires systemd_v244 # Older systemd lacks RuntimeMaxSec support.
   256  
   257  	set_cgroups_path
   258  	update_config '	  .annotations += {
   259  				"org.systemd.property.RuntimeMaxSec": "2",
   260  				"org.systemd.property.TimeoutStopSec": "1"
   261  			   }
   262  			| .process.args |= ["/bin/sleep", "10"]'
   263  
   264  	runc run -d --console-socket "$CONSOLE_SOCKET" test-failed-unit
   265  	[ "$status" -eq 0 ]
   266  
   267  	wait_for_container 10 1 test-failed-unit stopped
   268  
   269  	local user=""
   270  	[ $EUID -ne 0 ] && user="--user"
   271  
   272  	# Expect "unit is not active" exit code.
   273  	run -3 systemctl status $user "$SD_UNIT_NAME"
   274  
   275  	runc delete test-failed-unit
   276  	# Expect "no such unit" exit code.
   277  	run -4 systemctl status $user "$SD_UNIT_NAME"
   278  }