diff options
author | OpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com> | 2020-12-09 14:47:05 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-09 14:47:05 -0500 |
commit | da062b5bd03dd88060eb91c7d02936d5e7427cb9 (patch) | |
tree | 4b61e35336b54b815e0cf844778eb8e29906a120 | |
parent | 9abbe0728c5050914168a154622087a4dacd4dfe (diff) | |
parent | 2870a0b0a6b94528b82df7cee57c8c6a0252fc85 (diff) | |
download | podman-da062b5bd03dd88060eb91c7d02936d5e7427cb9.tar.gz podman-da062b5bd03dd88060eb91c7d02936d5e7427cb9.tar.bz2 podman-da062b5bd03dd88060eb91c7d02936d5e7427cb9.zip |
Merge pull request #8635 from Luap99/shell-completion-test
Add system test for shell completion
-rw-r--r-- | cmd/podman/common/completion.go | 78 | ||||
-rw-r--r-- | cmd/podman/containers/commit.go | 2 | ||||
-rw-r--r-- | cmd/podman/containers/cp.go | 2 | ||||
-rw-r--r-- | cmd/podman/containers/exec.go | 2 | ||||
-rw-r--r-- | cmd/podman/containers/logs.go | 6 | ||||
-rw-r--r-- | cmd/podman/containers/port.go | 2 | ||||
-rw-r--r-- | cmd/podman/containers/runlabel.go | 2 | ||||
-rw-r--r-- | cmd/podman/diff.go | 2 | ||||
-rw-r--r-- | cmd/podman/generate/kube.go | 2 | ||||
-rw-r--r-- | cmd/podman/generate/systemd.go | 2 | ||||
-rw-r--r-- | cmd/podman/images/build.go | 3 | ||||
-rw-r--r-- | cmd/podman/images/import.go | 5 | ||||
-rw-r--r-- | cmd/podman/images/push.go | 2 | ||||
-rw-r--r-- | cmd/podman/images/save.go | 2 | ||||
-rw-r--r-- | cmd/podman/images/untag.go | 2 | ||||
-rw-r--r-- | cmd/podman/inspect.go | 4 | ||||
-rw-r--r-- | cmd/podman/manifest/push.go | 2 | ||||
-rw-r--r-- | cmd/podman/networks/create.go | 2 | ||||
-rw-r--r-- | cmd/podman/play/kube.go | 2 | ||||
-rw-r--r-- | cmd/podman/pods/prune.go | 4 | ||||
-rw-r--r-- | cmd/podman/system/service.go | 3 | ||||
-rw-r--r-- | cmd/podman/system/unshare.go | 2 | ||||
-rw-r--r-- | test/system/015-help.bats | 13 | ||||
-rw-r--r-- | test/system/600-completion.bats | 272 | ||||
-rw-r--r-- | test/system/helpers.bash | 10 |
25 files changed, 392 insertions, 36 deletions
diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go index 25f4d0f79..f792b2713 100644 --- a/cmd/podman/common/completion.go +++ b/cmd/podman/common/completion.go @@ -278,7 +278,6 @@ func validCurrentCmdLine(cmd *cobra.Command, args []string, toComplete string) b return true } } - cobra.CompDebugln(err.Error(), true) return false } return true @@ -445,6 +444,29 @@ func AutocompleteNetworks(cmd *cobra.Command, args []string, toComplete string) return getNetworks(cmd, toComplete) } +// AutocompleteDefaultOneArg - Autocomplete path only for the first argument. +func AutocompleteDefaultOneArg(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if len(args) == 0 { + return nil, cobra.ShellCompDirectiveDefault + } + return nil, cobra.ShellCompDirectiveNoFileComp +} + +// AutocompleteCommitCommand - Autocomplete podman commit command args. +func AutocompleteCommitCommand(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } + if len(args) == 0 { + return getContainers(cmd, toComplete, completeDefault) + } + if len(args) == 1 { + return getImages(cmd, toComplete) + } + // don't complete more than 2 args + return nil, cobra.ShellCompDirectiveNoFileComp +} + // AutocompleteCpCommand - Autocomplete podman cp command args. func AutocompleteCpCommand(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if !validCurrentCmdLine(cmd, args, toComplete) { @@ -465,6 +487,43 @@ func AutocompleteCpCommand(cmd *cobra.Command, args []string, toComplete string) return nil, cobra.ShellCompDirectiveNoFileComp } +// AutocompleteExecCommand - Autocomplete podman exec command args. +func AutocompleteExecCommand(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } + if len(args) == 0 { + return getContainers(cmd, toComplete, completeDefault, "running") + } + return nil, cobra.ShellCompDirectiveDefault +} + +// AutocompleteRunlabelCommand - Autocomplete podman container runlabel command args. +func AutocompleteRunlabelCommand(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } + if len(args) == 0 { + // FIXME: What labels can we recommend here? + return nil, cobra.ShellCompDirectiveNoFileComp + } + if len(args) == 1 { + return getImages(cmd, toComplete) + } + return nil, cobra.ShellCompDirectiveDefault +} + +// AutocompletePortCommand - Autocomplete podman port command args. +func AutocompletePortCommand(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } + if len(args) == 0 { + return getContainers(cmd, toComplete, completeDefault) + } + return nil, cobra.ShellCompDirectiveNoFileComp +} + // AutocompleteNetworkConnectCmd - Autocomplete podman network connect/disconnect command args. func AutocompleteNetworkConnectCmd(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) == 0 { @@ -496,6 +555,23 @@ func AutocompleteTopCmd(cmd *cobra.Command, args []string, toComplete string) ([ return descriptors, cobra.ShellCompDirectiveNoFileComp } +// AutocompleteInspect - Autocomplete podman inspect. +func AutocompleteInspect(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if !validCurrentCmdLine(cmd, args, toComplete) { + return nil, cobra.ShellCompDirectiveNoFileComp + } + containers, _ := getContainers(cmd, toComplete, completeDefault) + images, _ := getImages(cmd, toComplete) + pods, _ := getPods(cmd, toComplete, completeDefault) + networks, _ := getNetworks(cmd, toComplete) + volumes, _ := getVolumes(cmd, toComplete) + suggestions := append(containers, images...) + suggestions = append(suggestions, pods...) + suggestions = append(suggestions, networks...) + suggestions = append(suggestions, volumes...) + return suggestions, cobra.ShellCompDirectiveNoFileComp +} + // AutocompleteSystemConnections - Autocomplete system connections. func AutocompleteSystemConnections(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if !validCurrentCmdLine(cmd, args, toComplete) { diff --git a/cmd/podman/containers/commit.go b/cmd/podman/containers/commit.go index c5c7673b2..ff06e10f7 100644 --- a/cmd/podman/containers/commit.go +++ b/cmd/podman/containers/commit.go @@ -24,7 +24,7 @@ var ( Long: commitDescription, RunE: commit, Args: cobra.RangeArgs(1, 2), - ValidArgsFunction: common.AutocompleteContainers, + ValidArgsFunction: common.AutocompleteCommitCommand, Example: `podman commit -q --message "committing container to image" reverent_golick image-committed podman commit -q --author "firstName lastName" reverent_golick image-committed podman commit -q --pause=false containerID image-committed diff --git a/cmd/podman/containers/cp.go b/cmd/podman/containers/cp.go index fd3aa7680..9b0a01a2f 100644 --- a/cmd/podman/containers/cp.go +++ b/cmd/podman/containers/cp.go @@ -13,7 +13,7 @@ var ( You can copy from the container's file system to the local machine or the reverse, from the local filesystem to the container. If "-" is specified for either the SRC_PATH or DEST_PATH, you can also stream a tar archive from STDIN or to STDOUT. The CONTAINER can be a running or stopped container. The SRC_PATH or DEST_PATH can be a file or directory. ` cpCommand = &cobra.Command{ - Use: "cp [options] SRC_PATH DEST_PATH", + Use: "cp [options] [CONTAINER:]SRC_PATH [CONTAINER:]DEST_PATH", Short: "Copy files/folders between a container and the local filesystem", Long: cpDescription, Args: cobra.ExactArgs(2), diff --git a/cmd/podman/containers/exec.go b/cmd/podman/containers/exec.go index 306bae58e..3d4918d50 100644 --- a/cmd/podman/containers/exec.go +++ b/cmd/podman/containers/exec.go @@ -26,7 +26,7 @@ var ( Long: execDescription, RunE: exec, DisableFlagsInUseLine: true, - ValidArgsFunction: common.AutocompleteContainersRunning, + ValidArgsFunction: common.AutocompleteExecCommand, Example: `podman exec -it ctrID ls podman exec -it -w /tmp myCtr pwd podman exec --user root ctrID ls`, diff --git a/cmd/podman/containers/logs.go b/cmd/podman/containers/logs.go index 1fa4ac11f..d4ede370a 100644 --- a/cmd/podman/containers/logs.go +++ b/cmd/podman/containers/logs.go @@ -69,6 +69,12 @@ var ( ) func init() { + // if run remotely we only allow one container arg + if registry.IsRemote() { + logsCommand.Use = "logs [options] CONTAINER" + containerLogsCommand.Use = logsCommand.Use + } + // logs registry.Commands = append(registry.Commands, registry.CliCommand{ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, diff --git a/cmd/podman/containers/port.go b/cmd/podman/containers/port.go index ac31e158e..d59161149 100644 --- a/cmd/podman/containers/port.go +++ b/cmd/podman/containers/port.go @@ -26,7 +26,7 @@ var ( Args: func(cmd *cobra.Command, args []string) error { return validate.CheckAllLatestAndCIDFile(cmd, args, true, false) }, - ValidArgsFunction: common.AutocompleteContainers, + ValidArgsFunction: common.AutocompletePortCommand, Example: `podman port --all podman port ctrID 80/tcp podman port --latest 80`, diff --git a/cmd/podman/containers/runlabel.go b/cmd/podman/containers/runlabel.go index 2f6d2eb05..6ebba4935 100644 --- a/cmd/podman/containers/runlabel.go +++ b/cmd/podman/containers/runlabel.go @@ -30,7 +30,7 @@ var ( Long: runlabelDescription, RunE: runlabel, Args: cobra.MinimumNArgs(2), - ValidArgsFunction: common.AutocompleteImages, + ValidArgsFunction: common.AutocompleteRunlabelCommand, Example: `podman container runlabel run imageID podman container runlabel install imageID arg1 arg2 podman container runlabel --display run myImage`, diff --git a/cmd/podman/diff.go b/cmd/podman/diff.go index 5e6abe243..e094e6bdd 100644 --- a/cmd/podman/diff.go +++ b/cmd/podman/diff.go @@ -18,7 +18,7 @@ var ( // Command: podman _diff_ Object_ID diffDescription = `Displays changes on a container or image's filesystem. The container or image will be compared to its parent layer.` diffCmd = &cobra.Command{ - Use: "diff [options] {CONTAINER_ID | IMAGE_ID}", + Use: "diff [options] {CONTAINER|IMAGE}", Args: validate.IDOrLatestArgs, Short: "Display the changes to the object's file system", Long: diffDescription, diff --git a/cmd/podman/generate/kube.go b/cmd/podman/generate/kube.go index 0517db19a..cb608e7b5 100644 --- a/cmd/podman/generate/kube.go +++ b/cmd/podman/generate/kube.go @@ -22,7 +22,7 @@ var ( Whether the input is for a container or pod, Podman will always generate the specification as a pod.` kubeCmd = &cobra.Command{ - Use: "kube [options] CONTAINER... | POD", + Use: "kube [options] {CONTAINER...|POD}", Short: "Generate Kubernetes YAML from a container or pod.", Long: kubeDescription, RunE: kube, diff --git a/cmd/podman/generate/systemd.go b/cmd/podman/generate/systemd.go index e9cf76aae..f9099d3b8 100644 --- a/cmd/podman/generate/systemd.go +++ b/cmd/podman/generate/systemd.go @@ -26,7 +26,7 @@ var ( The generated units can later be controlled via systemctl(1).` systemdCmd = &cobra.Command{ - Use: "systemd [options] CTR|POD", + Use: "systemd [options] {CONTAINER|POD}", Short: "Generate systemd units.", Long: systemdDescription, RunE: systemd, diff --git a/cmd/podman/images/build.go b/cmd/podman/images/build.go index 739e1c265..48b355ecd 100644 --- a/cmd/podman/images/build.go +++ b/cmd/podman/images/build.go @@ -11,6 +11,7 @@ import ( "github.com/containers/buildah/pkg/parse" "github.com/containers/common/pkg/completion" "github.com/containers/common/pkg/config" + "github.com/containers/podman/v2/cmd/podman/common" "github.com/containers/podman/v2/cmd/podman/registry" "github.com/containers/podman/v2/cmd/podman/utils" "github.com/containers/podman/v2/pkg/domain/entities" @@ -44,7 +45,7 @@ var ( Long: buildDescription, Args: cobra.MaximumNArgs(1), RunE: build, - ValidArgsFunction: completion.AutocompleteDefault, + ValidArgsFunction: common.AutocompleteDefaultOneArg, Example: `podman build . podman build --creds=username:password -t imageName -f Containerfile.simple . podman build --layers --force-rm --tag imageName .`, diff --git a/cmd/podman/images/import.go b/cmd/podman/images/import.go index f38ab3b19..ac59935ad 100644 --- a/cmd/podman/images/import.go +++ b/cmd/podman/images/import.go @@ -25,18 +25,19 @@ var ( Short: "Import a tarball to create a filesystem image", Long: importDescription, RunE: importCon, - ValidArgsFunction: completion.AutocompleteDefault, + Args: cobra.RangeArgs(1, 2), + ValidArgsFunction: common.AutocompleteDefaultOneArg, Example: `podman import http://example.com/ctr.tar url-image cat ctr.tar | podman -q import --message "importing the ctr.tar tarball" - image-imported cat ctr.tar | podman import -`, } imageImportCommand = &cobra.Command{ - Args: cobra.MinimumNArgs(1), Use: importCommand.Use, Short: importCommand.Short, Long: importCommand.Long, RunE: importCommand.RunE, + Args: importCommand.Args, ValidArgsFunction: importCommand.ValidArgsFunction, Example: `podman image import http://example.com/ctr.tar url-image cat ctr.tar | podman -q image import --message "importing the ctr.tar tarball" - image-imported diff --git a/cmd/podman/images/push.go b/cmd/podman/images/push.go index 447b02fbe..d82083cd8 100644 --- a/cmd/podman/images/push.go +++ b/cmd/podman/images/push.go @@ -29,7 +29,7 @@ var ( // Command: podman push pushCmd = &cobra.Command{ - Use: "push [options] SOURCE [DESTINATION]", + Use: "push [options] IMAGE [DESTINATION]", Short: "Push an image to a specified destination", Long: pushDescription, RunE: imagePush, diff --git a/cmd/podman/images/save.go b/cmd/podman/images/save.go index 9ef2d0c91..3a35c4fad 100644 --- a/cmd/podman/images/save.go +++ b/cmd/podman/images/save.go @@ -43,7 +43,7 @@ var ( } return nil }, - ValidArgsFunction: completion.AutocompleteNone, + ValidArgsFunction: common.AutocompleteImages, Example: `podman save --quiet -o myimage.tar imageID podman save --format docker-dir -o ubuntu-dir ubuntu podman save > alpine-all.tar alpine:latest`, diff --git a/cmd/podman/images/untag.go b/cmd/podman/images/untag.go index 17dc21203..3cf62713b 100644 --- a/cmd/podman/images/untag.go +++ b/cmd/podman/images/untag.go @@ -9,7 +9,7 @@ import ( var ( untagCommand = &cobra.Command{ - Use: "untag IMAGE [NAME...]", + Use: "untag IMAGE [IMAGE...]", Short: "Remove a name from a local image", Long: "Removes one or more names from a locally-stored image.", RunE: untag, diff --git a/cmd/podman/inspect.go b/cmd/podman/inspect.go index f62abe931..64daae951 100644 --- a/cmd/podman/inspect.go +++ b/cmd/podman/inspect.go @@ -20,12 +20,12 @@ var ( // Command: podman _inspect_ Object_ID inspectCmd = &cobra.Command{ - Use: "inspect [options] {CONTAINER_ID | IMAGE_ID} [...]", + Use: "inspect [options] {CONTAINER|IMAGE|POD|NETWORK|VOLUME} [...]", Short: "Display the configuration of object denoted by ID", RunE: inspectExec, Long: inspectDescription, TraverseChildren: true, - ValidArgsFunction: common.AutocompleteContainersAndImages, + ValidArgsFunction: common.AutocompleteInspect, Example: `podman inspect fedora podman inspect --type image fedora podman inspect CtrID ImgID diff --git a/cmd/podman/manifest/push.go b/cmd/podman/manifest/push.go index a3b469491..89faa42a2 100644 --- a/cmd/podman/manifest/push.go +++ b/cmd/podman/manifest/push.go @@ -24,7 +24,7 @@ type manifestPushOptsWrapper struct { var ( manifestPushOpts = manifestPushOptsWrapper{} pushCmd = &cobra.Command{ - Use: "push [options] SOURCE DESTINATION", + Use: "push [options] LIST DESTINATION", Short: "Push a manifest list or image index to a registry", Long: "Pushes manifest lists and image indexes to registries.", RunE: push, diff --git a/cmd/podman/networks/create.go b/cmd/podman/networks/create.go index 8db4bb89a..1a091f111 100644 --- a/cmd/podman/networks/create.go +++ b/cmd/podman/networks/create.go @@ -17,7 +17,7 @@ import ( var ( networkCreateDescription = `create CNI networks for containers and pods` networkCreateCommand = &cobra.Command{ - Use: "create [options] [NETWORK]", + Use: "create [options] [NAME]", Short: "network create", Long: networkCreateDescription, RunE: networkCreate, diff --git a/cmd/podman/play/kube.go b/cmd/podman/play/kube.go index db70ad7d4..5e227d05a 100644 --- a/cmd/podman/play/kube.go +++ b/cmd/podman/play/kube.go @@ -39,7 +39,7 @@ var ( Long: kubeDescription, RunE: kube, Args: cobra.ExactArgs(1), - ValidArgsFunction: completion.AutocompleteDefault, + ValidArgsFunction: common.AutocompleteDefaultOneArg, Example: `podman play kube nginx.yml podman play kube --creds user:password --seccomp-profile-root /custom/path apache.yml`, } diff --git a/cmd/podman/pods/prune.go b/cmd/podman/pods/prune.go index e069c9b7f..965c36398 100644 --- a/cmd/podman/pods/prune.go +++ b/cmd/podman/pods/prune.go @@ -7,7 +7,7 @@ import ( "os" "strings" - "github.com/containers/podman/v2/cmd/podman/common" + "github.com/containers/common/pkg/completion" "github.com/containers/podman/v2/cmd/podman/registry" "github.com/containers/podman/v2/cmd/podman/utils" "github.com/containers/podman/v2/cmd/podman/validate" @@ -28,7 +28,7 @@ var ( Short: "Remove all stopped pods and their containers", Long: pruneDescription, RunE: prune, - ValidArgsFunction: common.AutocompletePods, + ValidArgsFunction: completion.AutocompleteNone, Example: `podman pod prune`, } ) diff --git a/cmd/podman/system/service.go b/cmd/podman/system/service.go index 42482b5d9..f8bdbfa10 100644 --- a/cmd/podman/system/service.go +++ b/cmd/podman/system/service.go @@ -10,6 +10,7 @@ import ( "time" "github.com/containers/common/pkg/completion" + "github.com/containers/podman/v2/cmd/podman/common" "github.com/containers/podman/v2/cmd/podman/registry" "github.com/containers/podman/v2/pkg/domain/entities" "github.com/containers/podman/v2/pkg/rootless" @@ -32,7 +33,7 @@ Enable a listening service for API access to Podman commands. Short: "Run API service", Long: srvDescription, RunE: service, - ValidArgsFunction: completion.AutocompleteDefault, + ValidArgsFunction: common.AutocompleteDefaultOneArg, Example: `podman system service --time=0 unix:///tmp/podman.sock`, } diff --git a/cmd/podman/system/unshare.go b/cmd/podman/system/unshare.go index 437cf7b2e..364852979 100644 --- a/cmd/podman/system/unshare.go +++ b/cmd/podman/system/unshare.go @@ -14,7 +14,7 @@ import ( var ( unshareDescription = "Runs a command in a modified user namespace." unshareCommand = &cobra.Command{ - Use: "unshare [COMMAND [ARG ...]]", + Use: "unshare [COMMAND [ARG...]]", DisableFlagsInUseLine: true, Short: "Run a command in a modified user namespace", Long: unshareDescription, diff --git a/test/system/015-help.bats b/test/system/015-help.bats index 22db8be8a..5f38c34a1 100644 --- a/test/system/015-help.bats +++ b/test/system/015-help.bats @@ -12,22 +12,11 @@ # load helpers -# run 'podman help', parse the output looking for 'Available Commands'; -# return that list. -function podman_commands() { - dprint "$@" - run_podman help "$@" |\ - awk '/^Available Commands:/{ok=1;next}/^Options:/{ok=0}ok { print $1 }' |\ - grep . - "$output" -} - - function check_help() { local count=0 local -A found - for cmd in $(podman_commands "$@"); do + for cmd in $(_podman_commands "$@"); do # Human-readable podman command string, with multiple spaces collapsed command_string="podman $* $cmd" command_string=${command_string// / } # 'podman x' -> 'podman x' diff --git a/test/system/600-completion.bats b/test/system/600-completion.bats new file mode 100644 index 000000000..1e43cdc41 --- /dev/null +++ b/test/system/600-completion.bats @@ -0,0 +1,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" + +} diff --git a/test/system/helpers.bash b/test/system/helpers.bash index 2cced10c2..6a7c6cc42 100644 --- a/test/system/helpers.bash +++ b/test/system/helpers.bash @@ -521,5 +521,15 @@ function remove_same_dev_warning() { output=$(printf '%s\n' "${lines[@]}") } +# run 'podman help', parse the output looking for 'Available Commands'; +# return that list. +function _podman_commands() { + dprint "$@" + run_podman help "$@" | + awk '/^Available Commands:/{ok=1;next}/^Options:/{ok=0}ok { print $1 }' | + grep . + "$output" +} + # END miscellaneous tools ############################################################################### |