github.com/containers/podman/v5@v5.1.0-rc1/test/system/090-events.bats (about) 1 #!/usr/bin/env bats -*- bats -*- 2 # 3 # tests for podman events functionality 4 # 5 6 load helpers 7 load helpers.network 8 9 # bats test_tags=distro-integration 10 @test "events with a filter by label" { 11 cname=test-$(random_string 30 | tr A-Z a-z) 12 labelname=$(random_string 10) 13 labelvalue=$(random_string 15) 14 15 run_podman run --label $labelname=$labelvalue --name $cname --rm $IMAGE ls 16 17 expect=".* container start [0-9a-f]\+ (image=$IMAGE, name=$cname,.* ${labelname}=${labelvalue}" 18 run_podman events --filter type=container -f container=$cname --filter label=${labelname}=${labelvalue} --filter event=start --stream=false 19 is "$output" "$expect" "filtering by container name and label" 20 21 # Same thing, but without the container-name filter 22 run_podman system events -f type=container --filter label=${labelname}=${labelvalue} --filter event=start --stream=false 23 is "$output" "$expect" "filtering just by label" 24 25 # Now filter just by container name, no label 26 run_podman events --filter type=container --filter container=$cname --filter event=start --stream=false 27 is "$output" "$expect" "filtering just by container" 28 } 29 30 @test "truncate events" { 31 cname=test-$(random_string 30 | tr A-Z a-z) 32 33 run_podman run -d --name=$cname --rm $IMAGE echo hi 34 id="$output" 35 36 run_podman events --filter container=$cname --filter event=start --stream=false 37 is "$output" ".* $id " "filtering by container name full id" 38 39 truncID=${id:0:12} 40 run_podman events --filter container=$cname --filter event=start --stream=false --no-trunc=false 41 is "$output" ".* $truncID " "filtering by container name trunc id" 42 43 # --no-trunc does not affect --format; we always get the full ID 44 run_podman events --filter container=$cname --filter event=died --stream=false --format='{{.ID}}--{{.Image}}' --no-trunc=false 45 assert "$output" = "${id}--${IMAGE}" 46 } 47 48 @test "image events" { 49 skip_if_remote "remote does not support --events-backend" 50 pushedDir=$PODMAN_TMPDIR/dir 51 mkdir -p $pushedDir 52 53 tarball=$PODMAN_TMPDIR/ball.tar 54 55 run_podman image inspect --format "{{.ID}}" $IMAGE 56 imageID="$output" 57 58 t0=$(date --iso-8601=seconds) 59 tag=registry.com/$(random_string 10 | tr A-Z a-z) 60 61 bogus_image="localhost:$(random_free_port)/bogus" 62 63 # Force using the file backend since the journal backend is eating events 64 # (see containers/podman/pull/10219#issuecomment-842325032). 65 run_podman --events-backend=file push $IMAGE dir:$pushedDir 66 run_podman --events-backend=file save $IMAGE -o $tarball 67 run_podman --events-backend=file load -i $tarball 68 run_podman --events-backend=file pull docker-archive:$tarball 69 run_podman 125 --events-backend=file pull --retry 0 $bogus_image 70 run_podman --events-backend=file tag $IMAGE $tag 71 run_podman --events-backend=file untag $IMAGE $tag 72 run_podman --events-backend=file tag $IMAGE $tag 73 run_podman --events-backend=file rmi -f $imageID 74 run_podman --events-backend=file load -i $tarball 75 76 run_podman --events-backend=file events --stream=false --filter type=image --since $t0 77 is "$output" ".*image push $imageID dir:$pushedDir 78 .*image save $imageID $tarball 79 .*image loadfromarchive $imageID $tarball 80 .*image pull $imageID docker-archive:$tarball 81 .*image pull-error $bogus_image .*pinging container registry localhost.*connection refused 82 .*image tag $imageID $tag 83 .*image untag $imageID $tag:latest 84 .*image tag $imageID $tag 85 .*image untag $imageID $tag:latest 86 .*image untag $imageID $IMAGE 87 .*image remove $imageID $imageID" \ 88 "podman events" 89 90 # With --format we can check the _exact_ output, not just substrings 91 local -a expect=("push--dir:$pushedDir" 92 "save--$tarball" 93 "loadfromarchive--$tarball" 94 "pull--docker-archive:$tarball" 95 "pull-error--$bogus_image" 96 "tag--$tag" 97 "untag--$tag:latest" 98 "tag--$tag" 99 "untag--$tag:latest" 100 "untag--$IMAGE" 101 "remove--$imageID" 102 "loadfromarchive--$tarball" 103 ) 104 run_podman --events-backend=file events --stream=false --filter type=image --since $t0 --format '{{.Status}}--{{.Name}}' 105 for i in $(seq 0 ${#expect[@]}); do 106 assert "${lines[$i]}" = "${expect[$i]}" "events, line $i" 107 done 108 assert "${#lines[@]}" = "${#expect[@]}" "Total lines of output" 109 } 110 111 function _events_disjunctive_filters() { 112 local backend=$1 113 114 # Regression test for #10507: make sure that filters with the same key are 115 # applied in disjunction. 116 t0=$(date --iso-8601=seconds) 117 run_podman $backend run --name foo --rm $IMAGE ls 118 run_podman $backend run --name bar --rm $IMAGE ls 119 run_podman $backend events --stream=false --since=$t0 --filter container=foo --filter container=bar --filter event=start 120 is "$output" ".* container start .* name=foo.* 121 .* container start .* name=bar.*" 122 } 123 124 @test "events with disjunctive filters - file" { 125 skip_if_remote "remote does not support --events-backend" 126 _events_disjunctive_filters --events-backend=file 127 } 128 129 @test "events with disjunctive filters - journald" { 130 skip_if_remote "remote does not support --events-backend" 131 skip_if_journald_unavailable "system does not support journald events" 132 _events_disjunctive_filters --events-backend=journald 133 } 134 135 @test "events with file backend and journald logdriver with --follow failure" { 136 skip_if_remote "remote does not support --events-backend" 137 skip_if_journald_unavailable "system does not support journald events" 138 run_podman --events-backend=file run --log-driver=journald --name=test $IMAGE echo hi 139 is "$output" "hi" "Should support events-backend=file" 140 141 run_podman 125 --events-backend=file logs --follow test 142 is "$output" "Error: using --follow with the journald --log-driver but without the journald --events-backend (file) is not supported" \ 143 "Should fail with reasonable error message when events-backend and events-logger do not match" 144 145 } 146 147 @test "events with disjunctive filters - default" { 148 _events_disjunctive_filters "" 149 } 150 151 # bats test_tags=distro-integration 152 @test "events with events_logfile_path in containers.conf" { 153 skip_if_remote "remote does not support --events-backend" 154 events_file=$PODMAN_TMPDIR/events.log 155 containersconf=$PODMAN_TMPDIR/containers.conf 156 cat >$containersconf <<EOF 157 [engine] 158 events_logfile_path="$events_file" 159 EOF 160 CONTAINERS_CONF_OVERRIDE="$containersconf" run_podman --events-backend=file pull $IMAGE 161 assert "$(< $events_file)" =~ "\"Name\":\"$IMAGE\"" "Image found in events" 162 } 163 164 function _populate_events_file() { 165 # Create 100 duplicate entries to populate the events log file. 166 local events_file=$1 167 truncate --size=0 $events_file 168 for i in {0..99}; do 169 printf '{"Name":"busybox","Status":"pull","Time":"2022-04-06T11:26:42.7236679%02d+02:00","Type":"image","Attributes":null}\n' $i >> $events_file 170 done 171 } 172 173 # bats test_tags=distro-integration 174 @test "events log-file rotation" { 175 skip_if_remote "setting CONTAINERS_CONF_OVERRIDE logger options does not affect remote client" 176 177 # Make sure that the events log file is (not) rotated depending on the 178 # settings in containers.conf. 179 180 # Config without a limit 181 eventsFile=$PODMAN_TMPDIR/events.txt 182 containersConf=$PODMAN_TMPDIR/containers.conf 183 cat >$containersConf <<EOF 184 [engine] 185 events_logger="file" 186 events_logfile_path="$eventsFile" 187 EOF 188 189 # Check that a non existing event file does not cause a hang (#15688) 190 CONTAINERS_CONF_OVERRIDE=$containersConf run_podman events --stream=false 191 192 _populate_events_file $eventsFile 193 194 # Create events *without* a limit and make sure that it has not been 195 # rotated/truncated. 196 contentBefore=$(head -n100 $eventsFile) 197 CONTAINERS_CONF_OVERRIDE=$containersConf run_podman run --rm $IMAGE true 198 contentAfter=$(head -n100 $eventsFile) 199 is "$contentBefore" "$contentAfter" "events file has not been rotated" 200 201 # Repopulate events file 202 rm $eventsFile 203 _populate_events_file $eventsFile 204 205 # Config with a limit 206 rm $containersConf 207 cat >$containersConf <<EOF 208 [engine] 209 events_logger="file" 210 events_logfile_path="$eventsFile" 211 # The limit of 4750 is the *exact* half of the initial events file. 212 events_logfile_max_size=4750 213 EOF 214 215 # Create events *with* a limit and make sure that it has been 216 # rotated/truncated. Once rotated, the events file should only contain the 217 # second half of its previous events plus the new ones. 218 expectedContentAfterTruncation=$PODMAN_TMPDIR/truncated.txt 219 220 run_podman create $IMAGE 221 ctrID=$output 222 CONTAINERS_CONF_OVERRIDE=$containersConf run_podman rm $ctrID 223 tail -n52 $eventsFile >> $expectedContentAfterTruncation 224 225 # Make sure the events file looks as expected. 226 is "$(cat $eventsFile)" "$(cat $expectedContentAfterTruncation)" "events file has been rotated" 227 228 # Make sure that `podman events` can read the file, and that it returns the 229 # same amount of events. We checked the contents before. 230 CONTAINERS_CONF_OVERRIDE=$containersConf run_podman events --stream=false --since="2022-03-06T11:26:42.723667984+02:00" --format=json 231 assert "${#lines[@]}" = 52 "Number of events returned" 232 is "${lines[0]}" "{\"Name\":\"$eventsFile\",\"Status\":\"log-rotation\",\"time\":[0-9]\+,\"timeNano\":[0-9]\+,\"Type\":\"system\",\"Attributes\":{\"io.podman.event.rotate\":\"begin\"}}" 233 is "${lines[-2]}" "{\"Name\":\"$eventsFile\",\"Status\":\"log-rotation\",\"time\":[0-9]\+,\"timeNano\":[0-9]\+,\"Type\":\"system\",\"Attributes\":{\"io.podman.event.rotate\":\"end\"}}" 234 is "${lines[-1]}" "{\"ID\":\"$ctrID\",\"Image\":\"$IMAGE\",\"Name\":\".*\",\"Status\":\"remove\",\"time\":[0-9]\+,\"timeNano\":[0-9]\+,\"Type\":\"container\",\"Attributes\":{.*}}" 235 } 236 237 @test "events log-file no duplicates" { 238 skip_if_remote "setting CONTAINERS_CONF_OVERRIDE logger options does not affect remote client" 239 240 # This test makes sure that events are not returned more than once when 241 # streaming during a log-file rotation. 242 eventsFile=$PODMAN_TMPDIR/events.txt 243 eventsJSON=$PODMAN_TMPDIR/events.json 244 containersConf=$PODMAN_TMPDIR/containers.conf 245 cat >$containersConf <<EOF 246 [engine] 247 events_logger="file" 248 events_logfile_path="$eventsFile" 249 # The populated file has a size of 11300, so let's create a couple of events to 250 # force a log rotation. 251 events_logfile_max_size=11300 252 EOF 253 254 _populate_events_file $eventsFile 255 CONTAINERS_CONF_OVERRIDE=$containersConf timeout --kill=10 20 \ 256 $PODMAN events --stream=true --since="2022-03-06T11:26:42.723667984+02:00" --format=json > $eventsJSON & 257 258 # Now wait for the above podman-events process to write to the eventsJSON 259 # file, so we know it's reading. 260 retries=20 261 while [[ $retries -gt 0 ]]; do 262 if [ -s $eventsJSON ]; then 263 break 264 fi 265 retries=$((retries - 1)) 266 sleep 0.5 267 done 268 assert $retries -gt 0 \ 269 "Timed out waiting for podman-events to start reading pre-existing events" 270 271 CONTAINERS_CONF_OVERRIDE=$containersConf run_podman create $IMAGE 272 ctrID=$output 273 CONTAINERS_CONF_OVERRIDE=$containersConf run_podman rm -f $ctrID 274 275 # Now wait for the last event above to be read by the `podman-events` 276 # process above. 277 retries=20 278 while [[ $retries -gt 0 ]]; do 279 run grep "\"Status\"\:\"remove\"," $eventsJSON 280 if [[ $status -eq 0 ]]; then 281 break 282 fi 283 retries=$((retries - 1)) 284 sleep 0.5 285 done 286 test "$status" = 0 || die "Did not find expected 'Status:remove' line in log" 287 288 # Make sure that the log file has been rotated as expected. 289 run cat $eventsFile 290 assert "${#lines[@]}" = 54 "Number of events in $eventsFile" # 49 previous + 2 rotation + pull/create/rm 291 is "${lines[0]}" "{\"Name\":\"$eventsFile\",\"Status\":\"log-rotation\",\"Time\":\".*\",\"Type\":\"system\",\"Attributes\":{\"io.podman.event.rotate\":\"begin\"}}" 292 is "${lines[1]}" "{\"Name\":\"busybox\",\"Status\":\"pull\",\"Time\":\"2022-04-06T11:26:42.723667951+02:00\",\"Type\":\"image\",\"Attributes\":null}" 293 is "${lines[49]}" "{\"Name\":\"busybox\",\"Status\":\"pull\",\"Time\":\"2022-04-06T11:26:42.723667999+02:00\",\"Type\":\"image\",\"Attributes\":null}" 294 is "${lines[50]}" "{\"Name\":\"$eventsFile\",\"Status\":\"log-rotation\",\"Time\":\".*\",\"Type\":\"system\",\"Attributes\":{\"io.podman.event.rotate\":\"end\"}}" 295 is "${lines[53]}" "{\"ID\":\"$ctrID\",\"Image\":\"$IMAGE\",\"Name\":\".*\",\"Status\":\"remove\",\"Time\":\".*\",\"Type\":\"container\",\"Attributes\":{.*}}" 296 297 298 # Make sure that the JSON stream looks as expected. That means it has all 299 # events and no duplicates. 300 run cat $eventsJSON 301 is "${lines[0]}" "{\"Name\":\"busybox\",\"Status\":\"pull\",\"time\":1649237202,\"timeNano\":1649237202723[0-9]\+,\"Type\":\"image\",\"Attributes\":null}" 302 is "${lines[99]}" "{\"Name\":\"busybox\",\"Status\":\"pull\",\"time\":1649237202,\"timeNano\":1649237202723[0-9]\+,\"Type\":\"image\",\"Attributes\":null}" 303 is "${lines[100]}" "{\"Name\":\"$eventsFile\",\"Status\":\"log-rotation\",\"time\":[0-9]\+,\"timeNano\":[0-9]\+,\"Type\":\"system\",\"Attributes\":{\"io.podman.event.rotate\":\"end\"}}" 304 is "${lines[103]}" "{\"ID\":\"$ctrID\",\"Image\":\"$IMAGE\",\"Name\":\".*\",\"Status\":\"remove\",\"time\":[0-9]\+,\"timeNano\":[0-9]\+,\"Type\":\"container\",\"Attributes\":{.*}}" 305 } 306 307 # Prior to #15633, container labels would not appear in 'die' log events 308 @test "events - labels included in container die" { 309 skip_if_remote "remote does not support --events-backend" 310 local cname=c$(random_string 15) 311 local lname=l$(random_string 10) 312 local lvalue="v$(random_string 10) $(random_string 5)" 313 314 run_podman 17 --events-backend=file run --rm \ 315 --name=$cname \ 316 --label=$lname="$lvalue" \ 317 $IMAGE sh -c 'exit 17' 318 run_podman --events-backend=file events \ 319 --filter=container=$cname \ 320 --filter=status=died \ 321 --stream=false \ 322 --format="{{.Attributes.$lname}}" 323 assert "$output" = "$lvalue" "podman-events output includes container label" 324 } 325 326 @test "events - backend none should error" { 327 skip_if_remote "remote does not support --events-backend" 328 329 run_podman 125 --events-backend none events 330 is "$output" "Error: cannot read events with the \"none\" backend" "correct error message" 331 run_podman 125 --events-backend none events --stream=false 332 is "$output" "Error: cannot read events with the \"none\" backend" "correct error message" 333 } 334 335 function _events_container_create_inspect_data { 336 containersConf=$PODMAN_TMPDIR/containers.conf 337 cat >$containersConf <<EOF 338 [engine] 339 events_logger="$1" 340 events_container_create_inspect_data=true 341 EOF 342 343 local cname=c$(random_string 15) 344 t0=$(date --iso-8601=seconds) 345 346 CONTAINERS_CONF_OVERRIDE=$containersConf run_podman create --name=$cname $IMAGE 347 CONTAINERS_CONF_OVERRIDE=$containersConf run_podman container inspect --size=true $cname 348 inspect_json=$(jq -r --tab . <<< "$output") 349 350 CONTAINERS_CONF_OVERRIDE=$containersConf run_podman --events-backend=$1 events \ 351 --since="$t0" \ 352 --filter=status=$cname \ 353 --filter=status=create \ 354 --stream=false \ 355 --format="{{.ContainerInspectData}}" 356 events_json=$(jq -r --tab . <<< "[$output]") 357 assert "$events_json" = "$inspect_json" "JSON payload in event attributes is the same as the inspect one" 358 359 # Make sure that the inspect data doesn't show by default in 360 # podman-events. 361 CONTAINERS_CONF_OVERRIDE=$containersConf run_podman --events-backend=$1 events \ 362 --since="$t0" \ 363 --filter=status=$cname \ 364 --filter=status=create \ 365 --stream=false 366 assert "$output" != ".*ConmonPidFile.*" 367 assert "$output" != ".*EffectiveCaps.*" 368 } 369 370 @test "events - container inspect data - journald" { 371 skip_if_remote "remote does not support --events-backend" 372 skip_if_journald_unavailable 373 374 _events_container_create_inspect_data journald 375 } 376 377 @test "events - container inspect data - file" { 378 skip_if_remote "remote does not support --events-backend" 379 380 _events_container_create_inspect_data file 381 } 382 383 @test "events - docker compat" { 384 local cname=c$(random_string 15) 385 t0=$(date --iso-8601=seconds) 386 run_podman run --name=$cname --rm $IMAGE true 387 run_podman events \ 388 --since="$t0" \ 389 --filter=status=$cname \ 390 --filter=status=die \ 391 --stream=false 392 is "${lines[0]}" ".* container died .* (image=$IMAGE, name=$cname, .*)" 393 } 394 395 @test "events - volume events" { 396 local vname=v$(random_string 10) 397 run_podman volume create $vname 398 run_podman volume rm $vname 399 400 run_podman events --since=1m --stream=false --filter volume=$vname 401 notrunc_results="$output" 402 assert "${lines[0]}" =~ ".* volume create $vname" 403 assert "${lines[1]}" =~ ".* volume remove $vname" 404 405 # Prefix test 406 run_podman events --since=1m --stream=false --filter volume=${vname:0:5} 407 assert "$output" = "$notrunc_results" 408 } 409 410 @test "events - invalid filter" { 411 run_podman 125 events --since="the dawn of time...ish" 412 assert "$output" =~ "failed to parse event filters" 413 }