github.com/containers/podman/v5@v5.1.0-rc1/test/system/035-logs.bats (about) 1 #!/usr/bin/env bats -*- bats -*- 2 # 3 # Basic tests for podman logs 4 # 5 6 load helpers 7 8 @test "podman logs - basic test" { 9 rand_string=$(random_string 40) 10 11 run_podman create $IMAGE echo $rand_string 12 cid="$output" 13 14 run_podman logs $cid 15 is "$output" "" "logs on created container: empty" 16 17 run_podman start --attach --interactive $cid 18 is "$output" "$rand_string" "output from podman-start on created ctr" 19 is "$output" "$rand_string" "logs of started container" 20 21 run_podman logs $cid 22 is "$output" "$rand_string" "output from podman-logs after container is run" 23 24 # test --since with Unix timestamps 25 run_podman logs --since 1000 $cid 26 27 # test --until with Unix timestamps 28 run_podman logs --until 1000 $cid 29 30 run_podman rm $cid 31 } 32 33 function _log_test_tail() { 34 local driver=$1 35 36 run_podman run -d --log-driver=$driver $IMAGE sh -c "echo test1; echo test2" 37 cid="$output" 38 39 run_podman wait $cid 40 run_podman logs --tail 1 --timestamps $cid 41 log1="$output" 42 assert "$log1" =~ "^[0-9-]+T[0-9:.]+([\+-][0-9:]+|Z) test2" \ 43 "logs should only show last line" 44 45 # Sigh. I hate doing this, but podman-remote --timestamp only has 1-second 46 # resolution (regular podman has sub-second). For the timestamps-differ 47 # check below, we need to force a different second. 48 if is_remote; then 49 sleep 2 50 fi 51 52 run_podman restart $cid 53 run_podman wait $cid 54 55 run_podman logs -t --tail 1 $cid 56 log2="$output" 57 assert "$log2" =~ "^[0-9-]+T[0-9:.]+([\+-][0-9:]+|Z) test2" \ 58 "logs, after restart, shows only last line" 59 60 assert "$log2" != "$log1" "log timestamps should differ" 61 62 run_podman rm $cid 63 } 64 65 @test "podman logs - tail test, k8s-file" { 66 _log_test_tail k8s-file 67 } 68 69 @test "podman logs - tail test, journald" { 70 # We can't use journald on RHEL as rootless: rhbz#1895105 71 skip_if_journald_unavailable 72 73 _log_test_tail journald 74 } 75 76 function _additional_events_backend() { 77 local driver=$1 78 # Since PR#10431, 'logs -f' with journald driver is only supported with journald events backend. 79 if [[ $driver = "journald" ]]; then 80 run_podman info --format '{{.Host.EventLogger}}' >/dev/null 81 if [[ $output != "journald" ]]; then 82 echo "--events-backend journald" 83 fi 84 fi 85 } 86 87 function _log_test_multi() { 88 local driver=$1 89 90 skip_if_remote "logs does not support multiple containers when run remotely" 91 92 # Under k8s file, 'podman logs' returns just the facts, Ma'am. 93 # Under journald, there may be other cruft (e.g. container removals) 94 local etc= 95 if [[ $driver =~ journal ]]; then 96 etc='.*' 97 fi 98 99 local events_backend=$(_additional_events_backend $driver) 100 101 # Simple helper to make the container starts, below, easier to read 102 local -a cid 103 doit() { 104 run_podman ${events_backend} run --log-driver=$driver --rm -d --name "$1" $IMAGE sh -c "$2"; 105 cid+=($(echo "${output:0:12}")) 106 } 107 108 # Not really a guarantee that we'll get a-b-c-d in order, but it's 109 # the best we can do. The trailing 'sleep' in each container 110 # minimizes the chance of a race condition in which the container 111 # is removed before 'podman logs' has a chance to wake up and read 112 # the final output. 113 doit c1 "echo a;sleep 10;echo d;sleep 3" 114 doit c2 "sleep 1;echo b;sleep 2;echo c;sleep 3" 115 116 run_podman ${events_backend} logs -f c1 c2 117 assert "$output" =~ \ 118 "${cid[0]} a$etc 119 ${cid[1]} b$etc 120 ${cid[1]} c$etc 121 ${cid[0]} d" "Sequential output from logs" 122 } 123 124 @test "podman logs - multi k8s-file" { 125 _log_test_multi k8s-file 126 } 127 128 @test "podman logs - multi journald" { 129 # We can't use journald on RHEL as rootless: rhbz#1895105 130 skip_if_journald_unavailable 131 132 _log_test_multi journald 133 } 134 135 function _log_test_restarted() { 136 local driver=$1 137 local events_backend=$(_additional_events_backend $driver) 138 if [[ -n "${events_backend}" ]]; then 139 skip_if_remote "remote does not support --events-backend" 140 fi 141 run_podman run --log-driver=$driver ${events_backend} --name logtest $IMAGE sh -c 'start=0; if test -s log; then start=`tail -n 1 log`; fi; seq `expr $start + 1` `expr $start + 10` | tee -a log' 142 # FIXME: #9597 143 # run/start is flaking for remote so let's wait for the container condition 144 # to stop wasting energy until the root cause gets fixed. 145 run_podman container wait --condition=exited --condition=stopped logtest 146 run_podman ${events_backend} start -a logtest 147 logfile=$(mktemp -p ${PODMAN_TMPDIR} logfileXXXXXXXX) 148 $PODMAN $_PODMAN_TEST_OPTS ${events_backend} logs -f logtest > $logfile 149 expected=$(mktemp -p ${PODMAN_TMPDIR} expectedXXXXXXXX) 150 seq 1 20 > $expected 151 diff -u ${expected} ${logfile} 152 } 153 154 @test "podman logs restarted - k8s-file" { 155 _log_test_restarted k8s-file 156 } 157 158 @test "podman logs restarted journald" { 159 # We can't use journald on RHEL as rootless: rhbz#1895105 160 skip_if_journald_unavailable 161 162 _log_test_restarted journald 163 } 164 165 @test "podman logs - journald log driver requires journald events backend" { 166 skip_if_remote "remote does not support --events-backend" 167 # We can't use journald on RHEL as rootless: rhbz#1895105 168 skip_if_journald_unavailable 169 170 run_podman --events-backend=file run --log-driver=journald -d --name test --replace $IMAGE ls / 171 run_podman --events-backend=file logs test 172 run_podman 125 --events-backend=file logs --follow test 173 is "$output" "Error: using --follow with the journald --log-driver but without the journald --events-backend (file) is not supported" "journald logger requires journald eventer" 174 } 175 176 function _log_test_since() { 177 local driver=$1 178 179 s_before="before_$(random_string)_${driver}" 180 s_after="after_$(random_string)_${driver}" 181 182 before=$(date --iso-8601=seconds) 183 run_podman run --log-driver=$driver -d --name test $IMAGE sh -c \ 184 "echo $s_before; trap 'echo $s_after; exit' SIGTERM; while :; do sleep 0.1; done" 185 wait_for_output "$s_before" test 186 187 # sleep a second to make sure the date is after the first echo 188 # (We could instead use iso-8601=ns but seconds feels more real-world) 189 sleep 1 190 after=$(date --iso-8601=seconds) 191 run_podman stop test 192 193 run_podman logs test 194 is "$output" \ 195 "$s_before 196 $s_after" 197 198 run_podman logs --since $before test 199 is "$output" \ 200 "$s_before 201 $s_after" 202 203 run_podman logs --since $after test 204 is "$output" "$s_after" 205 run_podman rm -t 1 -f test 206 } 207 208 @test "podman logs - since k8s-file" { 209 _log_test_since k8s-file 210 } 211 212 @test "podman logs - since journald" { 213 # We can't use journald on RHEL as rootless: rhbz#1895105 214 skip_if_journald_unavailable 215 216 _log_test_since journald 217 } 218 219 function _log_test_until() { 220 local driver=$1 221 222 s_before="before_$(random_string)_${driver}" 223 s_after="after_$(random_string)_${driver}" 224 225 before=$(date --iso-8601=seconds) 226 sleep 1 227 run_podman run --log-driver=$driver -d --name test $IMAGE sh -c \ 228 "echo $s_before; trap 'echo $s_after; exit' SIGTERM; while :; do sleep 0.1; done" 229 230 # sleep a second to make sure the date is after the first echo 231 sleep 1 232 run_podman stop test 233 run_podman wait test 234 235 # Sigh. Stupid journald has a lag. Wait a few seconds for it to catch up. 236 retries=20 237 s_both="$s_before 238 $s_after" 239 while [[ $retries -gt 0 ]]; do 240 run_podman logs test 241 if [[ "$output" = "$s_both" ]]; then 242 break 243 fi 244 retries=$((retries - 1)) 245 sleep 0.1 246 done 247 assert $retries -gt 0 \ 248 "Timed out waiting for before&after in podman logs: $output" 249 250 run_podman logs --until $before test 251 is "$output" "" "podman logs --until before" 252 253 after=$(date --date='+1 second' --iso-8601=ns) 254 255 run_podman logs --until $after test 256 is "$output" "$s_both" "podman logs --until after" 257 run_podman rm -t 0 -f test 258 } 259 260 @test "podman logs - until k8s-file" { 261 _log_test_until k8s-file 262 } 263 264 @test "podman logs - until journald" { 265 # We can't use journald on RHEL as rootless: rhbz#1895105 266 skip_if_journald_unavailable 267 268 _log_test_until journald 269 } 270 271 function _log_test_follow() { 272 local driver=$1 273 cname=$(random_string) 274 contentA=$(random_string) 275 contentB=$(random_string) 276 contentC=$(random_string) 277 local events_backend=$(_additional_events_backend $driver) 278 279 if [[ -n "${events_backend}" ]]; then 280 skip_if_remote "remote does not support --events-backend" 281 fi 282 283 # Note: it seems we need at least three log lines to hit #11461. 284 run_podman ${events_backend} run --log-driver=$driver --name $cname $IMAGE sh -c "echo $contentA; echo $contentB; echo $contentC" 285 run_podman ${events_backend} logs -f $cname 286 is "$output" "$contentA 287 $contentB 288 $contentC" "logs -f on exited container works" 289 290 run_podman ${events_backend} rm -t 0 -f $cname 291 } 292 293 @test "podman logs - --follow k8s-file" { 294 _log_test_follow k8s-file 295 } 296 297 @test "podman logs - --follow journald" { 298 # We can't use journald on RHEL as rootless: rhbz#1895105 299 skip_if_journald_unavailable 300 301 _log_test_follow journald 302 } 303 304 function _log_test_follow_since() { 305 local driver=$1 306 cname=$(random_string) 307 content=$(random_string) 308 local events_backend=$(_additional_events_backend $driver) 309 310 if [[ -n "${events_backend}" ]]; then 311 skip_if_remote "remote does not support --events-backend" 312 fi 313 314 run_podman ${events_backend} run --log-driver=$driver --name $cname $IMAGE echo "$content" 315 # Using --since 0s can flake because the log might written in the second as the logs call is made. 316 # The -1s makes sure we only read logs that would be created 1s in the future which cannot happen. 317 run_podman ${events_backend} logs --since -1s -f $cname 318 assert "$output" == "" "logs --since -f on exited container works" 319 320 run_podman ${events_backend} rm -t 0 -f $cname 321 322 # Now do the same with a running container to check #16950. 323 run_podman ${events_backend} run --log-driver=$driver --name $cname -d $IMAGE \ 324 sh -c "sleep 1; while :; do echo $content && sleep 5; done" 325 326 # sleep is required to make sure the podman event backend no longer sees the start event in the log 327 # This value must be greater or equal than the value given in --since below 328 sleep 0.2 329 330 # Make sure podman logs actually follows by giving a low timeout and check that the command times out 331 PODMAN_TIMEOUT=3 run_podman 124 ${events_backend} logs --since 0.1s -f $cname 332 assert "$output" =~ "^$content 333 timeout: sending signal TERM to command.*" "logs --since -f on running container works" 334 335 run_podman ${events_backend} rm -t 0 -f $cname 336 } 337 338 @test "podman logs - --since --follow k8s-file" { 339 _log_test_follow_since k8s-file 340 } 341 342 # bats test_tags=distro-integration 343 @test "podman logs - --since --follow journald" { 344 # We can't use journald on RHEL as rootless: rhbz#1895105 345 skip_if_journald_unavailable 346 347 _log_test_follow_since journald 348 } 349 350 function _log_test_follow_until() { 351 local driver=$1 352 cname=$(random_string) 353 content=$(random_string) 354 local events_backend=$(_additional_events_backend $driver) 355 356 if [[ -n "${events_backend}" ]]; then 357 skip_if_remote "remote does not support --events-backend" 358 fi 359 360 run_podman ${events_backend} run --log-driver=$driver --name $cname -d $IMAGE \ 361 sh -c "n=1;while :; do echo $content--\$n; n=\$((n+1));sleep 0.1; done" 362 363 t0=$SECONDS 364 # The logs command should exit after the until time even when follow is set 365 PODMAN_TIMEOUT=10 run_podman ${events_backend} logs --until 3s -f $cname 366 t1=$SECONDS 367 logs_seen="$output" 368 369 # The delta should be 3 but because it could be a bit longer on a slow system such as CI we also accept 4. 370 delta_t=$(( $t1 - $t0 )) 371 assert $delta_t -gt 2 "podman logs --until: exited too early!" 372 assert $delta_t -lt 5 "podman logs --until: exited too late!" 373 374 # Impossible to know how many lines we'll see, but require at least two 375 assert "$logs_seen" =~ "$content--1 376 $content--2.*" "logs --until -f on running container works" 377 378 run_podman ${events_backend} rm -t 0 -f $cname 379 } 380 381 @test "podman logs - --until --follow k8s-file" { 382 _log_test_follow_until k8s-file 383 } 384 385 # bats test_tags=distro-integration 386 @test "podman logs - --until --follow journald" { 387 # We can't use journald on RHEL as rootless: rhbz#1895105 388 skip_if_journald_unavailable 389 390 _log_test_follow_until journald 391 } 392 393 # https://github.com/containers/podman/issues/19545 394 @test "podman logs --tail, k8s-file with partial lines" { 395 cname="tail_container" 396 397 # "-t" gives us ^Ms (CRs) in the log 398 run_podman run --name $cname --log-driver k8s-file -t $IMAGE echo hi 399 400 # Hand-craft a log file with partial lines and carriage returns 401 run_podman inspect --format '{{.HostConfig.LogConfig.Path}}' $cname 402 logpath="$output" 403 timestamp=$(head -n1 "$logpath" | awk '{print $1}') 404 cr=$'\r' 405 nl=$'\n' 406 # Delete, don't overwrite, in case conmon still has the fd open 407 rm -f $logpath 408 cat > $logpath <<EOF 409 $timestamp stdout F podman1$cr 410 $timestamp stdout P podman2 411 $timestamp stdout F $cr 412 $timestamp stdout F podman3$cr 413 EOF 414 415 # FIXME: remove after 2024-01-01 if no more flakes seen. 416 cat -vET $logpath 417 418 expect1="podman3${cr}" 419 expect2="podman2${cr}${nl}podman3${cr}" 420 expect3="podman1${cr}${nl}podman2${cr}${nl}podman3${cr}" 421 422 # This always worked 423 run_podman logs --tail 1 $cname 424 assert "$output" = "$expect1" "--tail 1" 425 426 # Prior to this PR, the first line would be "^M" without the podman 427 run_podman logs --tail 2 $cname 428 assert "$output" = "$expect2" "--tail 2" 429 430 # Confirm that we won't overrun 431 for i in 3 4 5; do 432 run_podman logs --tail $i $cname 433 assert "$output" = "$expect3" "--tail $i" 434 done 435 436 run_podman rm $cname 437 } 438 439 # vim: filetype=sh