mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Merge pull request #89840 from eddiezane/ez/kubectl-396
Add get-users and delete-user to kubectl config
This commit is contained in:
		@@ -245,6 +245,7 @@ package_group(
 | 
			
		||||
        "//staging/src/k8s.io/kubectl/pkg/cmd/attach",
 | 
			
		||||
        "//staging/src/k8s.io/kubectl/pkg/cmd/certificates",
 | 
			
		||||
        "//staging/src/k8s.io/kubectl/pkg/cmd/clusterinfo",
 | 
			
		||||
        "//staging/src/k8s.io/kubectl/pkg/cmd/config",
 | 
			
		||||
        "//staging/src/k8s.io/kubectl/pkg/cmd/cp",
 | 
			
		||||
        "//staging/src/k8s.io/kubectl/pkg/cmd/create",
 | 
			
		||||
        "//staging/src/k8s.io/kubectl/pkg/cmd/delete",
 | 
			
		||||
 
 | 
			
		||||
@@ -14,8 +14,10 @@ go_library(
 | 
			
		||||
        "current_context.go",
 | 
			
		||||
        "delete_cluster.go",
 | 
			
		||||
        "delete_context.go",
 | 
			
		||||
        "delete_user.go",
 | 
			
		||||
        "get_clusters.go",
 | 
			
		||||
        "get_contexts.go",
 | 
			
		||||
        "get_users.go",
 | 
			
		||||
        "navigation_step_parser.go",
 | 
			
		||||
        "rename_context.go",
 | 
			
		||||
        "set.go",
 | 
			
		||||
@@ -25,9 +27,7 @@ go_library(
 | 
			
		||||
    ],
 | 
			
		||||
    importmap = "k8s.io/kubernetes/vendor/k8s.io/kubectl/pkg/cmd/config",
 | 
			
		||||
    importpath = "k8s.io/kubectl/pkg/cmd/config",
 | 
			
		||||
    visibility = [
 | 
			
		||||
        "//build/visible_to:pkg_kubectl_cmd_config_CONSUMERS",
 | 
			
		||||
    ],
 | 
			
		||||
    visibility = ["//visibility:public"],
 | 
			
		||||
    deps = [
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
 | 
			
		||||
@@ -56,8 +56,10 @@ go_test(
 | 
			
		||||
        "current_context_test.go",
 | 
			
		||||
        "delete_cluster_test.go",
 | 
			
		||||
        "delete_context_test.go",
 | 
			
		||||
        "delete_user_test.go",
 | 
			
		||||
        "get_clusters_test.go",
 | 
			
		||||
        "get_contexts_test.go",
 | 
			
		||||
        "get_users_test.go",
 | 
			
		||||
        "navigation_step_parser_test.go",
 | 
			
		||||
        "rename_context_test.go",
 | 
			
		||||
        "set_test.go",
 | 
			
		||||
@@ -73,6 +75,7 @@ go_test(
 | 
			
		||||
        "//staging/src/k8s.io/client-go/tools/clientcmd:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/client-go/tools/clientcmd/api:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/component-base/cli/flag:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/kubectl/pkg/cmd/testing:go_default_library",
 | 
			
		||||
        "//staging/src/k8s.io/kubectl/pkg/cmd/util:go_default_library",
 | 
			
		||||
    ],
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
@@ -65,8 +65,10 @@ func NewCmdConfig(f cmdutil.Factory, pathOptions *clientcmd.PathOptions, streams
 | 
			
		||||
	cmd.AddCommand(NewCmdConfigUseContext(streams.Out, pathOptions))
 | 
			
		||||
	cmd.AddCommand(NewCmdConfigGetContexts(streams, pathOptions))
 | 
			
		||||
	cmd.AddCommand(NewCmdConfigGetClusters(streams.Out, pathOptions))
 | 
			
		||||
	cmd.AddCommand(NewCmdConfigGetUsers(streams, pathOptions))
 | 
			
		||||
	cmd.AddCommand(NewCmdConfigDeleteCluster(streams.Out, pathOptions))
 | 
			
		||||
	cmd.AddCommand(NewCmdConfigDeleteContext(streams.Out, streams.ErrOut, pathOptions))
 | 
			
		||||
	cmd.AddCommand(NewCmdConfigDeleteUser(streams, pathOptions))
 | 
			
		||||
	cmd.AddCommand(NewCmdConfigRenameContext(streams.Out, pathOptions))
 | 
			
		||||
 | 
			
		||||
	return cmd
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										120
									
								
								staging/src/k8s.io/kubectl/pkg/cmd/config/delete_user.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								staging/src/k8s.io/kubectl/pkg/cmd/config/delete_user.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,120 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2020 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 config
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/cli-runtime/pkg/genericclioptions"
 | 
			
		||||
	"k8s.io/client-go/tools/clientcmd"
 | 
			
		||||
	clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
 | 
			
		||||
	cmdutil "k8s.io/kubectl/pkg/cmd/util"
 | 
			
		||||
	"k8s.io/kubectl/pkg/util/i18n"
 | 
			
		||||
	"k8s.io/kubectl/pkg/util/templates"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	deleteUserExample = templates.Examples(`
 | 
			
		||||
		# Delete the minikube user
 | 
			
		||||
		kubectl config delete-user minikube`)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DeleteUserOptions holds the data needed to run the command
 | 
			
		||||
type DeleteUserOptions struct {
 | 
			
		||||
	user string
 | 
			
		||||
 | 
			
		||||
	configAccess clientcmd.ConfigAccess
 | 
			
		||||
	config       *clientcmdapi.Config
 | 
			
		||||
	configFile   string
 | 
			
		||||
 | 
			
		||||
	genericclioptions.IOStreams
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewDeleteUserOptions creates the options for the command
 | 
			
		||||
func NewDeleteUserOptions(ioStreams genericclioptions.IOStreams, configAccess clientcmd.ConfigAccess) *DeleteUserOptions {
 | 
			
		||||
	return &DeleteUserOptions{
 | 
			
		||||
		configAccess: configAccess,
 | 
			
		||||
		IOStreams:    ioStreams,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewCmdConfigDeleteUser returns a Command instance for 'config delete-user' sub command
 | 
			
		||||
func NewCmdConfigDeleteUser(streams genericclioptions.IOStreams, configAccess clientcmd.ConfigAccess) *cobra.Command {
 | 
			
		||||
	o := NewDeleteUserOptions(streams, configAccess)
 | 
			
		||||
 | 
			
		||||
	cmd := &cobra.Command{
 | 
			
		||||
		Use:                   "delete-user NAME",
 | 
			
		||||
		DisableFlagsInUseLine: true,
 | 
			
		||||
		Short:                 i18n.T("Delete the specified user from the kubeconfig"),
 | 
			
		||||
		Long:                  "Delete the specified user from the kubeconfig",
 | 
			
		||||
		Example:               deleteUserExample,
 | 
			
		||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
			
		||||
			cmdutil.CheckErr(o.Complete(cmd, args))
 | 
			
		||||
			cmdutil.CheckErr(o.Validate())
 | 
			
		||||
			cmdutil.CheckErr(o.Run())
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return cmd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Complete sets up the command to run
 | 
			
		||||
func (o *DeleteUserOptions) Complete(cmd *cobra.Command, args []string) error {
 | 
			
		||||
	config, err := o.configAccess.GetStartingConfig()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	o.config = config
 | 
			
		||||
 | 
			
		||||
	if len(args) != 1 {
 | 
			
		||||
		return cmdutil.UsageErrorf(cmd, "user to delete is required")
 | 
			
		||||
	}
 | 
			
		||||
	o.user = args[0]
 | 
			
		||||
 | 
			
		||||
	configFile := o.configAccess.GetDefaultFilename()
 | 
			
		||||
	if o.configAccess.IsExplicitFile() {
 | 
			
		||||
		configFile = o.configAccess.GetExplicitFile()
 | 
			
		||||
	}
 | 
			
		||||
	o.configFile = configFile
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Validate ensures the command has enough info to run
 | 
			
		||||
func (o *DeleteUserOptions) Validate() error {
 | 
			
		||||
	_, ok := o.config.AuthInfos[o.user]
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return fmt.Errorf("cannot delete user %s, not in %s", o.user, o.configFile)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Run performs the command
 | 
			
		||||
func (o *DeleteUserOptions) Run() error {
 | 
			
		||||
	delete(o.config.AuthInfos, o.user)
 | 
			
		||||
 | 
			
		||||
	if err := clientcmd.ModifyConfig(o.configAccess, *o.config, true); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fmt.Fprintf(o.Out, "deleted user %s from %s\n", o.user, o.configFile)
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										202
									
								
								staging/src/k8s.io/kubectl/pkg/cmd/config/delete_user_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										202
									
								
								staging/src/k8s.io/kubectl/pkg/cmd/config/delete_user_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,202 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2020 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 config
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/cli-runtime/pkg/genericclioptions"
 | 
			
		||||
	"k8s.io/client-go/tools/clientcmd"
 | 
			
		||||
	clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
 | 
			
		||||
	cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestDeleteUserComplete(t *testing.T) {
 | 
			
		||||
	var tests = []struct {
 | 
			
		||||
		name string
 | 
			
		||||
		args []string
 | 
			
		||||
		err  string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "no args",
 | 
			
		||||
			args: []string{},
 | 
			
		||||
			err:  "user to delete is required",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "user provided",
 | 
			
		||||
			args: []string{"minikube"},
 | 
			
		||||
			err:  "",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i := range tests {
 | 
			
		||||
		test := tests[i]
 | 
			
		||||
		t.Run(test.name, func(t *testing.T) {
 | 
			
		||||
			tf := cmdtesting.NewTestFactory()
 | 
			
		||||
			defer tf.Cleanup()
 | 
			
		||||
 | 
			
		||||
			ioStreams, _, out, _ := genericclioptions.NewTestIOStreams()
 | 
			
		||||
			pathOptions, err := tf.PathOptionsWithConfig(clientcmdapi.Config{})
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Fatalf("unexpected error executing command: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			cmd := NewCmdConfigDeleteUser(ioStreams, pathOptions)
 | 
			
		||||
			cmd.SetOut(out)
 | 
			
		||||
			options := NewDeleteUserOptions(ioStreams, pathOptions)
 | 
			
		||||
 | 
			
		||||
			if err := options.Complete(cmd, test.args); err != nil {
 | 
			
		||||
				if test.err == "" {
 | 
			
		||||
					t.Fatalf("unexpected error executing command: %v", err)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if !strings.Contains(err.Error(), test.err) {
 | 
			
		||||
					t.Fatalf("expected error to contain %v, got %v", test.err, err.Error())
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if options.configFile != pathOptions.GlobalFile {
 | 
			
		||||
				t.Fatalf("expected configFile to be %v, got %v", pathOptions.GlobalFile, options.configFile)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestDeleteUserValidate(t *testing.T) {
 | 
			
		||||
	var tests = []struct {
 | 
			
		||||
		name   string
 | 
			
		||||
		user   string
 | 
			
		||||
		config clientcmdapi.Config
 | 
			
		||||
		err    string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "user not in config",
 | 
			
		||||
			user: "kube",
 | 
			
		||||
			config: clientcmdapi.Config{
 | 
			
		||||
				AuthInfos: map[string]*clientcmdapi.AuthInfo{
 | 
			
		||||
					"minikube": {Username: "minikube"},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			err: "cannot delete user kube",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "user in config",
 | 
			
		||||
			user: "kube",
 | 
			
		||||
			config: clientcmdapi.Config{
 | 
			
		||||
				AuthInfos: map[string]*clientcmdapi.AuthInfo{
 | 
			
		||||
					"minikube": {Username: "minikube"},
 | 
			
		||||
					"kube":     {Username: "kube"},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			err: "",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i := range tests {
 | 
			
		||||
		test := tests[i]
 | 
			
		||||
		t.Run(test.name, func(t *testing.T) {
 | 
			
		||||
			tf := cmdtesting.NewTestFactory()
 | 
			
		||||
			defer tf.Cleanup()
 | 
			
		||||
 | 
			
		||||
			ioStreams, _, _, _ := genericclioptions.NewTestIOStreams()
 | 
			
		||||
			pathOptions, err := tf.PathOptionsWithConfig(test.config)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Fatalf("unexpected error executing command: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			options := NewDeleteUserOptions(ioStreams, pathOptions)
 | 
			
		||||
			options.config = &test.config
 | 
			
		||||
			options.user = test.user
 | 
			
		||||
 | 
			
		||||
			if err := options.Validate(); err != nil {
 | 
			
		||||
				if !strings.Contains(err.Error(), test.err) {
 | 
			
		||||
					t.Fatalf("expected: %s but got %s", test.err, err.Error())
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestDeleteUserRun(t *testing.T) {
 | 
			
		||||
	var tests = []struct {
 | 
			
		||||
		name          string
 | 
			
		||||
		user          string
 | 
			
		||||
		config        clientcmdapi.Config
 | 
			
		||||
		expectedUsers []string
 | 
			
		||||
		out           string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name: "delete user",
 | 
			
		||||
			user: "kube",
 | 
			
		||||
			config: clientcmdapi.Config{
 | 
			
		||||
				AuthInfos: map[string]*clientcmdapi.AuthInfo{
 | 
			
		||||
					"minikube": {Username: "minikube"},
 | 
			
		||||
					"kube":     {Username: "kube"},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expectedUsers: []string{"minikube"},
 | 
			
		||||
			out:           "deleted user kube from",
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i := range tests {
 | 
			
		||||
		test := tests[i]
 | 
			
		||||
		t.Run(test.name, func(t *testing.T) {
 | 
			
		||||
			tf := cmdtesting.NewTestFactory()
 | 
			
		||||
			defer tf.Cleanup()
 | 
			
		||||
 | 
			
		||||
			ioStreams, _, out, _ := genericclioptions.NewTestIOStreams()
 | 
			
		||||
			pathOptions, err := tf.PathOptionsWithConfig(test.config)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Fatalf("unexpected error executing command: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			options := NewDeleteUserOptions(ioStreams, pathOptions)
 | 
			
		||||
			options.config = &test.config
 | 
			
		||||
			options.configFile = pathOptions.GlobalFile
 | 
			
		||||
			options.user = test.user
 | 
			
		||||
 | 
			
		||||
			if err := options.Run(); err != nil {
 | 
			
		||||
				t.Fatalf("unexpected error executing command: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if got := out.String(); !strings.Contains(got, test.out) {
 | 
			
		||||
				t.Fatalf("expected: %s but got %s", test.out, got)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			config, err := clientcmd.LoadFromFile(options.configFile)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Fatalf("unexpected error executing command: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			users := make([]string, 0, len(config.AuthInfos))
 | 
			
		||||
			for user := range config.AuthInfos {
 | 
			
		||||
				users = append(users, user)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if !reflect.DeepEqual(test.expectedUsers, users) {
 | 
			
		||||
				t.Fatalf("expected %v, got %v", test.expectedUsers, users)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										90
									
								
								staging/src/k8s.io/kubectl/pkg/cmd/config/get_users.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								staging/src/k8s.io/kubectl/pkg/cmd/config/get_users.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,90 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2020 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 config
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"sort"
 | 
			
		||||
 | 
			
		||||
	"github.com/spf13/cobra"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/cli-runtime/pkg/genericclioptions"
 | 
			
		||||
	"k8s.io/client-go/tools/clientcmd"
 | 
			
		||||
	cmdutil "k8s.io/kubectl/pkg/cmd/util"
 | 
			
		||||
	"k8s.io/kubectl/pkg/util/i18n"
 | 
			
		||||
	"k8s.io/kubectl/pkg/util/templates"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	getUsersExample = templates.Examples(`
 | 
			
		||||
		# List the users kubectl knows about
 | 
			
		||||
		kubectl config get-users`)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// GetUsersOptions holds the data needed to run the command
 | 
			
		||||
type GetUsersOptions struct {
 | 
			
		||||
	configAccess clientcmd.ConfigAccess
 | 
			
		||||
 | 
			
		||||
	genericclioptions.IOStreams
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewGetUsersOptions creates the options for the command
 | 
			
		||||
func NewGetUsersOptions(ioStreams genericclioptions.IOStreams, configAccess clientcmd.ConfigAccess) *GetUsersOptions {
 | 
			
		||||
	return &GetUsersOptions{
 | 
			
		||||
		configAccess: configAccess,
 | 
			
		||||
		IOStreams:    ioStreams,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewCmdConfigGetUsers creates a command object for the "get-users" action, which
 | 
			
		||||
// lists all users defined in the kubeconfig.
 | 
			
		||||
func NewCmdConfigGetUsers(streams genericclioptions.IOStreams, configAccess clientcmd.ConfigAccess) *cobra.Command {
 | 
			
		||||
	o := NewGetUsersOptions(streams, configAccess)
 | 
			
		||||
 | 
			
		||||
	cmd := &cobra.Command{
 | 
			
		||||
		Use:     "get-users",
 | 
			
		||||
		Short:   i18n.T("Display users defined in the kubeconfig"),
 | 
			
		||||
		Long:    "Display users defined in the kubeconfig.",
 | 
			
		||||
		Example: getUsersExample,
 | 
			
		||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
			
		||||
			cmdutil.CheckErr(o.Run())
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return cmd
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Run performs the command
 | 
			
		||||
func (o *GetUsersOptions) Run() error {
 | 
			
		||||
	config, err := o.configAccess.GetStartingConfig()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	users := make([]string, 0, len(config.AuthInfos))
 | 
			
		||||
	for user := range config.AuthInfos {
 | 
			
		||||
		users = append(users, user)
 | 
			
		||||
	}
 | 
			
		||||
	sort.Strings(users)
 | 
			
		||||
 | 
			
		||||
	fmt.Fprintf(o.Out, "NAME\n")
 | 
			
		||||
	for _, user := range users {
 | 
			
		||||
		fmt.Fprintf(o.Out, "%s\n", user)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										75
									
								
								staging/src/k8s.io/kubectl/pkg/cmd/config/get_users_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										75
									
								
								staging/src/k8s.io/kubectl/pkg/cmd/config/get_users_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,75 @@
 | 
			
		||||
/*
 | 
			
		||||
Copyright 2020 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 config
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"k8s.io/cli-runtime/pkg/genericclioptions"
 | 
			
		||||
	clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
 | 
			
		||||
	cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestGetUsersRun(t *testing.T) {
 | 
			
		||||
	var tests = []struct {
 | 
			
		||||
		name     string
 | 
			
		||||
		config   clientcmdapi.Config
 | 
			
		||||
		expected string
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			name:     "no users",
 | 
			
		||||
			config:   clientcmdapi.Config{},
 | 
			
		||||
			expected: "NAME\n",
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			name: "some users",
 | 
			
		||||
			config: clientcmdapi.Config{
 | 
			
		||||
				AuthInfos: map[string]*clientcmdapi.AuthInfo{
 | 
			
		||||
					"minikube": {Username: "minikube"},
 | 
			
		||||
					"admin":    {Username: "admin"},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expected: `NAME
 | 
			
		||||
admin
 | 
			
		||||
minikube
 | 
			
		||||
`,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i := range tests {
 | 
			
		||||
		test := tests[i]
 | 
			
		||||
		t.Run(test.name, func(t *testing.T) {
 | 
			
		||||
			tf := cmdtesting.NewTestFactory()
 | 
			
		||||
			defer tf.Cleanup()
 | 
			
		||||
 | 
			
		||||
			ioStreams, _, out, _ := genericclioptions.NewTestIOStreams()
 | 
			
		||||
			pathOptions, err := tf.PathOptionsWithConfig(test.config)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				t.Fatalf("unexpected error executing command: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
			options := NewGetUsersOptions(ioStreams, pathOptions)
 | 
			
		||||
 | 
			
		||||
			if err = options.Run(); err != nil {
 | 
			
		||||
				t.Fatalf("unexpected error executing command: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if got := out.String(); got != test.expected {
 | 
			
		||||
				t.Fatalf("expected: %s but got %s", test.expected, got)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -465,6 +465,25 @@ func (f *TestFactory) ClientForMapping(mapping *meta.RESTMapping) (resource.REST
 | 
			
		||||
	return f.Client, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PathOptions returns a new PathOptions with a temp file
 | 
			
		||||
func (f *TestFactory) PathOptions() *clientcmd.PathOptions {
 | 
			
		||||
	pathOptions := clientcmd.NewDefaultPathOptions()
 | 
			
		||||
	pathOptions.GlobalFile = f.tempConfigFile.Name()
 | 
			
		||||
	pathOptions.EnvVar = ""
 | 
			
		||||
	return pathOptions
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PathOptionsWithConfig writes a config to a temp file and returns PathOptions
 | 
			
		||||
func (f *TestFactory) PathOptionsWithConfig(config clientcmdapi.Config) (*clientcmd.PathOptions, error) {
 | 
			
		||||
	pathOptions := f.PathOptions()
 | 
			
		||||
	err := clientcmd.WriteToFile(config, pathOptions.GlobalFile)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return pathOptions, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnstructuredClientForMapping is used to get UnstructuredClient from a TestFactory
 | 
			
		||||
func (f *TestFactory) UnstructuredClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error) {
 | 
			
		||||
	if f.UnstructuredClientForMappingFunc != nil {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user