Skip to content

Commit

Permalink
Merge pull request #11880 from johngmyers/root-completion
Browse files Browse the repository at this point in the history
Improve completion for kops root command
  • Loading branch information
k8s-ci-robot committed Jun 28, 2021
2 parents 0432737 + 26a5aa1 commit 9bd1887
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 9 deletions.
3 changes: 2 additions & 1 deletion cmd/kops/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/kops/cmd/kops/util"
api "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/commands/commandutils"
"k8s.io/kops/pkg/kopscodecs"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
Expand Down Expand Up @@ -116,7 +117,7 @@ func NewCmdGet(f *util.Factory, out io.Writer) *cobra.Command {
return cmd
}

func RunGet(ctx context.Context, f Factory, out io.Writer, options *GetOptions) error {
func RunGet(ctx context.Context, f commandutils.Factory, out io.Writer, options *GetOptions) error {

client, err := f.Clientset()
if err != nil {
Expand Down
3 changes: 2 additions & 1 deletion cmd/kops/get_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"k8s.io/kops/cmd/kops/util"
kopsapi "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/apis/kops/registry"
"k8s.io/kops/pkg/commands/commandutils"
"k8s.io/kops/pkg/kopscodecs"
"k8s.io/kops/util/pkg/tables"
"k8s.io/kubectl/pkg/util/i18n"
Expand Down Expand Up @@ -120,7 +121,7 @@ func NewCmdGetCluster(f *util.Factory, out io.Writer, getOptions *GetOptions) *c
return cmd
}

func RunGetClusters(ctx context.Context, f Factory, out io.Writer, options *GetClusterOptions) error {
func RunGetClusters(ctx context.Context, f commandutils.Factory, out io.Writer, options *GetClusterOptions) error {
client, err := f.Clientset()
if err != nil {
return err
Expand Down
14 changes: 8 additions & 6 deletions cmd/kops/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import (
kopsapi "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/client/simple"
"k8s.io/kops/pkg/commands"
"k8s.io/kops/pkg/commands/commandutils"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
)
Expand Down Expand Up @@ -65,10 +66,6 @@ var (
rootShort = i18n.T(`kOps is Kubernetes Operations.`)
)

type Factory interface {
Clientset() (simple.Clientset, error)
}

type RootCmd struct {
util.FactoryOptions

Expand All @@ -81,7 +78,7 @@ type RootCmd struct {
cobraCommand *cobra.Command
}

var _ Factory = &RootCmd{}
var _ commandutils.Factory = &RootCmd{}

var rootCommand = RootCmd{
cobraCommand: &cobra.Command{
Expand Down Expand Up @@ -129,13 +126,18 @@ func NewCmdRoot(f *util.Factory, out io.Writer) *cobra.Command {
cmd.PersistentFlags().StringVar(&rootCommand.configFile, "config", "", "yaml config file (default is $HOME/.kops.yaml)")
viper.BindPFlag("config", cmd.PersistentFlags().Lookup("config"))
viper.SetDefault("config", "$HOME/.kops.yaml")
cmd.RegisterFlagCompletionFunc("config", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return []string{"yaml", "json"}, cobra.ShellCompDirectiveFilterFileExt
})

cmd.PersistentFlags().StringVar(&rootCommand.RegistryPath, "state", "", "Location of state storage (kops 'config' file). Overrides KOPS_STATE_STORE environment variable")
viper.BindPFlag("KOPS_STATE_STORE", cmd.PersistentFlags().Lookup("state"))
viper.BindEnv("KOPS_STATE_STORE")
// TODO implement completion against VFS

defaultClusterName := os.Getenv("KOPS_CLUSTER_NAME")
cmd.PersistentFlags().StringVarP(&rootCommand.clusterName, "name", "", defaultClusterName, "Name of cluster. Overrides KOPS_CLUSTER_NAME environment variable")
cmd.RegisterFlagCompletionFunc("name", commandutils.CompleteClusterName(&rootCommand))

// create subcommands
cmd.AddCommand(NewCmdCompletion(f, out))
Expand Down Expand Up @@ -290,7 +292,7 @@ func (c *RootCmd) Cluster(ctx context.Context) (*kopsapi.Cluster, error) {
return GetCluster(ctx, c.factory, clusterName)
}

func GetCluster(ctx context.Context, factory Factory, clusterName string) (*kopsapi.Cluster, error) {
func GetCluster(ctx context.Context, factory commandutils.Factory, clusterName string) (*kopsapi.Cluster, error) {
if clusterName == "" {
return nil, field.Required(field.NewPath("clusterName"), "Cluster name is required")
}
Expand Down
14 changes: 13 additions & 1 deletion pkg/commands/commandutils/BUILD.bazel

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 48 additions & 0 deletions pkg/commands/commandutils/cluster.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
Copyright 2021 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package commandutils

import (
"context"

"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// CompleteClusterName returns a Cobra completion function for cluster names.
func CompleteClusterName(f Factory) func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
ConfigureKlogForCompletion()

client, err := f.Clientset()
if err != nil {
return CompletionError("getting clientset", err)
}

list, err := client.ListClusters(context.TODO(), metav1.ListOptions{})
if err != nil {
return CompletionError("listing clusters", err)
}

var clusterNames []string
for _, cluster := range list.Items {
clusterNames = append(clusterNames, cluster.Name)
}

return clusterNames, cobra.ShellCompDirectiveNoFileComp
}
}
29 changes: 29 additions & 0 deletions pkg/commands/commandutils/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
Copyright 2021 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package commandutils

import (
"fmt"

"github.com/spf13/cobra"
)

// CompletionError a helper function to logs and return an error from a Cobra completion function.
func CompletionError(prefix string, err error) ([]string, cobra.ShellCompDirective) {
cobra.CompError(fmt.Sprintf("%s: %v", prefix, err))
return nil, cobra.ShellCompDirectiveError | cobra.ShellCompDirectiveNoFileComp
}
23 changes: 23 additions & 0 deletions pkg/commands/commandutils/factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
Copyright 2021 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package commandutils

import "k8s.io/kops/pkg/client/simple"

type Factory interface {
Clientset() (simple.Clientset, error)
}
34 changes: 34 additions & 0 deletions pkg/commands/commandutils/klog.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
Copyright 2021 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package commandutils

import (
"github.com/spf13/cobra"
"k8s.io/klog/v2"
)

// ConfigureKlogForCompletion configures Klog to not interfere with Cobra completion functions.
func ConfigureKlogForCompletion() {
klog.SetOutput(&toCompDebug{})
}

type toCompDebug struct{}

func (t toCompDebug) Write(p []byte) (n int, err error) {
cobra.CompDebug(string(p), false)
return len(p), nil
}

0 comments on commit 9bd1887

Please sign in to comment.