Skip to content

Commit

Permalink
Merge pull request #8436 from Luap99/remote-completion
Browse files Browse the repository at this point in the history
Enable remote shell completion without a running endpoint
  • Loading branch information
openshift-merge-robot committed Nov 23, 2020
2 parents 5292d5a + bf11bb7 commit 79ab19a
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 68 deletions.
132 changes: 93 additions & 39 deletions cmd/podman/common/completion.go
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/containers/podman/v2/pkg/registries"
"github.com/containers/podman/v2/pkg/rootless"
systemdGen "github.com/containers/podman/v2/pkg/systemd/generate"
"github.com/spf13/cobra"
)
Expand All @@ -36,7 +37,35 @@ const (

type keyValueCompletion map[string]func(s string) ([]string, cobra.ShellCompDirective)

func getContainers(toComplete string, cType completeType, statuses ...string) ([]string, cobra.ShellCompDirective) {
func setupContainerEngine(cmd *cobra.Command) (entities.ContainerEngine, error) {
containerEngine, err := registry.NewContainerEngine(cmd, []string{})
if err != nil {
cobra.CompErrorln(err.Error())
return nil, err
}
if !registry.IsRemote() && rootless.IsRootless() {
err := containerEngine.SetupRootless(registry.Context(), cmd)
if err != nil {
return nil, err
}
}
return containerEngine, nil
}

func setupImageEngine(cmd *cobra.Command) (entities.ImageEngine, error) {
imageEngine, err := registry.NewImageEngine(cmd, []string{})
if err != nil {
return nil, err
}
// we also need to set up the container engine since this
// is required to setup the rootless namespace
if _, err = setupContainerEngine(cmd); err != nil {
return nil, err
}
return imageEngine, nil
}

func getContainers(cmd *cobra.Command, toComplete string, cType completeType, statuses ...string) ([]string, cobra.ShellCompDirective) {
suggestions := []string{}
listOpts := entities.ContainerListOptions{
Filters: make(map[string][]string),
Expand All @@ -47,7 +76,12 @@ func getContainers(toComplete string, cType completeType, statuses ...string) ([
listOpts.Filters["status"] = statuses
}

containers, err := registry.ContainerEngine().ContainerList(registry.GetContext(), listOpts)
engine, err := setupContainerEngine(cmd)
if err != nil {
cobra.CompErrorln(err.Error())
return nil, cobra.ShellCompDirectiveNoFileComp
}
containers, err := engine.ContainerList(registry.GetContext(), listOpts)
if err != nil {
cobra.CompErrorln(err.Error())
return nil, cobra.ShellCompDirectiveError
Expand All @@ -68,7 +102,7 @@ func getContainers(toComplete string, cType completeType, statuses ...string) ([
return suggestions, cobra.ShellCompDirectiveNoFileComp
}

func getPods(toComplete string, cType completeType, statuses ...string) ([]string, cobra.ShellCompDirective) {
func getPods(cmd *cobra.Command, toComplete string, cType completeType, statuses ...string) ([]string, cobra.ShellCompDirective) {
suggestions := []string{}
listOpts := entities.PodPSOptions{
Filters: make(map[string][]string),
Expand All @@ -77,7 +111,12 @@ func getPods(toComplete string, cType completeType, statuses ...string) ([]strin
listOpts.Filters["status"] = statuses
}

pods, err := registry.ContainerEngine().PodPs(registry.GetContext(), listOpts)
engine, err := setupContainerEngine(cmd)
if err != nil {
cobra.CompErrorln(err.Error())
return nil, cobra.ShellCompDirectiveNoFileComp
}
pods, err := engine.PodPs(registry.GetContext(), listOpts)
if err != nil {
cobra.CompErrorln(err.Error())
return nil, cobra.ShellCompDirectiveError
Expand All @@ -98,11 +137,16 @@ func getPods(toComplete string, cType completeType, statuses ...string) ([]strin
return suggestions, cobra.ShellCompDirectiveNoFileComp
}

func getVolumes(toComplete string) ([]string, cobra.ShellCompDirective) {
func getVolumes(cmd *cobra.Command, toComplete string) ([]string, cobra.ShellCompDirective) {
suggestions := []string{}
lsOpts := entities.VolumeListOptions{}

volumes, err := registry.ContainerEngine().VolumeList(registry.GetContext(), lsOpts)
engine, err := setupContainerEngine(cmd)
if err != nil {
cobra.CompErrorln(err.Error())
return nil, cobra.ShellCompDirectiveNoFileComp
}
volumes, err := engine.VolumeList(registry.GetContext(), lsOpts)
if err != nil {
cobra.CompErrorln(err.Error())
return nil, cobra.ShellCompDirectiveError
Expand All @@ -116,11 +160,16 @@ func getVolumes(toComplete string) ([]string, cobra.ShellCompDirective) {
return suggestions, cobra.ShellCompDirectiveNoFileComp
}

func getImages(toComplete string) ([]string, cobra.ShellCompDirective) {
func getImages(cmd *cobra.Command, toComplete string) ([]string, cobra.ShellCompDirective) {
suggestions := []string{}
listOptions := entities.ImageListOptions{}

images, err := registry.ImageEngine().List(registry.GetContext(), listOptions)
engine, err := setupImageEngine(cmd)
if err != nil {
cobra.CompErrorln(err.Error())
return nil, cobra.ShellCompDirectiveNoFileComp
}
images, err := engine.List(registry.GetContext(), listOptions)
if err != nil {
cobra.CompErrorln(err.Error())
return nil, cobra.ShellCompDirectiveError
Expand Down Expand Up @@ -171,11 +220,16 @@ func getRegistries() ([]string, cobra.ShellCompDirective) {
return regs, cobra.ShellCompDirectiveNoFileComp
}

func getNetworks(toComplete string) ([]string, cobra.ShellCompDirective) {
func getNetworks(cmd *cobra.Command, toComplete string) ([]string, cobra.ShellCompDirective) {
suggestions := []string{}
networkListOptions := entities.NetworkListOptions{}

networks, err := registry.ContainerEngine().NetworkList(registry.Context(), networkListOptions)
engine, err := setupContainerEngine(cmd)
if err != nil {
cobra.CompErrorln(err.Error())
return nil, cobra.ShellCompDirectiveNoFileComp
}
networks, err := engine.NetworkList(registry.Context(), networkListOptions)
if err != nil {
cobra.CompErrorln(err.Error())
return nil, cobra.ShellCompDirectiveError
Expand Down Expand Up @@ -266,55 +320,55 @@ func AutocompleteContainers(cmd *cobra.Command, args []string, toComplete string
if !validCurrentCmdLine(cmd, args, toComplete) {
return nil, cobra.ShellCompDirectiveNoFileComp
}
return getContainers(toComplete, completeDefault)
return getContainers(cmd, toComplete, completeDefault)
}

// AutocompleteContainersCreated - Autocomplete only created container names.
func AutocompleteContainersCreated(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if !validCurrentCmdLine(cmd, args, toComplete) {
return nil, cobra.ShellCompDirectiveNoFileComp
}
return getContainers(toComplete, completeDefault, "created")
return getContainers(cmd, toComplete, completeDefault, "created")
}

// AutocompleteContainersExited - Autocomplete only exited container names.
func AutocompleteContainersExited(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if !validCurrentCmdLine(cmd, args, toComplete) {
return nil, cobra.ShellCompDirectiveNoFileComp
}
return getContainers(toComplete, completeDefault, "exited")
return getContainers(cmd, toComplete, completeDefault, "exited")
}

// AutocompleteContainersPaused - Autocomplete only paused container names.
func AutocompleteContainersPaused(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if !validCurrentCmdLine(cmd, args, toComplete) {
return nil, cobra.ShellCompDirectiveNoFileComp
}
return getContainers(toComplete, completeDefault, "paused")
return getContainers(cmd, toComplete, completeDefault, "paused")
}

// AutocompleteContainersRunning - Autocomplete only running container names.
func AutocompleteContainersRunning(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if !validCurrentCmdLine(cmd, args, toComplete) {
return nil, cobra.ShellCompDirectiveNoFileComp
}
return getContainers(toComplete, completeDefault, "running")
return getContainers(cmd, toComplete, completeDefault, "running")
}

// AutocompleteContainersStartable - Autocomplete only created and exited container names.
func AutocompleteContainersStartable(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if !validCurrentCmdLine(cmd, args, toComplete) {
return nil, cobra.ShellCompDirectiveNoFileComp
}
return getContainers(toComplete, completeDefault, "created", "exited")
return getContainers(cmd, toComplete, completeDefault, "created", "exited")
}

// AutocompletePods - Autocomplete all pod names.
func AutocompletePods(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if !validCurrentCmdLine(cmd, args, toComplete) {
return nil, cobra.ShellCompDirectiveNoFileComp
}
return getPods(toComplete, completeDefault)
return getPods(cmd, toComplete, completeDefault)
}

// AutocompletePodsRunning - Autocomplete only running pod names.
Expand All @@ -323,16 +377,16 @@ func AutocompletePodsRunning(cmd *cobra.Command, args []string, toComplete strin
if !validCurrentCmdLine(cmd, args, toComplete) {
return nil, cobra.ShellCompDirectiveNoFileComp
}
return getPods(toComplete, completeDefault, "running", "degraded")
return getPods(cmd, toComplete, completeDefault, "running", "degraded")
}

// AutocompleteContainersAndPods - Autocomplete container names and pod names.
func AutocompleteContainersAndPods(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if !validCurrentCmdLine(cmd, args, toComplete) {
return nil, cobra.ShellCompDirectiveNoFileComp
}
containers, _ := getContainers(toComplete, completeDefault)
pods, _ := getPods(toComplete, completeDefault)
containers, _ := getContainers(cmd, toComplete, completeDefault)
pods, _ := getPods(cmd, toComplete, completeDefault)
return append(containers, pods...), cobra.ShellCompDirectiveNoFileComp
}

Expand All @@ -341,8 +395,8 @@ func AutocompleteContainersAndImages(cmd *cobra.Command, args []string, toComple
if !validCurrentCmdLine(cmd, args, toComplete) {
return nil, cobra.ShellCompDirectiveNoFileComp
}
containers, _ := getContainers(toComplete, completeDefault)
images, _ := getImages(toComplete)
containers, _ := getContainers(cmd, toComplete, completeDefault)
images, _ := getImages(cmd, toComplete)
return append(containers, images...), cobra.ShellCompDirectiveNoFileComp
}

Expand All @@ -351,15 +405,15 @@ func AutocompleteVolumes(cmd *cobra.Command, args []string, toComplete string) (
if !validCurrentCmdLine(cmd, args, toComplete) {
return nil, cobra.ShellCompDirectiveNoFileComp
}
return getVolumes(toComplete)
return getVolumes(cmd, toComplete)
}

// AutocompleteImages - Autocomplete images.
func AutocompleteImages(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
if !validCurrentCmdLine(cmd, args, toComplete) {
return nil, cobra.ShellCompDirectiveNoFileComp
}
return getImages(toComplete)
return getImages(cmd, toComplete)
}

// AutocompleteCreateRun - Autocomplete only the fist argument as image and then do file completion.
Expand All @@ -368,7 +422,7 @@ func AutocompleteCreateRun(cmd *cobra.Command, args []string, toComplete string)
return nil, cobra.ShellCompDirectiveNoFileComp
}
if len(args) < 1 {
return getImages(toComplete)
return getImages(cmd, toComplete)
}
// TODO: add path completion for files in the image
return nil, cobra.ShellCompDirectiveDefault
Expand All @@ -387,7 +441,7 @@ func AutocompleteNetworks(cmd *cobra.Command, args []string, toComplete string)
if !validCurrentCmdLine(cmd, args, toComplete) {
return nil, cobra.ShellCompDirectiveNoFileComp
}
return getNetworks(toComplete)
return getNetworks(cmd, toComplete)
}

// AutocompleteCpCommand - Autocomplete podman cp command args.
Expand All @@ -396,7 +450,7 @@ func AutocompleteCpCommand(cmd *cobra.Command, args []string, toComplete string)
return nil, cobra.ShellCompDirectiveNoFileComp
}
if len(args) < 2 {
containers, _ := getContainers(toComplete, completeDefault)
containers, _ := getContainers(cmd, toComplete, completeDefault)
for _, container := range containers {
// TODO: Add path completion for inside the container if possible
if strings.HasPrefix(container, toComplete) {
Expand Down Expand Up @@ -464,7 +518,7 @@ func AutocompleteCreateAttach(cmd *cobra.Command, args []string, toComplete stri
// -> host,container:[name],ns:[path],private
func AutocompleteNamespace(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
kv := keyValueCompletion{
"container:": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(s, completeDefault) },
"container:": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(cmd, s, completeDefault) },
"ns:": func(s string) ([]string, cobra.ShellCompDirective) { return nil, cobra.ShellCompDirectiveDefault },
"host": nil,
"private": nil,
Expand Down Expand Up @@ -623,7 +677,7 @@ func AutocompleteMountFlag(cmd *cobra.Command, args []string, toComplete string)
// AutocompleteVolumeFlag - Autocomplete volume flag options.
// -> volumes and paths
func AutocompleteVolumeFlag(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
volumes, _ := getVolumes(toComplete)
volumes, _ := getVolumes(cmd, toComplete)
directive := cobra.ShellCompDirectiveNoSpace | cobra.ShellCompDirectiveDefault
if strings.Contains(toComplete, ":") {
// add space after second path
Expand Down Expand Up @@ -753,15 +807,15 @@ var containerStatuses = []string{"created", "running", "paused", "stopped", "exi
// AutocompletePsFilters - Autocomplete ps filter options.
func AutocompletePsFilters(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
kv := keyValueCompletion{
"id=": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(s, completeIDs) },
"name=": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(s, completeNames) },
"id=": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(cmd, s, completeIDs) },
"name=": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(cmd, s, completeNames) },
"status=": func(_ string) ([]string, cobra.ShellCompDirective) {
return containerStatuses, cobra.ShellCompDirectiveNoFileComp
},
"ancestor": func(s string) ([]string, cobra.ShellCompDirective) { return getImages(s) },
"before=": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(s, completeDefault) },
"since=": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(s, completeDefault) },
"volume=": func(s string) ([]string, cobra.ShellCompDirective) { return getVolumes(s) },
"ancestor": func(s string) ([]string, cobra.ShellCompDirective) { return getImages(cmd, s) },
"before=": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(cmd, s, completeDefault) },
"since=": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(cmd, s, completeDefault) },
"volume=": func(s string) ([]string, cobra.ShellCompDirective) { return getVolumes(cmd, s) },
"health=": func(_ string) ([]string, cobra.ShellCompDirective) {
return []string{define.HealthCheckHealthy,
define.HealthCheckUnhealthy}, cobra.ShellCompDirectiveNoFileComp
Expand All @@ -776,14 +830,14 @@ func AutocompletePsFilters(cmd *cobra.Command, args []string, toComplete string)
// AutocompletePodPsFilters - Autocomplete pod ps filter options.
func AutocompletePodPsFilters(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
kv := keyValueCompletion{
"id=": func(s string) ([]string, cobra.ShellCompDirective) { return getPods(s, completeIDs) },
"name=": func(s string) ([]string, cobra.ShellCompDirective) { return getPods(s, completeNames) },
"id=": func(s string) ([]string, cobra.ShellCompDirective) { return getPods(cmd, s, completeIDs) },
"name=": func(s string) ([]string, cobra.ShellCompDirective) { return getPods(cmd, s, completeNames) },
"status=": func(_ string) ([]string, cobra.ShellCompDirective) {
return []string{"stopped", "running",
"paused", "exited", "dead", "created", "degraded"}, cobra.ShellCompDirectiveNoFileComp
},
"ctr-ids=": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(s, completeIDs) },
"ctr-names=": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(s, completeNames) },
"ctr-ids=": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(cmd, s, completeIDs) },
"ctr-names=": func(s string) ([]string, cobra.ShellCompDirective) { return getContainers(cmd, s, completeNames) },
"ctr-number=": nil,
"ctr-status=": func(_ string) ([]string, cobra.ShellCompDirective) {
return containerStatuses, cobra.ShellCompDirectiveNoFileComp
Expand Down

0 comments on commit 79ab19a

Please sign in to comment.