github.com/containers/podman/v5@v5.1.0-rc1/test/system/220-healthcheck.bats (about) 1 #!/usr/bin/env bats -*- bats -*- 2 # 3 # tests for podman healthcheck 4 # 5 # 6 7 load helpers 8 9 10 # Helper function: run 'podman inspect' and check various given fields 11 function _check_health { 12 local testname="$1" 13 local tests="$2" 14 local since="$3" 15 local hc_status="$4" 16 17 run_podman inspect --format "{{json .State.Healthcheck}}" healthcheck_c 18 19 parse_table "$tests" | while read field expect;do 20 actual=$(jq ".$field" <<<"$output") 21 is "$actual" "$expect" "$testname - .State.Healthcheck.$field" 22 done 23 24 # Make sure we can read the healthcheck event in podman events (#20342) 25 run_podman events --filter container=healthcheck_c --filter event=health_status \ 26 --since "$since" --stream=false --format "{{.HealthStatus}}" 27 # Because the assert below would fail with "lines: bad array subscript" when 28 # there are no events lets special case this to provide a more meaningful error. 29 if [[ -z "$output" ]]; then 30 die "no healthcheck events" 31 fi 32 assert "${lines[-1]}" == "$hc_status" "$testname - podman events health status" 33 } 34 35 @test "podman healthcheck" { 36 run_podman run -d --name healthcheck_c \ 37 --health-cmd /home/podman/healthcheck \ 38 --health-interval 1s \ 39 --health-retries 3 \ 40 --health-on-failure=kill \ 41 $IMAGE /home/podman/pause 42 43 run_podman inspect healthcheck_c --format "{{.Config.HealthcheckOnFailureAction}}" 44 is "$output" "kill" "on-failure action is set to kill" 45 46 current_time=$(date --iso-8601=seconds) 47 # We can't check for 'starting' because a 1-second interval is too 48 # short; it could run healthcheck before we get to our first check. 49 # 50 # So, just force a healthcheck run, then confirm that it's running. 51 run_podman healthcheck run healthcheck_c 52 is "$output" "" "output from 'podman healthcheck run'" 53 54 _check_health "All healthy" " 55 Status | \"healthy\" 56 FailingStreak | 0 57 Log[-1].ExitCode | 0 58 Log[-1].Output | \"Life is Good on stdout\\\nLife is Good on stderr\" 59 " "$current_time" "healthy" 60 61 current_time=$(date --iso-8601=seconds) 62 # Force a failure 63 run_podman exec healthcheck_c touch /uh-oh 64 sleep 2 65 66 _check_health "First failure" " 67 Status | \"healthy\" 68 FailingStreak | [123] 69 Log[-1].ExitCode | 1 70 Log[-1].Output | \"Uh-oh on stdout!\\\nUh-oh on stderr!\" 71 " "$current_time" "healthy" 72 73 current_time=$(date --iso-8601=seconds) 74 # After three successive failures, container should no longer be healthy 75 sleep 5 76 _check_health "Three or more failures" " 77 Status | \"unhealthy\" 78 FailingStreak | [3456] 79 Log[-1].ExitCode | 1 80 Log[-1].Output | \"Uh-oh on stdout!\\\nUh-oh on stderr!\" 81 " "$current_time" "unhealthy" 82 83 # now the on-failure should kick in and kill the container 84 run_podman wait healthcheck_c 85 86 # Clean up 87 run_podman rm -t 0 -f healthcheck_c 88 } 89 90 @test "podman healthcheck - restart cleans up old state" { 91 ctr="healthcheck_c" 92 93 run_podman run -d --name $ctr \ 94 --health-cmd /home/podman/healthcheck \ 95 --health-retries=3 \ 96 --health-interval=disable \ 97 $IMAGE /home/podman/pause 98 99 run_podman container inspect $ctr --format "{{.State.Healthcheck.FailingStreak}}" 100 is "$output" "0" "Failing streak of fresh container should be 0" 101 102 # Get the healthcheck to fail 103 run_podman exec $ctr touch /uh-oh-only-once 104 run_podman 1 healthcheck run $ctr 105 is "$output" "unhealthy" "output from 'podman healthcheck run'" 106 run_podman container inspect $ctr --format "{{.State.Healthcheck.FailingStreak}}" 107 is "$output" "1" "Failing streak after one failed healthcheck should be 1" 108 109 run_podman container restart $ctr 110 run_podman container inspect $ctr --format "{{.State.Healthcheck.FailingStreak}}" 111 is "$output" "0" "Failing streak of restarted container should be 0 again" 112 113 run_podman rm -f -t0 $ctr 114 } 115 116 @test "podman wait --condition={healthy,unhealthy}" { 117 ctr="healthcheck_c" 118 119 wait_file="$PODMAN_TMPDIR/$(random_string).wait_for_me" 120 121 for condition in healthy unhealthy;do 122 rm -f $wait_file 123 run_podman run -d --name $ctr \ 124 --health-cmd /home/podman/healthcheck \ 125 --health-retries=1 \ 126 --health-interval=disable \ 127 $IMAGE /home/podman/pause 128 if [[ $condition == "unhealthy" ]];then 129 # create the uh-oh file to let the health check fail 130 run_podman exec $ctr touch /uh-oh 131 fi 132 133 # Wait for the container in the background and create the $wait_file to 134 # signal the specified wait condition was met. 135 (timeout --foreground -v --kill=5 5 $PODMAN wait --condition=$condition $ctr && touch $wait_file) & 136 137 # Sleep 1 second to make sure above commands are running 138 sleep 1 139 if [[ -f $wait_file ]]; then 140 die "the wait file should only be created after the container turned healthy" 141 fi 142 143 if [[ $condition == "healthy" ]];then 144 run_podman healthcheck run $ctr 145 else 146 run_podman 1 healthcheck run $ctr 147 fi 148 wait_for_file $wait_file 149 run_podman rm -f -t0 $ctr 150 done 151 } 152 153 @test "podman healthcheck --health-on-failure" { 154 run_podman 125 create --health-on-failure=kill $IMAGE 155 is "$output" "Error: cannot set on-failure action to kill without a health check" 156 157 ctr="healthcheck_c" 158 159 for policy in none kill restart stop;do 160 uhoh=/uh-oh 161 if [[ $policy != "none" ]];then 162 # only fail the first run 163 uhoh=/uh-oh-only-once 164 fi 165 166 # Run healthcheck image. 167 run_podman run -d --name $ctr \ 168 --health-cmd /home/podman/healthcheck \ 169 --health-retries=1 \ 170 --health-on-failure=$policy \ 171 --health-interval=disable \ 172 $IMAGE /home/podman/pause 173 174 # healthcheck should succeed 175 run_podman healthcheck run $ctr 176 177 # Now cause the healthcheck to fail 178 run_podman exec $ctr touch $uhoh 179 180 # healthcheck should now fail, with exit status 1 and 'unhealthy' output 181 run_podman 1 healthcheck run $ctr 182 is "$output" "unhealthy" "output from 'podman healthcheck run' (policy: $policy)" 183 184 if [[ $policy == "restart" ]];then 185 # Make sure the container transitions back to running 186 run_podman wait --condition=running $ctr 187 run_podman inspect $ctr --format "{{.RestartCount}}" 188 assert "${#lines[@]}" != 0 "Container has been restarted at least once" 189 run_podman container inspect $ctr --format "{{.State.Healthcheck.FailingStreak}}" 190 is "$output" "0" "Failing streak of restarted container should be 0 again" 191 run_podman healthcheck run $ctr 192 elif [[ $policy == "none" ]];then 193 run_podman inspect $ctr --format "{{.State.Status}} {{.Config.HealthcheckOnFailureAction}}" 194 # Container is still running and health check still broken 195 is "$output" "running $policy" "container continued running" 196 run_podman 1 healthcheck run $ctr 197 is "$output" "unhealthy" "output from 'podman healthcheck run' (policy: $policy)" 198 else 199 run_podman inspect $ctr --format "{{.State.Status}} {{.Config.HealthcheckOnFailureAction}}" 200 # kill and stop yield the container into a non-running state 201 is "$output" ".* $policy" "container was stopped/killed (policy: $policy)" 202 assert "$output" != "running $policy" 203 # also make sure that it's not stuck in the stopping state 204 assert "$output" != "stopping $policy" 205 fi 206 207 run_podman rm -f -t0 $ctr 208 done 209 } 210 211 @test "podman healthcheck --health-on-failure with interval" { 212 ctr="healthcheck_c" 213 214 for policy in stop kill restart ;do 215 t0=$(date --iso-8601=seconds) 216 run_podman run -d --name $ctr \ 217 --health-cmd /bin/false \ 218 --health-retries=1 \ 219 --health-on-failure=$policy \ 220 --health-interval=1s \ 221 $IMAGE top 222 223 if [[ $policy == "restart" ]];then 224 # Sleeping for 2 seconds makes the test much faster than using 225 # podman-wait which would compete with the container getting 226 # restarted. 227 sleep 2 228 # Make sure the container transitions back to running 229 run_podman wait --condition=running $ctr 230 run_podman inspect $ctr --format "{{.RestartCount}}" 231 assert "${#lines[@]}" != 0 "Container has been restarted at least once" 232 else 233 # kill and stop yield the container into a non-running state 234 run_podman wait $ctr 235 run_podman inspect $ctr --format "{{.State.Status}} {{.Config.HealthcheckOnFailureAction}}" 236 is "$output" ".* $policy" "container was stopped/killed (policy: $policy)" 237 assert "$output" != "running $policy" 238 # also make sure that it's not stuck in the stopping state 239 assert "$output" != "stopping $policy" 240 fi 241 242 run_podman rm -f -t0 $ctr 243 done 244 } 245 246 # vim: filetype=sh