blob: 1e43cdc411fc3f29e26858350dcb5851aa37799c (
plain)
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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
|
#!/usr/bin/env bats -*- bats -*-
#
# Test podman shell completion
#
# Shell completion is provided via the cobra library
# It is implement by calling a hidden subcommand called "__complete"
#
load helpers
function check_shell_completion() {
local count=0
# Newline character; used for confirming string output
local nl="
"
for cmd in $(_podman_commands "$@"); do
# Human-readable podman command string, with multiple spaces collapsed
name="podman"
if is_remote; then
name="podman-remote"
fi
command_string="$name $* $cmd"
command_string=${command_string// / } # 'podman x' -> 'podman x'
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)
[ -n "$usage" ] || die "podman $cmd: no Usage message found"
# If usage ends in '[command]', recurse into subcommands
if expr "$usage" : '.*\[command\]$' >/dev/null; then
check_shell_completion "$@" $cmd
continue
fi
# Trim to command path so we only have the args
args="${usage/$command_string/}"
# Trim leading whitespaces
args="${args#"${args%%[![:space:]]*}"}"
# Extra args is used to match the correct argument number for the command
# This is important because some commands provide different suggestions based
# on the number of arguments.
extra_args=()
for arg in $args; do
match=false
i=0
while true; do
case $arg in
# If we have options than we need to check if we are getting flag completion
"[options]")
# skip this for remote it fails if a command only has the latest flag e.g podman top
if ! is_remote; then
run_completion "$@" $cmd "--"
# If this fails there is most likely a problem with the cobra library
is "${lines[0]}" "--.*" "Found flag in suggestions"
[ ${#lines[@]} -gt 2 ] || die "No flag suggestions"
_check_completion_end NoFileComp
fi
# continue the outer for args loop
continue 2
;;
*CONTAINER*)
run_completion "$@" $cmd "${extra_args[@]}" ""
is "$output" ".*-$random_container_name${nl}" "Found expected container in suggestions"
match=true
# resume
;;&
*POD*)
run_completion "$@" $cmd "${extra_args[@]}" ""
is "$output" ".*-$random_pod_name${nl}" "Found expected pod in suggestions"
_check_completion_end NoFileComp
match=true
# resume
;;&
*IMAGE*)
run_completion "$@" $cmd "${extra_args[@]}" ""
is "$output" ".*localhost/$random_image_name:$random_image_tag${nl}" "Found expected image in suggestions"
# check that we complete the image with and without tag after at least one char is typed
run_completion "$@" $cmd "${extra_args[@]}" "${random_image_name:0:1}"
is "$output" ".*$random_image_name:$random_image_tag${nl}" "Found expected image with tag in suggestions"
is "$output" ".*$random_image_name${nl}" "Found expected image without tag in suggestions"
# check that we complete the image id after at least two chars are typed
run_completion "$@" $cmd "${extra_args[@]}" "${random_image_id:0:2}"
is "$output" ".*$random_image_id${nl}" "Found expected image id in suggestions"
match=true
# resume
;;&
*NETWORK*)
run_completion "$@" $cmd "${extra_args[@]}" ""
is "$output" ".*$random_network_name${nl}" "Found network in suggestions"
_check_completion_end NoFileComp
match=true
# resume
;;&
*VOLUME*)
run_completion "$@" $cmd "${extra_args[@]}" ""
is "$output" ".*$random_volume_name${nl}" "Found volume in suggestions"
_check_completion_end NoFileComp
match=true
# resume
;;&
*REGISTRY*)
run_completion "$@" $cmd "${extra_args[@]}" ""
### FIXME how can we get the configured registries?
_check_completion_end NoFileComp
### FIXME this fails if no registries are configured
[[ ${#lines[@]} -gt 2 ]] || die "No registries found in suggestions"
match=true
# resume
;;&
*PATH* | *CONTEXT* | *KUBEFILE* | *COMMAND* | *ARG...* | *URI*)
# default shell completion should be done for everthing which accepts a path
run_completion "$@" $cmd "${extra_args[@]}" ""
# cp is a special case it returns ShellCompDirectiveNoSpace
if [[ "$cmd" == "cp" ]]; then
_check_completion_end NoSpace
else
_check_completion_end Default
[[ ${#lines[@]} -eq 2 ]] || die "Suggestions are in the output"
fi
;;
*)
if [[ "$match" == "false" ]]; then
dprint "UNKNOWN arg: $arg for $command_string ${extra_args[*]}"
fi
;;
esac
# Increment the argument array
extra_args+=("arg")
i=$(($i + 1))
# If the argument ends with ...] than we accept 0...n args
# Loop three times to make sure we are not only completing the first arg
if [[ ! ${arg} =~ "..." ]] || [[ i -gt 3 ]]; then
break
fi
done
done
# If the command takes no more parameters make sure we are getting no completion
if [[ ! ${args##* } =~ "..." ]]; then
run_completion "$@" $cmd "${extra_args[@]}" ""
_check_completion_end NoFileComp
if [ ${#lines[@]} -gt 2 ]; then
# checking for line count is not enough since we may inlcude additional debug output
# lines starting with [Debug] are allowed
i=0
length=$(( ${#lines[@]} - 2 ))
while [[ i -lt length ]]; do
[[ "${lines[$i]:0:7}" == "[Debug]" ]] || die "Suggestions are in the output"
i=$(( i + 1 ))
done
fi
fi
done
}
# run the completion cmd
function run_completion() {
PODMAN="$PODMAN_COMPLETION" run_podman "$@"
}
# check for the given ShellCompDirective (always last line)
function _check_completion_end() {
is "${lines[-1]}" "Completion ended with directive: ShellCompDirective$1" "Completion has wrong ShellCompDirective set"
}
@test "podman shell completion test" {
random_container_name=$(random_string 30)
random_pod_name=$(random_string 30)
random_image_name=$(random_string 30)
random_image_name=${random_image_name,,} # name must be lowercase
random_image_tag=$(random_string 5)
random_network_name=$(random_string 30)
random_volume_name=$(random_string 30)
# create a container for each state since some commands are only suggesting running container for example
run_podman create --name created-$random_container_name $IMAGE
run_podman run --name running-$random_container_name -d $IMAGE top
run_podman run --name pause-$random_container_name -d $IMAGE top
run_podman pause pause-$random_container_name
run_podman run --name exited-$random_container_name -d $IMAGE echo exited
# create pods for each state
run_podman pod create --name created-$random_pod_name
run_podman pod create --name running-$random_pod_name
run_podman run -d --name running-$random_pod_name-con --pod running-$random_pod_name $IMAGE top
run_podman pod create --name degraded-$random_pod_name
run_podman run -d --name degraded-$random_pod_name-con --pod degraded-$random_pod_name $IMAGE echo degraded
run_podman pod create --name exited-$random_pod_name
run_podman run -d --name exited-$random_pod_name-con --pod exited-$random_pod_name $IMAGE echo exited
run_podman pod stop exited-$random_pod_name
# create image name (just tag with new names no need to pull)
run_podman image tag $IMAGE $random_image_name:$random_image_tag
run_podman image list --format '{{.ID}}' --filter reference=$random_image_name
random_image_id="${lines[0]}"
# create network
run_podman network create $random_network_name
# create volume
run_podman volume create $random_volume_name
# $PODMAN may be a space-separated string, e.g. if we include a --url.
local -a podman_as_array=($PODMAN)
# __completeNoDesc must be the first arg if we running the completion cmd
PODMAN_COMPLETION="${podman_as_array[0]} __completeNoDesc ${podman_as_array[@]:1}"
# Called with no args -- start with 'podman --help'. check_shell_completion() will
# recurse for any subcommands.
check_shell_completion
# cleanup
run_podman volume rm $random_volume_name
run_podman network rm $random_network_name
run_podman image untag $IMAGE $random_image_name:$random_image_tag
for state in created running degraded exited; do
run_podman pod rm --force $state-$random_pod_name
done
for state in created running pause exited; do
run_podman rm --force $state-$random_container_name
done
# Clean up the pod pause image
run_podman image list --format '{{.ID}} {{.Repository}}'
while read id name; do
if [[ "$name" =~ /pause ]]; then
run_podman rmi $id
fi
done <<<"$output"
}
|