mirror of
https://github.com/containers/podman.git
synced 2025-06-23 02:18:13 +08:00
Merge pull request #8635 from Luap99/shell-completion-test
Add system test for shell completion
This commit is contained in:
@ -278,7 +278,6 @@ func validCurrentCmdLine(cmd *cobra.Command, args []string, toComplete string) b
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cobra.CompDebugln(err.Error(), true)
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
@ -445,6 +444,29 @@ func AutocompleteNetworks(cmd *cobra.Command, args []string, toComplete string)
|
|||||||
return getNetworks(cmd, toComplete)
|
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.
|
// AutocompleteCpCommand - Autocomplete podman cp command args.
|
||||||
func AutocompleteCpCommand(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
func AutocompleteCpCommand(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
if !validCurrentCmdLine(cmd, args, toComplete) {
|
if !validCurrentCmdLine(cmd, args, toComplete) {
|
||||||
@ -465,6 +487,43 @@ func AutocompleteCpCommand(cmd *cobra.Command, args []string, toComplete string)
|
|||||||
return nil, cobra.ShellCompDirectiveNoFileComp
|
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.
|
// AutocompleteNetworkConnectCmd - Autocomplete podman network connect/disconnect command args.
|
||||||
func AutocompleteNetworkConnectCmd(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
func AutocompleteNetworkConnectCmd(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
@ -496,6 +555,23 @@ func AutocompleteTopCmd(cmd *cobra.Command, args []string, toComplete string) ([
|
|||||||
return descriptors, cobra.ShellCompDirectiveNoFileComp
|
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.
|
// AutocompleteSystemConnections - Autocomplete system connections.
|
||||||
func AutocompleteSystemConnections(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
func AutocompleteSystemConnections(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||||
if !validCurrentCmdLine(cmd, args, toComplete) {
|
if !validCurrentCmdLine(cmd, args, toComplete) {
|
||||||
|
@ -24,7 +24,7 @@ var (
|
|||||||
Long: commitDescription,
|
Long: commitDescription,
|
||||||
RunE: commit,
|
RunE: commit,
|
||||||
Args: cobra.RangeArgs(1, 2),
|
Args: cobra.RangeArgs(1, 2),
|
||||||
ValidArgsFunction: common.AutocompleteContainers,
|
ValidArgsFunction: common.AutocompleteCommitCommand,
|
||||||
Example: `podman commit -q --message "committing container to image" reverent_golick image-committed
|
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 --author "firstName lastName" reverent_golick image-committed
|
||||||
podman commit -q --pause=false containerID image-committed
|
podman commit -q --pause=false containerID image-committed
|
||||||
|
@ -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.
|
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{
|
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",
|
Short: "Copy files/folders between a container and the local filesystem",
|
||||||
Long: cpDescription,
|
Long: cpDescription,
|
||||||
Args: cobra.ExactArgs(2),
|
Args: cobra.ExactArgs(2),
|
||||||
|
@ -26,7 +26,7 @@ var (
|
|||||||
Long: execDescription,
|
Long: execDescription,
|
||||||
RunE: exec,
|
RunE: exec,
|
||||||
DisableFlagsInUseLine: true,
|
DisableFlagsInUseLine: true,
|
||||||
ValidArgsFunction: common.AutocompleteContainersRunning,
|
ValidArgsFunction: common.AutocompleteExecCommand,
|
||||||
Example: `podman exec -it ctrID ls
|
Example: `podman exec -it ctrID ls
|
||||||
podman exec -it -w /tmp myCtr pwd
|
podman exec -it -w /tmp myCtr pwd
|
||||||
podman exec --user root ctrID ls`,
|
podman exec --user root ctrID ls`,
|
||||||
|
@ -69,6 +69,12 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
// if run remotely we only allow one container arg
|
||||||
|
if registry.IsRemote() {
|
||||||
|
logsCommand.Use = "logs [options] CONTAINER"
|
||||||
|
containerLogsCommand.Use = logsCommand.Use
|
||||||
|
}
|
||||||
|
|
||||||
// logs
|
// logs
|
||||||
registry.Commands = append(registry.Commands, registry.CliCommand{
|
registry.Commands = append(registry.Commands, registry.CliCommand{
|
||||||
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
|
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
|
||||||
|
@ -26,7 +26,7 @@ var (
|
|||||||
Args: func(cmd *cobra.Command, args []string) error {
|
Args: func(cmd *cobra.Command, args []string) error {
|
||||||
return validate.CheckAllLatestAndCIDFile(cmd, args, true, false)
|
return validate.CheckAllLatestAndCIDFile(cmd, args, true, false)
|
||||||
},
|
},
|
||||||
ValidArgsFunction: common.AutocompleteContainers,
|
ValidArgsFunction: common.AutocompletePortCommand,
|
||||||
Example: `podman port --all
|
Example: `podman port --all
|
||||||
podman port ctrID 80/tcp
|
podman port ctrID 80/tcp
|
||||||
podman port --latest 80`,
|
podman port --latest 80`,
|
||||||
|
@ -30,7 +30,7 @@ var (
|
|||||||
Long: runlabelDescription,
|
Long: runlabelDescription,
|
||||||
RunE: runlabel,
|
RunE: runlabel,
|
||||||
Args: cobra.MinimumNArgs(2),
|
Args: cobra.MinimumNArgs(2),
|
||||||
ValidArgsFunction: common.AutocompleteImages,
|
ValidArgsFunction: common.AutocompleteRunlabelCommand,
|
||||||
Example: `podman container runlabel run imageID
|
Example: `podman container runlabel run imageID
|
||||||
podman container runlabel install imageID arg1 arg2
|
podman container runlabel install imageID arg1 arg2
|
||||||
podman container runlabel --display run myImage`,
|
podman container runlabel --display run myImage`,
|
||||||
|
@ -18,7 +18,7 @@ var (
|
|||||||
// Command: podman _diff_ Object_ID
|
// 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.`
|
diffDescription = `Displays changes on a container or image's filesystem. The container or image will be compared to its parent layer.`
|
||||||
diffCmd = &cobra.Command{
|
diffCmd = &cobra.Command{
|
||||||
Use: "diff [options] {CONTAINER_ID | IMAGE_ID}",
|
Use: "diff [options] {CONTAINER|IMAGE}",
|
||||||
Args: validate.IDOrLatestArgs,
|
Args: validate.IDOrLatestArgs,
|
||||||
Short: "Display the changes to the object's file system",
|
Short: "Display the changes to the object's file system",
|
||||||
Long: diffDescription,
|
Long: diffDescription,
|
||||||
|
@ -22,7 +22,7 @@ var (
|
|||||||
Whether the input is for a container or pod, Podman will always generate the specification as a pod.`
|
Whether the input is for a container or pod, Podman will always generate the specification as a pod.`
|
||||||
|
|
||||||
kubeCmd = &cobra.Command{
|
kubeCmd = &cobra.Command{
|
||||||
Use: "kube [options] CONTAINER... | POD",
|
Use: "kube [options] {CONTAINER...|POD}",
|
||||||
Short: "Generate Kubernetes YAML from a container or pod.",
|
Short: "Generate Kubernetes YAML from a container or pod.",
|
||||||
Long: kubeDescription,
|
Long: kubeDescription,
|
||||||
RunE: kube,
|
RunE: kube,
|
||||||
|
@ -26,7 +26,7 @@ var (
|
|||||||
The generated units can later be controlled via systemctl(1).`
|
The generated units can later be controlled via systemctl(1).`
|
||||||
|
|
||||||
systemdCmd = &cobra.Command{
|
systemdCmd = &cobra.Command{
|
||||||
Use: "systemd [options] CTR|POD",
|
Use: "systemd [options] {CONTAINER|POD}",
|
||||||
Short: "Generate systemd units.",
|
Short: "Generate systemd units.",
|
||||||
Long: systemdDescription,
|
Long: systemdDescription,
|
||||||
RunE: systemd,
|
RunE: systemd,
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/containers/buildah/pkg/parse"
|
"github.com/containers/buildah/pkg/parse"
|
||||||
"github.com/containers/common/pkg/completion"
|
"github.com/containers/common/pkg/completion"
|
||||||
"github.com/containers/common/pkg/config"
|
"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/registry"
|
||||||
"github.com/containers/podman/v2/cmd/podman/utils"
|
"github.com/containers/podman/v2/cmd/podman/utils"
|
||||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||||
@ -44,7 +45,7 @@ var (
|
|||||||
Long: buildDescription,
|
Long: buildDescription,
|
||||||
Args: cobra.MaximumNArgs(1),
|
Args: cobra.MaximumNArgs(1),
|
||||||
RunE: build,
|
RunE: build,
|
||||||
ValidArgsFunction: completion.AutocompleteDefault,
|
ValidArgsFunction: common.AutocompleteDefaultOneArg,
|
||||||
Example: `podman build .
|
Example: `podman build .
|
||||||
podman build --creds=username:password -t imageName -f Containerfile.simple .
|
podman build --creds=username:password -t imageName -f Containerfile.simple .
|
||||||
podman build --layers --force-rm --tag imageName .`,
|
podman build --layers --force-rm --tag imageName .`,
|
||||||
|
@ -25,18 +25,19 @@ var (
|
|||||||
Short: "Import a tarball to create a filesystem image",
|
Short: "Import a tarball to create a filesystem image",
|
||||||
Long: importDescription,
|
Long: importDescription,
|
||||||
RunE: importCon,
|
RunE: importCon,
|
||||||
ValidArgsFunction: completion.AutocompleteDefault,
|
Args: cobra.RangeArgs(1, 2),
|
||||||
|
ValidArgsFunction: common.AutocompleteDefaultOneArg,
|
||||||
Example: `podman import http://example.com/ctr.tar url-image
|
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 -q import --message "importing the ctr.tar tarball" - image-imported
|
||||||
cat ctr.tar | podman import -`,
|
cat ctr.tar | podman import -`,
|
||||||
}
|
}
|
||||||
|
|
||||||
imageImportCommand = &cobra.Command{
|
imageImportCommand = &cobra.Command{
|
||||||
Args: cobra.MinimumNArgs(1),
|
|
||||||
Use: importCommand.Use,
|
Use: importCommand.Use,
|
||||||
Short: importCommand.Short,
|
Short: importCommand.Short,
|
||||||
Long: importCommand.Long,
|
Long: importCommand.Long,
|
||||||
RunE: importCommand.RunE,
|
RunE: importCommand.RunE,
|
||||||
|
Args: importCommand.Args,
|
||||||
ValidArgsFunction: importCommand.ValidArgsFunction,
|
ValidArgsFunction: importCommand.ValidArgsFunction,
|
||||||
Example: `podman image import http://example.com/ctr.tar url-image
|
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
|
cat ctr.tar | podman -q image import --message "importing the ctr.tar tarball" - image-imported
|
||||||
|
@ -29,7 +29,7 @@ var (
|
|||||||
|
|
||||||
// Command: podman push
|
// Command: podman push
|
||||||
pushCmd = &cobra.Command{
|
pushCmd = &cobra.Command{
|
||||||
Use: "push [options] SOURCE [DESTINATION]",
|
Use: "push [options] IMAGE [DESTINATION]",
|
||||||
Short: "Push an image to a specified destination",
|
Short: "Push an image to a specified destination",
|
||||||
Long: pushDescription,
|
Long: pushDescription,
|
||||||
RunE: imagePush,
|
RunE: imagePush,
|
||||||
|
@ -43,7 +43,7 @@ var (
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
ValidArgsFunction: completion.AutocompleteNone,
|
ValidArgsFunction: common.AutocompleteImages,
|
||||||
Example: `podman save --quiet -o myimage.tar imageID
|
Example: `podman save --quiet -o myimage.tar imageID
|
||||||
podman save --format docker-dir -o ubuntu-dir ubuntu
|
podman save --format docker-dir -o ubuntu-dir ubuntu
|
||||||
podman save > alpine-all.tar alpine:latest`,
|
podman save > alpine-all.tar alpine:latest`,
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
untagCommand = &cobra.Command{
|
untagCommand = &cobra.Command{
|
||||||
Use: "untag IMAGE [NAME...]",
|
Use: "untag IMAGE [IMAGE...]",
|
||||||
Short: "Remove a name from a local image",
|
Short: "Remove a name from a local image",
|
||||||
Long: "Removes one or more names from a locally-stored image.",
|
Long: "Removes one or more names from a locally-stored image.",
|
||||||
RunE: untag,
|
RunE: untag,
|
||||||
|
@ -20,12 +20,12 @@ var (
|
|||||||
|
|
||||||
// Command: podman _inspect_ Object_ID
|
// Command: podman _inspect_ Object_ID
|
||||||
inspectCmd = &cobra.Command{
|
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",
|
Short: "Display the configuration of object denoted by ID",
|
||||||
RunE: inspectExec,
|
RunE: inspectExec,
|
||||||
Long: inspectDescription,
|
Long: inspectDescription,
|
||||||
TraverseChildren: true,
|
TraverseChildren: true,
|
||||||
ValidArgsFunction: common.AutocompleteContainersAndImages,
|
ValidArgsFunction: common.AutocompleteInspect,
|
||||||
Example: `podman inspect fedora
|
Example: `podman inspect fedora
|
||||||
podman inspect --type image fedora
|
podman inspect --type image fedora
|
||||||
podman inspect CtrID ImgID
|
podman inspect CtrID ImgID
|
||||||
|
@ -24,7 +24,7 @@ type manifestPushOptsWrapper struct {
|
|||||||
var (
|
var (
|
||||||
manifestPushOpts = manifestPushOptsWrapper{}
|
manifestPushOpts = manifestPushOptsWrapper{}
|
||||||
pushCmd = &cobra.Command{
|
pushCmd = &cobra.Command{
|
||||||
Use: "push [options] SOURCE DESTINATION",
|
Use: "push [options] LIST DESTINATION",
|
||||||
Short: "Push a manifest list or image index to a registry",
|
Short: "Push a manifest list or image index to a registry",
|
||||||
Long: "Pushes manifest lists and image indexes to registries.",
|
Long: "Pushes manifest lists and image indexes to registries.",
|
||||||
RunE: push,
|
RunE: push,
|
||||||
|
@ -17,7 +17,7 @@ import (
|
|||||||
var (
|
var (
|
||||||
networkCreateDescription = `create CNI networks for containers and pods`
|
networkCreateDescription = `create CNI networks for containers and pods`
|
||||||
networkCreateCommand = &cobra.Command{
|
networkCreateCommand = &cobra.Command{
|
||||||
Use: "create [options] [NETWORK]",
|
Use: "create [options] [NAME]",
|
||||||
Short: "network create",
|
Short: "network create",
|
||||||
Long: networkCreateDescription,
|
Long: networkCreateDescription,
|
||||||
RunE: networkCreate,
|
RunE: networkCreate,
|
||||||
|
@ -39,7 +39,7 @@ var (
|
|||||||
Long: kubeDescription,
|
Long: kubeDescription,
|
||||||
RunE: kube,
|
RunE: kube,
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
ValidArgsFunction: completion.AutocompleteDefault,
|
ValidArgsFunction: common.AutocompleteDefaultOneArg,
|
||||||
Example: `podman play kube nginx.yml
|
Example: `podman play kube nginx.yml
|
||||||
podman play kube --creds user:password --seccomp-profile-root /custom/path apache.yml`,
|
podman play kube --creds user:password --seccomp-profile-root /custom/path apache.yml`,
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"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/registry"
|
||||||
"github.com/containers/podman/v2/cmd/podman/utils"
|
"github.com/containers/podman/v2/cmd/podman/utils"
|
||||||
"github.com/containers/podman/v2/cmd/podman/validate"
|
"github.com/containers/podman/v2/cmd/podman/validate"
|
||||||
@ -28,7 +28,7 @@ var (
|
|||||||
Short: "Remove all stopped pods and their containers",
|
Short: "Remove all stopped pods and their containers",
|
||||||
Long: pruneDescription,
|
Long: pruneDescription,
|
||||||
RunE: prune,
|
RunE: prune,
|
||||||
ValidArgsFunction: common.AutocompletePods,
|
ValidArgsFunction: completion.AutocompleteNone,
|
||||||
Example: `podman pod prune`,
|
Example: `podman pod prune`,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containers/common/pkg/completion"
|
"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/cmd/podman/registry"
|
||||||
"github.com/containers/podman/v2/pkg/domain/entities"
|
"github.com/containers/podman/v2/pkg/domain/entities"
|
||||||
"github.com/containers/podman/v2/pkg/rootless"
|
"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",
|
Short: "Run API service",
|
||||||
Long: srvDescription,
|
Long: srvDescription,
|
||||||
RunE: service,
|
RunE: service,
|
||||||
ValidArgsFunction: completion.AutocompleteDefault,
|
ValidArgsFunction: common.AutocompleteDefaultOneArg,
|
||||||
Example: `podman system service --time=0 unix:///tmp/podman.sock`,
|
Example: `podman system service --time=0 unix:///tmp/podman.sock`,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,22 +12,11 @@
|
|||||||
#
|
#
|
||||||
load helpers
|
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() {
|
function check_help() {
|
||||||
local count=0
|
local count=0
|
||||||
local -A found
|
local -A found
|
||||||
|
|
||||||
for cmd in $(podman_commands "$@"); do
|
for cmd in $(_podman_commands "$@"); do
|
||||||
# Human-readable podman command string, with multiple spaces collapsed
|
# Human-readable podman command string, with multiple spaces collapsed
|
||||||
command_string="podman $* $cmd"
|
command_string="podman $* $cmd"
|
||||||
command_string=${command_string// / } # 'podman x' -> 'podman x'
|
command_string=${command_string// / } # 'podman x' -> 'podman x'
|
||||||
|
272
test/system/600-completion.bats
Normal file
272
test/system/600-completion.bats
Normal file
@ -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"
|
||||||
|
|
||||||
|
}
|
@ -521,5 +521,15 @@ function remove_same_dev_warning() {
|
|||||||
output=$(printf '%s\n' "${lines[@]}")
|
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
|
# END miscellaneous tools
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
Reference in New Issue
Block a user