github.com/containers/podman/v5@v5.1.0-rc1/test/apiv2/test-apiv2 (about) 1 #!/usr/bin/env bash 2 # 3 # Usage: test-apiv2 testglob 4 # 5 # DEVELOPER NOTE: you almost certainly don't need to play in here. See README. 6 # 7 ME=$(basename $0) 8 9 ############################################################################### 10 # BEGIN stuff you can but probably shouldn't customize 11 12 PODMAN_TEST_IMAGE_REGISTRY=${PODMAN_TEST_IMAGE_REGISTRY:-"quay.io"} 13 PODMAN_TEST_IMAGE_USER=${PODMAN_TEST_IMAGE_USER:-"libpod"} 14 PODMAN_TEST_IMAGE_NAME=${PODMAN_TEST_IMAGE_NAME:-"alpine_labels"} 15 PODMAN_TEST_IMAGE_TAG=${PODMAN_TEST_IMAGE_TAG:-"latest"} 16 PODMAN_TEST_IMAGE_FQN="$PODMAN_TEST_IMAGE_REGISTRY/$PODMAN_TEST_IMAGE_USER/$PODMAN_TEST_IMAGE_NAME:$PODMAN_TEST_IMAGE_TAG" 17 18 IMAGE=$PODMAN_TEST_IMAGE_FQN 19 20 REGISTRY_IMAGE="${PODMAN_TEST_IMAGE_REGISTRY}/${PODMAN_TEST_IMAGE_USER}/registry:2.7" 21 22 # END stuff you can but probably shouldn't customize 23 ############################################################################### 24 # BEGIN setup 25 26 TMPDIR=${TMPDIR:-/tmp} 27 WORKDIR=$(mktemp --tmpdir -d $ME.tmp.XXXXXX) 28 29 # Log of all HTTP requests and responses; always make '.log' point to latest 30 LOGBASE=${TMPDIR}/$ME.log 31 LOG=${LOGBASE}.$(date +'%Y%m%dT%H%M%S') 32 ln -sf $LOG $LOGBASE 33 34 HOST=localhost 35 PORT=${PODMAN_SERVICE_PORT:-8081} 36 37 # Keep track of test count and failures in files, not variables, because 38 # variables don't carry back up from subshells. 39 testcounter_file=$WORKDIR/.testcounter 40 failures_file=$WORKDIR/.failures 41 42 echo 0 >$testcounter_file 43 echo 0 >$failures_file 44 45 # Where the tests live 46 TESTS_DIR=$(realpath $(dirname $0)) 47 48 # As of 2021-11 podman has one external helper binary, rootlessport, needed 49 # for rootless networking. 50 if [[ -z "$CONTAINERS_HELPER_BINARY_DIR" ]]; then 51 export CONTAINERS_HELPER_BINARY_DIR=$(realpath ${TESTS_DIR}/../../bin) 52 fi 53 54 # Path to podman binary 55 PODMAN_BIN=${PODMAN:-${CONTAINERS_HELPER_BINARY_DIR}/podman} 56 57 # Cleanup handlers 58 clean_up_server() { 59 if [ -n "$service_pid" ]; then 60 # Remove any containers and images; this prevents the following warning: 61 # 'rm: cannot remove '/.../overlay': Device or resource busy 62 podman rm -a 63 podman rmi -af 64 65 stop_registry --cleanup 66 stop_service 67 fi 68 } 69 70 # Any non-test-related error, be it syntax or podman-command, fails here. 71 err_handler() { 72 echo "Fatal error in ${BASH_SOURCE[1]}:${BASH_LINENO[0]}" 73 echo "Log:" 74 sed -e 's/^/ >/' <$WORKDIR/output.log 75 echo "Bailing." 76 clean_up_server 77 } 78 79 trap err_handler ERR 80 81 # END setup 82 ############################################################################### 83 # BEGIN infrastructure code - the helper functions used in tests themselves 84 85 ######### 86 # die # Exit error with a message to stderr 87 ######### 88 function die() { 89 echo "$ME: $*" >&2 90 clean_up_server 91 exit 1 92 } 93 94 ######## 95 # is # Simple comparison 96 ######## 97 function is() { 98 local actual=$1 99 local expect=$2 100 local testname=$3 101 102 if [ "$actual" = "$expect" ]; then 103 # On success, include expected value; this helps readers understand 104 _show_ok 1 "$testname=$expect" 105 return 106 fi 107 _show_ok 0 "$testname" "$expect" "$actual" 108 } 109 110 ############ 111 # is_not # Simple disequality 112 ############ 113 function is_not() { 114 local actual=$1 115 local expect_not=$2 116 local testname=$3 117 118 if [ "$actual" != "$expect_not" ]; then 119 # On success, include expected value; this helps readers understand 120 _show_ok 1 "$testname!=$expect" 121 return 122 fi 123 _show_ok 0 "$testname" "!= $expect" "$actual" 124 } 125 126 ########## 127 # like # Compare, but allowing patterns 128 ########## 129 function like() { 130 local actual=$1 131 local expect=$2 132 local testname=$3 133 134 if expr "$actual" : "$expect" &>/dev/null; then 135 # On success, include expected value; this helps readers understand 136 # (but don't show enormous multi-line output like 'generate kube') 137 blurb=$(head -n1 <<<"$actual") 138 _show_ok 1 "$testname ('$blurb') ~ $expect" 139 return 140 fi 141 _show_ok 0 "$testname" "~ $expect" "$actual" 142 } 143 144 ############## 145 # _show_ok # Helper for is() and like(): displays 'ok' or 'not ok' 146 ############## 147 function _show_ok() { 148 local ok=$1 149 # Exec tests include control characters; filter them out 150 # Also filter out timestamps, to get consistent test names in logs 151 local testname=$(tr -d \\012 <<<"$2"|sed -e 's/since=[0-9.]\+/since=(T)/'|cat -vT) 152 153 # If output is a tty, colorize pass/fail 154 local red= 155 local green= 156 local reset= 157 local bold= 158 if [ -t 1 ]; then 159 red='\e[31m' 160 green='\e[32m' 161 reset='\e[0m' 162 bold='\e[1m' 163 fi 164 165 _bump $testcounter_file 166 count=$(<$testcounter_file) 167 168 # "skip" is a special case of "ok". Assume that our caller has included 169 # the magical '# skip - reason" comment string. 170 if [[ $ok == "skip" ]]; then 171 # colon-plus: replace green with yellow, but only if green is non-null 172 green="${green:+\e[33m}" 173 ok=1 174 fi 175 if [ $ok -eq 1 ]; then 176 echo -e "${green}ok $count ${TEST_CONTEXT} $testname${reset}" 177 echo "ok $count ${TEST_CONTEXT} $testname" >>$LOG 178 return 179 fi 180 181 # Failed 182 local expect=$3 183 local actual=$4 184 echo -e "${red}not ok $count ${TEST_CONTEXT} $testname${reset}" 185 echo -e "${red}# expected: $expect${reset}" 186 echo -e "${red}# actual: ${bold}$actual${reset}" 187 188 echo "not ok $count ${TEST_CONTEXT} $testname" >>$LOG 189 echo " expected: $expect" >>$LOG 190 191 _bump $failures_file 192 } 193 194 ########### 195 # _bump # Increment a counter in a file 196 ########### 197 function _bump() { 198 local file=$1 199 200 count=$(<$file) 201 echo $(( $count + 1 )) >| $file 202 } 203 204 ############# 205 # jsonify # convert 'foo=bar,x=y' to json {"foo":"bar","x":"y"} 206 ############# 207 function jsonify() { 208 # convert each to double-quoted form 209 local -a settings_out 210 for i in "$@"; do 211 # Each argument is of the form foo=bar. Separate into left and right. 212 local lhs 213 local rhs 214 IFS='=' read lhs rhs <<<"$i" 215 216 if [[ $rhs =~ \" || $rhs == true || $rhs == false || $rhs =~ ^-?[0-9]+$ ]]; then 217 # rhs has been pre-formatted for JSON or a non-string, do not change it 218 : 219 elif [[ $rhs == False ]]; then 220 # JSON boolean is lowercase only 221 rhs=false 222 elif [[ $rhs == True ]]; then 223 # JSON boolean is lowercase only 224 rhs=true 225 else 226 rhs="\"${rhs}\"" 227 fi 228 settings_out+=("\"${lhs}\":${rhs}") 229 done 230 231 # ...and wrap inside braces, with comma separator if multiple fields 232 (IFS=','; echo "{${settings_out[*]}}") 233 } 234 235 ####### 236 # t # Main test helper 237 ####### 238 function t() { 239 local method=$1; shift 240 local path=$1; shift 241 local -a curl_args form_args 242 local content_type="application/json" 243 244 local testname="$method $path" 245 246 # POST and PUT requests may be followed by one or more key=value pairs. 247 # Slurp the command line until we see a 3-digit status code. 248 if [[ $method = "POST" || $method == "PUT" || $method == "DELETE" ]]; then 249 local -a post_args 250 251 if [[ $method == "POST" ]]; then 252 function _add_curl_args() { curl_args+=(--data-binary @$1); } 253 else 254 function _add_curl_args() { curl_args+=(--upload-file $1); } 255 fi 256 257 for arg; do 258 case "$arg" in 259 # This is just some hack to avoid adding `-d {}` to curl for endpoints where we really need an empty body. 260 # --disable makes curl not lookup the curlrc file, it shouldn't affect the tests in any way. 261 -) curl_args+=(--disable); 262 shift;; 263 --form=*) form_args+=(--form); 264 form_args+=("${arg#--form=}"); 265 content_type="multipart/form-data"; 266 shift;; 267 *=*) post_args+=("$arg"); 268 shift;; 269 *.json) _add_curl_args $arg; 270 content_type="application/json"; 271 shift;; 272 *.tar) _add_curl_args $arg; 273 content_type="application/x-tar"; 274 shift;; 275 *.yaml) _add_curl_args $arg; 276 shift;; 277 application/*) content_type="$arg"; 278 shift;; 279 [1-9][0-9][0-9]) break;; 280 *) die "Internal error: invalid POST arg '$arg'" ;; 281 esac 282 done 283 if [[ -z "${curl_args[*]}" && -z "${form_args[*]}" ]]; then 284 curl_args=(-d $(jsonify ${post_args[*]})) 285 testname="$testname [${curl_args[*]}]" 286 elif [[ -z "${curl_args[*]}" ]]; then 287 curl_args=(--form request.json=$(jsonify ${post_args[*]}) "${form_args[@]}") 288 testname="$testname [${curl_args[*]} ${form_args[*]}]" 289 fi 290 fi 291 292 # entrypoint path can include a descriptive comment; strip it off 293 path=${path%% *} 294 295 local url=$path 296 if ! [[ $path =~ ^'http://' ]]; then 297 # path may include JSONish params that curl will barf on; url-encode them 298 path="${path//'['/%5B}" 299 path="${path//']'/%5D}" 300 path="${path//'{'/%7B}" 301 path="${path//'}'/%7D}" 302 path="${path//':'/%3A}" 303 304 # If given path begins with /, use it as-is; otherwise prepend /version/ 305 url=http://$HOST:$PORT 306 case "$path" in 307 /*) url="$url$path" ;; 308 libpod/*) url="$url/v4.0.0/$path" ;; 309 *) url="$url/v1.41/$path" ;; 310 esac 311 fi 312 313 # curl -X HEAD but without --head seems to wait for output anyway 314 if [[ $method == "HEAD" ]]; then 315 curl_args+=("--head") 316 fi 317 318 # If this is set, we're *expecting* curl to time out 319 if [[ -n "$APIV2_TEST_EXPECT_TIMEOUT" ]]; then 320 curl_args+=("-m" $APIV2_TEST_EXPECT_TIMEOUT) 321 fi 322 323 local expected_code=$1; shift 324 325 if [[ "$expected_code" == "101" ]]; then 326 curl_args+=("-H" "Connection: upgrade" "-H" "Upgrade: tcp") 327 fi 328 329 # Log every action we do 330 echo "-------------------------------------------------------------" >>$LOG 331 echo "\$ $testname" >>$LOG 332 rm -f $WORKDIR/curl.* 333 # The --write-out 'format' gives us important response data. 334 # The hairy "{ ...;rc=$?; } || :" lets us capture curl's exit code and 335 # give a helpful diagnostic if it fails. 336 : > $WORKDIR/curl.result.out 337 : > $WORKDIR/curl.result.err 338 { response=$(curl -X $method "${curl_args[@]}" \ 339 -H "Content-type: $content_type" \ 340 --dump-header $WORKDIR/curl.headers.out \ 341 -v --stderr $WORKDIR/curl.result.err \ 342 --write-out '%{http_code}^%{content_type}^%{time_total}' \ 343 -o $WORKDIR/curl.result.out "$url"); rc=$?; } || : 344 if [ -n "$PODMAN_TESTS_DUMP_TRACES" ]; then 345 # Dump the results we got back, exactly as we got them back. 346 echo "\$ begin stdout" >>$LOG 347 test -s $WORKDIR/curl.result.out && od -t x1c $WORKDIR/curl.result.out 2>&1 >>$LOG 348 echo "\$ end stdout" >>$LOG 349 echo "\$ begin stderr" >>$LOG 350 test -s $WORKDIR/curl.result.err && cat $WORKDIR/curl.result.err >>$LOG 351 echo "\$ end stderr" >>$LOG 352 echo "\$ begin response code^content_type^time_total" >>$LOG 353 od -t x1c <<< "$response" >>$LOG 354 echo "\$ end response" >>$LOG 355 fi 356 357 # Special case: this means we *expect and want* a timeout 358 if [[ -n "$APIV2_TEST_EXPECT_TIMEOUT" ]]; then 359 # Hardcoded. See curl(1) for list of exit codes 360 if [[ $rc -eq 28 ]]; then 361 _show_ok 1 "$testname: curl timed out (expected)" 362 else 363 _show_ok 0 "$testname: expected curl to time out; it did not" 364 fi 365 return 366 fi 367 368 # Any error from curl is instant bad news, from which we can't recover 369 if [[ $rc -ne 0 ]]; then 370 die "curl failure ($rc) on $url - cannot continue. args=${curl_args[*]}" 371 fi 372 373 # Show returned headers (without trailing ^M or empty lines) in log file. 374 # Sometimes -- I can't remember why! -- we don't get headers. 375 if [[ -e $WORKDIR/curl.headers.out ]]; then 376 tr -d '\015' < $WORKDIR/curl.headers.out | grep -E '.' >>$LOG 377 fi 378 379 IFS='^' read actual_code content_type time_total <<<"$response" 380 printf "X-Response-Time: ${time_total}s\n\n" >>$LOG 381 382 # Log results, if text. If JSON, filter through jq for readability. 383 if [[ $content_type =~ /octet ]]; then 384 output="[$(file --brief $WORKDIR/curl.result.out)]" 385 echo "$output" >>$LOG 386 elif [[ -e $WORKDIR/curl.result.out ]]; then 387 # Output from /logs sometimes includes NULs. Strip them. 388 output=$(tr -d '\0' < $WORKDIR/curl.result.out) 389 390 if [[ $content_type =~ application/json ]] && [[ $method != "HEAD" ]]; then 391 jq . <<<"$output" >>$LOG 392 else 393 echo "$output" >>$LOG 394 fi 395 else 396 output= 397 echo "[no output]" >>$LOG 398 fi 399 400 # Test return code 401 is "$actual_code" "$expected_code" "$testname : status" 402 403 # Special case: 204/304, by definition, MUST NOT return content (rfc2616) 404 if [[ $expected_code = 204 || $expected_code = 304 ]]; then 405 if [ -n "$*" ]; then 406 die "Internal error: ${expected_code} status returns no output; fix your test." 407 fi 408 if [ -n "$output" ]; then 409 _show_ok 0 "$testname: ${expected_code} status returns no output" "''" "$output" 410 fi 411 return 412 fi 413 414 local i 415 416 # Special case: if response code does not match, dump the response body 417 # and skip all further subtests. 418 if [[ "$actual_code" != "$expected_code" ]]; then 419 echo -e "# response: $output" 420 for i; do 421 _show_ok skip "$testname: $i # skip - wrong return code" 422 done 423 return 424 fi 425 426 for i; do 427 if expr "$i" : '[^\!]\+\!=.\+' >/dev/null; then 428 # Disequality on json field 429 json_field=$(expr "$i" : '\([^!]*\)!') 430 expect_not=$(expr "$i" : '[^\!]*\!=\(.*\)') 431 actual=$(jq -r "$json_field" <<<"$output") 432 is_not "$actual" "$expect_not" "$testname : $json_field" 433 elif expr "$i" : "[^=~]\+=.*" >/dev/null; then 434 # Exact match on json field 435 json_field=$(expr "$i" : "\([^=]*\)=") 436 expect=$(expr "$i" : '[^=]*=\(.*\)') 437 actual=$(jq -r "$json_field" <<<"$output") 438 is "$actual" "$expect" "$testname : $json_field" 439 elif expr "$i" : "[^=~]\+~.*" >/dev/null; then 440 # regex match on json field 441 json_field=$(expr "$i" : "\([^~]*\)~") 442 expect=$(expr "$i" : '[^~]*~\(.*\)') 443 actual=$(jq -r "$json_field" <<<"$output") 444 like "$actual" "$expect" "$testname : $json_field" 445 else 446 # Direct string comparison 447 is "$output" "$i" "$testname : output" 448 fi 449 done 450 } 451 452 ################### 453 # start_service # Run the socket listener 454 ################### 455 service_pid= 456 function start_service() { 457 # If there's a listener on the port, nothing for us to do 458 { exec 3<> /dev/tcp/$HOST/$PORT; } &>/dev/null && return 459 460 test -x $PODMAN_BIN || die "Not found: $PODMAN_BIN" 461 462 if [ "$HOST" != "localhost" ]; then 463 die "Cannot start service on non-localhost ($HOST)" 464 fi 465 466 # FIXME: EXPERIMENTAL: 2022-06-13: podman rootless needs a namespace. If 467 # system-service is the first podman command run (as is the case in CI) 468 # this will happen as a fork-exec, where the parent podman creates the 469 # namespace and the child is the server. Then, when stop_service() kills 470 # the parent, the child (server) happily stays alive and ruins subsequent 471 # tests that try to restart service with different settings. 472 # Workaround: run an unshare to get namespaces initialized. 473 if [[ $(id -u) != 0 ]]; then 474 $PODMAN_BIN unshare true 475 fi 476 477 CONTAINERS_REGISTRIES_CONF=$TESTS_DIR/../registries.conf \ 478 $PODMAN_BIN \ 479 --root $WORKDIR/server_root --syslog=true \ 480 system service \ 481 --time 0 \ 482 tcp:127.0.0.1:$PORT \ 483 &> $WORKDIR/server.log & 484 service_pid=$! 485 echo "# started service, pid $service_pid" 486 487 wait_for_port $HOST $PORT 488 } 489 490 function stop_service() { 491 # Stop the server 492 if [[ -n $service_pid ]]; then 493 kill $service_pid || : 494 wait $service_pid || : 495 echo "# stopped service, pid $service_pid" 496 fi 497 service_pid= 498 499 if { exec 3<> /dev/tcp/$HOST/$PORT; } &>/dev/null; then 500 echo "# WARNING: stop_service: Service still running on port $PORT" 501 fi 502 503 } 504 505 #################### 506 # start_registry # Run a local registry 507 #################### 508 REGISTRY_PORT= 509 REGISTRY_USERNAME= 510 REGISTRY_PASSWORD= 511 function start_registry() { 512 # We can be called multiple times, but each time should start a new 513 # registry container with (possibly) different configuration. That 514 # means that all callers must be responsible for invoking stop_registry. 515 if [[ -n "$REGISTRY_PORT" ]]; then 516 die "start_registry invoked twice in succession, without stop_registry" 517 fi 518 519 # First arg is auth type (default: "none", but can also be "htpasswd") 520 local auth="${1:-none}" 521 522 REGISTRY_PORT=$(random_port) 523 524 local REGDIR=$WORKDIR/registry 525 local AUTHDIR=$REGDIR/auth 526 mkdir -p $AUTHDIR 527 528 mkdir -p ${REGDIR}/{root,runroot} 529 local PODMAN_REGISTRY_ARGS="--root ${REGDIR}/root --runroot ${REGDIR}/runroot" 530 531 # Give it three tries, to compensate for network flakes 532 podman ${PODMAN_REGISTRY_ARGS} pull $REGISTRY_IMAGE || 533 podman ${PODMAN_REGISTRY_ARGS} pull $REGISTRY_IMAGE || 534 podman ${PODMAN_REGISTRY_ARGS} pull $REGISTRY_IMAGE 535 536 # Create a local cert (no need to do this more than once) 537 if [[ ! -e $AUTHDIR/domain.key ]]; then 538 # FIXME: is there a hidden "--quiet" flag? This is too noisy. 539 openssl req -newkey rsa:4096 -nodes -sha256 \ 540 -keyout $AUTHDIR/domain.key -x509 -days 2 \ 541 -out $AUTHDIR/domain.crt \ 542 -subj "/C=US/ST=Foo/L=Bar/O=Red Hat, Inc./CN=registry host certificate" \ 543 -addext subjectAltName=DNS:localhost 544 fi 545 546 # If invoked with auth=htpasswd, create credentials 547 REGISTRY_USERNAME= 548 REGISTRY_PASSWORD= 549 declare -a registry_auth_params=(-e "REGISTRY_AUTH=$auth") 550 if [[ "$auth" = "htpasswd" ]]; then 551 REGISTRY_USERNAME=u$(random_string 7) 552 REGISTRY_PASSWORD=p$(random_string 7) 553 554 htpasswd -Bbn ${REGISTRY_USERNAME} ${REGISTRY_PASSWORD} \ 555 > $AUTHDIR/htpasswd 556 557 registry_auth_params+=( 558 -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" 559 -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" 560 ) 561 fi 562 563 # Run the registry, and wait for it to come up 564 podman ${PODMAN_REGISTRY_ARGS} run -d \ 565 -p ${REGISTRY_PORT}:5000 \ 566 --name registry \ 567 -v $AUTHDIR:/auth:Z \ 568 "${registry_auth_params[@]}" \ 569 -e REGISTRY_HTTP_TLS_CERTIFICATE=/auth/domain.crt \ 570 -e REGISTRY_HTTP_TLS_KEY=/auth/domain.key \ 571 ${REGISTRY_IMAGE} 572 573 wait_for_port localhost $REGISTRY_PORT 10 574 echo "# started registry (auth=$auth) on port $PORT" 575 } 576 577 function stop_registry() { 578 local REGDIR=${WORKDIR}/registry 579 if [[ -d $REGDIR ]]; then 580 local OPTS="--root ${REGDIR}/root --runroot ${REGDIR}/runroot" 581 podman $OPTS stop -i -t 0 registry 582 583 # rm/rmi are important when running rootless: without them we 584 # get EPERMS in tmpdir cleanup because files are owned by subuids. 585 podman $OPTS rm -f -i registry 586 if [[ "$1" = "--cleanup" ]]; then 587 podman $OPTS rmi -f -a 588 fi 589 echo "# stopped registry on port $PORT" 590 fi 591 592 REGISTRY_PORT= 593 REGISTRY_USERNAME= 594 REGISTRY_PASSWORD= 595 } 596 597 ################# 598 # random_port # Random open port; arg is range (min-max), default 5000-5999 599 ################# 600 function random_port() { 601 local range=${1:-5000-5999} 602 603 local port 604 for port in $(shuf -i ${range}); do 605 if ! { exec 5<> /dev/tcp/127.0.0.1/$port; } &>/dev/null; then 606 echo $port 607 return 608 fi 609 done 610 611 die "Could not find open port in range $range" 612 } 613 614 ################### 615 # random_string # Pseudorandom alphanumeric string of given length 616 ################### 617 function random_string() { 618 local length=${1:-10} 619 head /dev/urandom | tr -dc a-zA-Z0-9 | head -c$length 620 } 621 622 ################### 623 # wait_for_port # Returns once port is available on host 624 ################### 625 function wait_for_port() { 626 local host=$1 # Probably "localhost" 627 local port=$2 # Numeric port 628 local _timeout=${3:-5} # Optional; default to 5 seconds 629 630 local path=/dev/tcp/$host/$port 631 632 # Wait 633 local i=$_timeout 634 while [ $i -gt 0 ]; do 635 { exec 3<> /dev/tcp/$host/$port; } &>/dev/null && return 636 sleep 1 637 i=$(( $i - 1 )) 638 done 639 die "Timed out (${_timeout}s) waiting for service ($path)" 640 } 641 642 ############ 643 # podman # Needed by some test scripts to invoke the actual podman binary 644 ############ 645 function podman() { 646 echo "\$ $PODMAN_BIN $*" >>$WORKDIR/output.log 647 # env CONTAINERS_REGISTRIES_CONF=$TESTS_DIR/../registries.conf \ 648 $PODMAN_BIN --root $WORKDIR/server_root "$@" >>$WORKDIR/output.log 2>&1 649 } 650 651 #################### 652 # root, rootless # Is server rootless? 653 #################### 654 ROOTLESS= 655 function root() { 656 ! rootless 657 } 658 659 function rootless() { 660 if [[ -z $ROOTLESS ]]; then 661 ROOTLESS=$(curl -s http://$HOST:$PORT/v1.40/info | jq .Rootless) 662 fi 663 test "$ROOTLESS" = "true" 664 } 665 666 # True if cgroups v2 are enabled 667 function have_cgroupsv2() { 668 cgroup_type=$(stat -f -c %T /sys/fs/cgroup) 669 test "$cgroup_type" = "cgroup2fs" 670 } 671 672 # END infrastructure code 673 ############################################################################### 674 # BEGIN sanity checks 675 676 for tool in curl jq podman; do 677 type $tool &>/dev/null || die "$ME: Required tool '$tool' not found" 678 done 679 680 # END sanity checks 681 ############################################################################### 682 # BEGIN entry handler (subtest invoker) 683 684 echo '============================= test session starts ==============================' 685 echo "podman client -- $(curl --version)" 686 687 # Identify the tests to run. If called with args, use those as globs. 688 tests_to_run=() 689 if [ -n "$*" ]; then 690 shopt -s nullglob 691 for i; do 692 match=(${TESTS_DIR}/*${i}*.at) 693 if [ ${#match} -eq 0 ]; then 694 die "No match for $TESTS_DIR/*$i*.at" 695 fi 696 tests_to_run+=("${match[@]}") 697 done 698 shopt -u nullglob 699 else 700 tests_to_run=($TESTS_DIR/*.at) 701 fi 702 echo -e "collected ${#tests_to_run[@]} items\n" 703 704 start_service 705 706 for i in "${tests_to_run[@]}"; do 707 TEST_CONTEXT="[$(basename $i .at)]" 708 709 # Clear output from 'podman' helper 710 truncate --size=0 $WORKDIR/output.log 711 712 source $i 713 done 714 715 # END entry handler 716 ############################################################################### 717 718 clean_up_server 719 720 test_count=$(<$testcounter_file) 721 failure_count=$(<$failures_file) 722 723 if [ -z "$PODMAN_TESTS_KEEP_WORKDIR" ]; then 724 rm -rf $WORKDIR 725 fi 726 727 echo "1..${test_count}" 728 729 exit $failure_count