1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
|
#!/usr/bin/env bats -*- bats -*-
#
# PR #15673: For all commands that accept --format '{{.GoTemplate}}',
# invoke with --format '{{"\n"}}' and make sure they don't choke.
#
load helpers
function teardown() {
# In case test fails: clean up all the entities we created
run_podman '?' machine rm -f "m-$(safename)"
run_podman '?' secret rm "s-$(safename)"
run_podman '?' pod rm -f "p-$(safename)"
run_podman '?' rm -f -t0 "c-$(safename)"
basic_teardown
}
# podman machine is finicky. Assume we can't run it, but see below for more.
can_run_podman_machine=
# podman stats, too
can_run_stats=
# Main test loop. Recursively runs 'podman [subcommand] help', looks for:
# > '[command]', which indicates, recurse; or
# > '--format', in which case we
# > check autocompletion, look for Go templates, in which case we
# > run the command with --format '{{"\n"}}' and make sure it passes
function check_subcommand() {
for cmd in $(_podman_commands "$@"); do
# Skip the compose command which is calling `docker-compose --help`
# and hence won't match the assumptions made below.
if [[ "$cmd" == "compose" ]]; then
continue
fi
# Human-readable podman command string, with multiple spaces collapsed
# Special case: 'podman machine' can only be run under ideal conditions
if [[ "$cmd" = "machine" ]] && [[ -z "$can_run_podman_machine" ]]; then
continue
fi
if [[ "$cmd" = "stats" ]] && [[ -z "$can_run_stats" ]]; then
continue
fi
# Human-readable podman command string, with multiple spaces collapsed
command_string="podman $* $cmd"
command_string=${command_string// / } # 'podman x' -> 'podman x'
# Run --help, decide if this is a subcommand with subcommands
run_podman "$@" $cmd --help
local full_help="$output"
# The line immediately after 'Usage:' gives us a 1-line synopsis
usage=$(echo "$full_help" | grep -A1 '^Usage:' | tail -1)
assert "$usage" != "" "podman $cmd: no Usage message found"
# Strip off the leading command string; we no longer need it
usage=$(sed -e "s/^ $command_string \?//" <<<"$usage")
# If usage ends in '[command]', recurse into subcommands
if expr "$usage" : '\[command\]' >/dev/null; then
# (except for 'podman help', which is a special case)
if [[ $cmd != "help" ]]; then
check_subcommand "$@" $cmd
fi
continue
fi
# Not a subcommand-subcommand. Look for --format option
if [[ ! "$output" =~ "--format" ]]; then
continue
fi
# Have --format. Make sure it's a Go-template option, not like --push
run_podman __completeNoDesc "$@" "$cmd" --format '{{.'
if [[ ! "$output" =~ \{\{\.[A-Z] ]]; then
continue
fi
# Got one.
dprint "$command_string has --format"
# Whatever is needed to make a runnable command
local extra=${extra_args[$command_string]}
if [[ -n "$extra" ]]; then
# Cross off our list
unset extra_args["$command_string"]
fi
# This is what does the work. We run with '?' so we can offer
# better error messages than just "exited with error status".
run_podman '?' "$@" "$cmd" $extra --format '{{"\n"}}'
# Special-case workaround for quay flakes
if [[ "$status" -ne 0 ]] && [[ "$*" =~ search ]] && [[ "$output" =~ quay.io ]]; then
echo "# Ignoring probable quay flake: $output" >&3
continue
fi
# Output must always be empty.
#
# - If you see "unterminated quoted string" here, there's a
# regression, and you need to fix --format (see PR #15673)
#
# - If you see any other error, it probably means that someone
# added a new podman subcommand that supports --format but
# needs some sort of option or argument to actually run.
# See 'extra_args_table' below.
#
assert "$output" = "" "$command_string --format '{{\"\n\"}}'"
# *Now* check exit status. This should never, ever, ever trigger!
# If it does, it means the podman command failed without an err msg!
assert "$status" = "0" \
"$command_string --format '{{\"\n\"}}' failed with no output!"
done
}
# Test entry point
# bats test_tags=ci:parallel
@test "check Go template formatting" {
skip_if_remote
ctrname="c-$(safename)"
podname="p-$(safename)"
secretname="s-$(safename)"
# Setup: some commands need a container, pod, secret, ...
run_podman run -d --name $ctrname $IMAGE top
run_podman pod create $podname
run_podman secret create $secretname /etc/hosts
# For 'search' and 'image search': if local cache registry is available,
# use it. This bypasses quay, and thus prevents flakes.
searchargs=$IMAGE
if [[ -n "$CI_USE_REGISTRY_CACHE" ]]; then
# FIXME: someday: find a way to refactor the hardcoded port
searchargs="--tls-verify=false 127.0.0.1:60333/we/dontactuallyneed:arealimage"
fi
# Most commands can't just be run with --format; they need an argument or
# option. This table defines what those are.
extra_args_table="
history | $IMAGE
image history | $IMAGE
image inspect | $IMAGE
container inspect | $ctrname
inspect | $ctrname
volume inspect | -a
secret inspect | $secretname
network inspect | podman
ps | -a
image search | $searchargs
search | $searchargs
pod inspect | $podname
events | --stream=false --events-backend=file
system events | --stream=false --events-backend=file
"
# ...or machine. But podman machine is ultra-finicky, it fails as root
# or if qemu is missing. Instead of checking for all the possible ways
# to skip it, just try running init. If it works, we can test it.
machinename="m-$(safename)"
run_podman '?' machine init --image=/dev/null $machinename
if [[ $status -eq 0 ]]; then
can_run_podman_machine=true
extra_args_table+="
machine inspect | $machinename
"
fi
# Similarly, 'stats' cannot run rootless under cgroups v1
if ! is_rootless || is_cgroupsv2; then
can_run_stats=true
extra_args_table+="
container stats | --no-stream
pod stats | --no-stream
stats | --no-stream
"
fi
# Convert the table at top to an associative array, keyed on subcommand
declare -A extra_args
while read subcommand extra; do
extra_args["podman $subcommand"]=$extra
done < <(parse_table "$extra_args_table")
# Run the test
check_subcommand
# Clean up
run_podman pod rm $podname
run_podman rm -f -t0 $ctrname
run_podman secret rm $secretname
run_podman '?' machine rm -f $machinename
# Make sure there are no leftover commands in our table - this would
# indicate a typo in the table, or a flaw in our logic such that
# we're not actually recursing.
local leftovers="${!extra_args[@]}"
assert "$leftovers" = "" "Did not find (or test) subcommands:"
}
# vim: filetype=sh
|