Shell Completion for podman build flags
The PR containers/podman#6442 enables a new way to create shell completions scripts. The shell completion is handled by cobra and since the build flags are defined here the completion functions for this should be defined here as well. For Reference see: https://github.com/spf13/cobra/blob/master/shell_completions.md I added a unit test to ensure that the flags have a completion function set. These completions could also be used by buildah if someone wants to implements this cobra completion logic for buildah. Signed-off-by: Paul Holzinger <paul.holzinger@web.de>
This commit is contained in:
parent
6348eb3a0e
commit
71ba2e4ef0
|
@ -11,9 +11,11 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/containers/buildah"
|
||||
"github.com/containers/buildah/pkg/completion"
|
||||
"github.com/containers/buildah/pkg/parse"
|
||||
"github.com/containers/buildah/util"
|
||||
"github.com/containers/common/pkg/auth"
|
||||
commonComp "github.com/containers/common/pkg/completion"
|
||||
"github.com/containers/common/pkg/config"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
|
@ -125,6 +127,17 @@ func GetUserNSFlags(flags *UserNSResults) pflag.FlagSet {
|
|||
return usernsFlags
|
||||
}
|
||||
|
||||
// GetUserNSFlagsCompletions returns the FlagCompletions for the userns flags
|
||||
func GetUserNSFlagsCompletions() commonComp.FlagCompletions {
|
||||
flagCompletion := commonComp.FlagCompletions{}
|
||||
flagCompletion["userns"] = completion.AutocompleteNamespaceFlag
|
||||
flagCompletion["userns-uid-map"] = commonComp.AutocompleteNone
|
||||
flagCompletion["userns-gid-map"] = commonComp.AutocompleteNone
|
||||
flagCompletion["userns-uid-map-user"] = commonComp.AutocompleteSubuidName
|
||||
flagCompletion["userns-gid-map-group"] = commonComp.AutocompleteSubgidName
|
||||
return flagCompletion
|
||||
}
|
||||
|
||||
// GetNameSpaceFlags returns the common flags for a namespace menu
|
||||
func GetNameSpaceFlags(flags *NameSpaceResults) pflag.FlagSet {
|
||||
fs := pflag.FlagSet{}
|
||||
|
@ -137,6 +150,18 @@ func GetNameSpaceFlags(flags *NameSpaceResults) pflag.FlagSet {
|
|||
return fs
|
||||
}
|
||||
|
||||
// GetNameSpaceFlagsCompletions returns the FlagCompletions for the namespace flags
|
||||
func GetNameSpaceFlagsCompletions() commonComp.FlagCompletions {
|
||||
flagCompletion := commonComp.FlagCompletions{}
|
||||
flagCompletion[string(specs.IPCNamespace)] = completion.AutocompleteNamespaceFlag
|
||||
flagCompletion[string(specs.NetworkNamespace)] = completion.AutocompleteNamespaceFlag
|
||||
flagCompletion["cni-config-dir"] = commonComp.AutocompleteDefault
|
||||
flagCompletion["cni-plugin-path"] = commonComp.AutocompleteDefault
|
||||
flagCompletion[string(specs.PIDNamespace)] = completion.AutocompleteNamespaceFlag
|
||||
flagCompletion[string(specs.UTSNamespace)] = completion.AutocompleteNamespaceFlag
|
||||
return flagCompletion
|
||||
}
|
||||
|
||||
// GetLayerFlags returns the common flags for layers
|
||||
func GetLayerFlags(flags *LayerResults) pflag.FlagSet {
|
||||
fs := pflag.FlagSet{}
|
||||
|
@ -145,6 +170,8 @@ func GetLayerFlags(flags *LayerResults) pflag.FlagSet {
|
|||
return fs
|
||||
}
|
||||
|
||||
// Note: GetLayerFlagsCompletion is not needed since GetLayerFlags only contains bool flags
|
||||
|
||||
// GetBudFlags returns common bud flags
|
||||
func GetBudFlags(flags *BudResults) pflag.FlagSet {
|
||||
fs := pflag.FlagSet{}
|
||||
|
@ -189,6 +216,35 @@ func GetBudFlags(flags *BudResults) pflag.FlagSet {
|
|||
return fs
|
||||
}
|
||||
|
||||
// GetBudFlagsCompletions returns the FlagCompletions for the common bud flags
|
||||
func GetBudFlagsCompletions() commonComp.FlagCompletions {
|
||||
flagCompletion := commonComp.FlagCompletions{}
|
||||
flagCompletion["arch"] = commonComp.AutocompleteNone
|
||||
flagCompletion["annotation"] = commonComp.AutocompleteNone
|
||||
flagCompletion["authfile"] = commonComp.AutocompleteDefault
|
||||
flagCompletion["build-arg"] = commonComp.AutocompleteNone
|
||||
flagCompletion["cache-from"] = commonComp.AutocompleteNone
|
||||
flagCompletion["cert-dir"] = commonComp.AutocompleteDefault
|
||||
flagCompletion["creds"] = commonComp.AutocompleteNone
|
||||
flagCompletion["file"] = commonComp.AutocompleteDefault
|
||||
flagCompletion["format"] = commonComp.AutocompleteNone
|
||||
flagCompletion["iidfile"] = commonComp.AutocompleteDefault
|
||||
flagCompletion["label"] = commonComp.AutocompleteNone
|
||||
flagCompletion["logfile"] = commonComp.AutocompleteDefault
|
||||
flagCompletion["loglevel"] = commonComp.AutocompleteDefault
|
||||
flagCompletion["timestamp"] = commonComp.AutocompleteNone
|
||||
flagCompletion["os"] = commonComp.AutocompleteNone
|
||||
flagCompletion["platform"] = commonComp.AutocompleteNone
|
||||
flagCompletion["runtime-flag"] = commonComp.AutocompleteNone
|
||||
flagCompletion["sign-by"] = commonComp.AutocompleteNone
|
||||
flagCompletion["signature-policy"] = commonComp.AutocompleteNone
|
||||
flagCompletion["tag"] = commonComp.AutocompleteNone
|
||||
flagCompletion["target"] = commonComp.AutocompleteNone
|
||||
flagCompletion["jobs"] = commonComp.AutocompleteNone
|
||||
return flagCompletion
|
||||
}
|
||||
|
||||
// GetFromAndBudFlags returns from and bud flags
|
||||
func GetFromAndBudFlags(flags *FromAndBudResults, usernsResults *UserNSResults, namespaceResults *NameSpaceResults) (pflag.FlagSet, error) {
|
||||
fs := pflag.FlagSet{}
|
||||
defaultContainerConfig, err := config.Default()
|
||||
|
@ -239,6 +295,44 @@ func GetFromAndBudFlags(flags *FromAndBudResults, usernsResults *UserNSResults,
|
|||
return fs, nil
|
||||
}
|
||||
|
||||
// GetFromAndBudFlagsCompletions returns the FlagCompletions for the from and bud flags
|
||||
func GetFromAndBudFlagsCompletions() commonComp.FlagCompletions {
|
||||
flagCompletion := commonComp.FlagCompletions{}
|
||||
flagCompletion["add-host"] = commonComp.AutocompleteNone
|
||||
flagCompletion["blob-cache"] = commonComp.AutocompleteNone
|
||||
flagCompletion["cap-add"] = commonComp.AutocompleteCapabilities
|
||||
flagCompletion["cap-drop"] = commonComp.AutocompleteCapabilities
|
||||
flagCompletion["cgroup-parent"] = commonComp.AutocompleteDefault // FIXME: This would be a path right?!
|
||||
flagCompletion["cpu-period"] = commonComp.AutocompleteNone
|
||||
flagCompletion["cpu-quota"] = commonComp.AutocompleteNone
|
||||
flagCompletion["cpu-shares"] = commonComp.AutocompleteNone
|
||||
flagCompletion["cpuset-cpus"] = commonComp.AutocompleteNone
|
||||
flagCompletion["cpuset-mems"] = commonComp.AutocompleteNone
|
||||
flagCompletion["device"] = commonComp.AutocompleteDefault
|
||||
flagCompletion["dns-search"] = commonComp.AutocompleteNone
|
||||
flagCompletion["dns"] = commonComp.AutocompleteNone
|
||||
flagCompletion["dns-option"] = commonComp.AutocompleteNone
|
||||
flagCompletion["isolation"] = commonComp.AutocompleteNone
|
||||
flagCompletion["memory"] = commonComp.AutocompleteNone
|
||||
flagCompletion["memory-swap"] = commonComp.AutocompleteNone
|
||||
flagCompletion["security-opt"] = commonComp.AutocompleteNone
|
||||
flagCompletion["shm-size"] = commonComp.AutocompleteNone
|
||||
flagCompletion["ulimit"] = commonComp.AutocompleteNone
|
||||
flagCompletion["volume"] = commonComp.AutocompleteDefault
|
||||
|
||||
// Add in the usernamespace and namespace flag completions
|
||||
userNsComp := GetUserNSFlagsCompletions()
|
||||
for name, comp := range userNsComp {
|
||||
flagCompletion[name] = comp
|
||||
}
|
||||
namespaceComp := GetNameSpaceFlagsCompletions()
|
||||
for name, comp := range namespaceComp {
|
||||
flagCompletion[name] = comp
|
||||
}
|
||||
|
||||
return flagCompletion
|
||||
}
|
||||
|
||||
// UseLayers returns true if BUILDAH_LAYERS is set to "1" or "true"
|
||||
// otherwise it returns false
|
||||
func UseLayers() bool {
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/containers/common/pkg/completion"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
func testFlagCompletion(t *testing.T, flags pflag.FlagSet, flagCompletions completion.FlagCompletions) {
|
||||
// lookup if for each flag a flag completion function exists
|
||||
flags.VisitAll(func(f *pflag.Flag) {
|
||||
// skip hidden, deprecated and boolean flags
|
||||
if f.Hidden || len(f.Deprecated) > 0 || f.Value.Type() == "bool" {
|
||||
return
|
||||
}
|
||||
if _, ok := flagCompletions[f.Name]; !ok {
|
||||
t.Errorf("Flag %q has no shell completion function set.", f.Name)
|
||||
}
|
||||
})
|
||||
|
||||
// make sure no unnecessary flag completion functions are defined
|
||||
for name := range flagCompletions {
|
||||
if flag := flags.Lookup(name); flag == nil {
|
||||
t.Errorf("Flag %q does not exists but has a shell completion function set.", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserNsFlagsCompletion(t *testing.T) {
|
||||
flags := GetUserNSFlags(&UserNSResults{})
|
||||
flagCompletions := GetUserNSFlagsCompletions()
|
||||
testFlagCompletion(t, flags, flagCompletions)
|
||||
}
|
||||
|
||||
func TestNameSpaceFlagsCompletion(t *testing.T) {
|
||||
flags := GetNameSpaceFlags(&NameSpaceResults{})
|
||||
flagCompletions := GetNameSpaceFlagsCompletions()
|
||||
testFlagCompletion(t, flags, flagCompletions)
|
||||
}
|
||||
|
||||
func TestBudFlagsCompletion(t *testing.T) {
|
||||
flags := GetBudFlags(&BudResults{})
|
||||
flagCompletions := GetBudFlagsCompletions()
|
||||
testFlagCompletion(t, flags, flagCompletions)
|
||||
}
|
||||
|
||||
func TestFromAndBudFlagsCompletions(t *testing.T) {
|
||||
flags, err := GetFromAndBudFlags(&FromAndBudResults{}, &UserNSResults{}, &NameSpaceResults{})
|
||||
if err != nil {
|
||||
t.Error("Could load the from and bud flags.")
|
||||
}
|
||||
flagCompletions := GetFromAndBudFlagsCompletions()
|
||||
testFlagCompletion(t, flags, flagCompletions)
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package completion
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
/* Autocomplete Functions for cobra ValidArgsFunction */
|
||||
|
||||
// AutocompleteNamespaceFlag - Autocomplete the userns flag.
|
||||
// -> host, private, container, ns:[path], [path]
|
||||
func AutocompleteNamespaceFlag(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
var completions []string
|
||||
// If we don't filter on "toComplete", zsh and fish will not do file completion
|
||||
// even if the prefix typed by the user does not match the returned completions
|
||||
for _, comp := range []string{"host", "private", "container", "ns:"} {
|
||||
if strings.HasPrefix(comp, toComplete) {
|
||||
completions = append(completions, comp)
|
||||
}
|
||||
}
|
||||
return completions, cobra.ShellCompDirectiveDefault
|
||||
}
|
Loading…
Reference in New Issue