mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Merge pull request #41538 from xingzhou/clusterrole
Automatic merge from submit-queue (batch tested with PRs 41146, 41486, 41482, 41538, 41784) Added `kubectl create clusterrole` command. Added `kubectl create clusterrole` command. Fixed part of #39596 **Special notes for your reviewer**: @deads2k, please help to review this patch, thanks **Release note**: ``` Added one new command `kubectl create clusterrole` to help user create a single ClusterRole from command line. ```
This commit is contained in:
		@@ -38,6 +38,7 @@ docs/man/man1/kubectl-config.1
 | 
				
			|||||||
docs/man/man1/kubectl-convert.1
 | 
					docs/man/man1/kubectl-convert.1
 | 
				
			||||||
docs/man/man1/kubectl-cordon.1
 | 
					docs/man/man1/kubectl-cordon.1
 | 
				
			||||||
docs/man/man1/kubectl-cp.1
 | 
					docs/man/man1/kubectl-cp.1
 | 
				
			||||||
 | 
					docs/man/man1/kubectl-create-clusterrole.1
 | 
				
			||||||
docs/man/man1/kubectl-create-clusterrolebinding.1
 | 
					docs/man/man1/kubectl-create-clusterrolebinding.1
 | 
				
			||||||
docs/man/man1/kubectl-create-configmap.1
 | 
					docs/man/man1/kubectl-create-configmap.1
 | 
				
			||||||
docs/man/man1/kubectl-create-deployment.1
 | 
					docs/man/man1/kubectl-create-deployment.1
 | 
				
			||||||
@@ -124,6 +125,7 @@ docs/user-guide/kubectl/kubectl_convert.md
 | 
				
			|||||||
docs/user-guide/kubectl/kubectl_cordon.md
 | 
					docs/user-guide/kubectl/kubectl_cordon.md
 | 
				
			||||||
docs/user-guide/kubectl/kubectl_cp.md
 | 
					docs/user-guide/kubectl/kubectl_cp.md
 | 
				
			||||||
docs/user-guide/kubectl/kubectl_create.md
 | 
					docs/user-guide/kubectl/kubectl_create.md
 | 
				
			||||||
 | 
					docs/user-guide/kubectl/kubectl_create_clusterrole.md
 | 
				
			||||||
docs/user-guide/kubectl/kubectl_create_clusterrolebinding.md
 | 
					docs/user-guide/kubectl/kubectl_create_clusterrolebinding.md
 | 
				
			||||||
docs/user-guide/kubectl/kubectl_create_configmap.md
 | 
					docs/user-guide/kubectl/kubectl_create_configmap.md
 | 
				
			||||||
docs/user-guide/kubectl/kubectl_create_deployment.md
 | 
					docs/user-guide/kubectl/kubectl_create_deployment.md
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								docs/man/man1/kubectl-create-clusterrole.1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								docs/man/man1/kubectl-create-clusterrole.1
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					This file is autogenerated, but we've stopped checking such files into the
 | 
				
			||||||
 | 
					repository to reduce the need for rebases. Please run hack/generate-docs.sh to
 | 
				
			||||||
 | 
					populate this file.
 | 
				
			||||||
							
								
								
									
										3
									
								
								docs/user-guide/kubectl/kubectl_create_clusterrole.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								docs/user-guide/kubectl/kubectl_create_clusterrole.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					This file is autogenerated, but we've stopped checking such files into the
 | 
				
			||||||
 | 
					repository to reduce the need for rebases. Please run hack/generate-docs.sh to
 | 
				
			||||||
 | 
					populate this file.
 | 
				
			||||||
@@ -2803,6 +2803,23 @@ runTests() {
 | 
				
			|||||||
    # make sure the server was properly bootstrapped with clusterroles and bindings
 | 
					    # make sure the server was properly bootstrapped with clusterroles and bindings
 | 
				
			||||||
    kube::test::get_object_assert clusterroles/cluster-admin "{{.metadata.name}}" 'cluster-admin'
 | 
					    kube::test::get_object_assert clusterroles/cluster-admin "{{.metadata.name}}" 'cluster-admin'
 | 
				
			||||||
    kube::test::get_object_assert clusterrolebindings/cluster-admin "{{.metadata.name}}" 'cluster-admin'
 | 
					    kube::test::get_object_assert clusterrolebindings/cluster-admin "{{.metadata.name}}" 'cluster-admin'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # test `kubectl create clusterrole`
 | 
				
			||||||
 | 
					    kubectl create "${kube_flags[@]}" clusterrole pod-admin --verb=* --resource=pods
 | 
				
			||||||
 | 
					    kube::test::get_object_assert clusterrole/pod-admin "{{range.rules}}{{range.verbs}}{{.}}:{{end}}{{end}}" '\*:'
 | 
				
			||||||
 | 
					    kube::test::get_object_assert clusterrole/pod-admin "{{range.rules}}{{range.resources}}{{.}}:{{end}}{{end}}" 'pods:'
 | 
				
			||||||
 | 
					    kube::test::get_object_assert clusterrole/pod-admin "{{range.rules}}{{range.apiGroups}}{{.}}:{{end}}{{end}}" ':'
 | 
				
			||||||
 | 
					    kubectl create "${kube_flags[@]}" clusterrole resource-reader --verb=get,list --resource=pods,deployments.extensions
 | 
				
			||||||
 | 
					    kube::test::get_object_assert clusterrole/resource-reader "{{range.rules}}{{range.verbs}}{{.}}:{{end}}{{end}}" 'get:list:get:list:'
 | 
				
			||||||
 | 
					    kube::test::get_object_assert clusterrole/resource-reader "{{range.rules}}{{range.resources}}{{.}}:{{end}}{{end}}" 'pods:deployments:'
 | 
				
			||||||
 | 
					    kube::test::get_object_assert clusterrole/resource-reader "{{range.rules}}{{range.apiGroups}}{{.}}:{{end}}{{end}}" ':extensions:'
 | 
				
			||||||
 | 
					    kubectl create "${kube_flags[@]}" clusterrole resourcename-reader --verb=get,list --resource=pods --resource-name=foo
 | 
				
			||||||
 | 
					    kube::test::get_object_assert clusterrole/resourcename-reader "{{range.rules}}{{range.verbs}}{{.}}:{{end}}{{end}}" 'get:list:'
 | 
				
			||||||
 | 
					    kube::test::get_object_assert clusterrole/resourcename-reader "{{range.rules}}{{range.resources}}{{.}}:{{end}}{{end}}" 'pods:'
 | 
				
			||||||
 | 
					    kube::test::get_object_assert clusterrole/resourcename-reader "{{range.rules}}{{range.apiGroups}}{{.}}:{{end}}{{end}}" ':'
 | 
				
			||||||
 | 
					    kube::test::get_object_assert clusterrole/resourcename-reader "{{range.rules}}{{range.resourceNames}}{{.}}:{{end}}{{end}}" 'foo:'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # test `kubectl create clusterrolebinding`
 | 
				
			||||||
    kubectl create "${kube_flags[@]}" clusterrolebinding super-admin --clusterrole=admin --user=super-admin
 | 
					    kubectl create "${kube_flags[@]}" clusterrolebinding super-admin --clusterrole=admin --user=super-admin
 | 
				
			||||||
    kube::test::get_object_assert clusterrolebinding/super-admin "{{range.subjects}}{{.name}}:{{end}}" 'super-admin:'
 | 
					    kube::test::get_object_assert clusterrolebinding/super-admin "{{range.subjects}}{{.name}}:{{end}}" 'super-admin:'
 | 
				
			||||||
    kubectl create "${kube_flags[@]}" clusterrolebinding super-group --clusterrole=admin --group=the-group
 | 
					    kubectl create "${kube_flags[@]}" clusterrolebinding super-group --clusterrole=admin --group=the-group
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,6 +25,7 @@ go_library(
 | 
				
			|||||||
        "convert.go",
 | 
					        "convert.go",
 | 
				
			||||||
        "cp.go",
 | 
					        "cp.go",
 | 
				
			||||||
        "create.go",
 | 
					        "create.go",
 | 
				
			||||||
 | 
					        "create_clusterrole.go",
 | 
				
			||||||
        "create_clusterrolebinding.go",
 | 
					        "create_clusterrolebinding.go",
 | 
				
			||||||
        "create_configmap.go",
 | 
					        "create_configmap.go",
 | 
				
			||||||
        "create_deployment.go",
 | 
					        "create_deployment.go",
 | 
				
			||||||
@@ -75,6 +76,7 @@ go_library(
 | 
				
			|||||||
        "//pkg/apis/rbac:go_default_library",
 | 
					        "//pkg/apis/rbac:go_default_library",
 | 
				
			||||||
        "//pkg/client/clientset_generated/internalclientset:go_default_library",
 | 
					        "//pkg/client/clientset_generated/internalclientset:go_default_library",
 | 
				
			||||||
        "//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
 | 
					        "//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
 | 
				
			||||||
 | 
					        "//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library",
 | 
				
			||||||
        "//pkg/client/unversioned:go_default_library",
 | 
					        "//pkg/client/unversioned:go_default_library",
 | 
				
			||||||
        "//pkg/client/unversioned/remotecommand:go_default_library",
 | 
					        "//pkg/client/unversioned/remotecommand:go_default_library",
 | 
				
			||||||
        "//pkg/kubectl:go_default_library",
 | 
					        "//pkg/kubectl:go_default_library",
 | 
				
			||||||
@@ -143,6 +145,7 @@ go_test(
 | 
				
			|||||||
        "clusterinfo_dump_test.go",
 | 
					        "clusterinfo_dump_test.go",
 | 
				
			||||||
        "cmd_test.go",
 | 
					        "cmd_test.go",
 | 
				
			||||||
        "cp_test.go",
 | 
					        "cp_test.go",
 | 
				
			||||||
 | 
					        "create_clusterrole_test.go",
 | 
				
			||||||
        "create_configmap_test.go",
 | 
					        "create_configmap_test.go",
 | 
				
			||||||
        "create_deployment_test.go",
 | 
					        "create_deployment_test.go",
 | 
				
			||||||
        "create_namespace_test.go",
 | 
					        "create_namespace_test.go",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -95,6 +95,7 @@ func NewCmdCreate(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
 | 
				
			|||||||
	cmd.AddCommand(NewCmdCreateServiceAccount(f, out))
 | 
						cmd.AddCommand(NewCmdCreateServiceAccount(f, out))
 | 
				
			||||||
	cmd.AddCommand(NewCmdCreateService(f, out, errOut))
 | 
						cmd.AddCommand(NewCmdCreateService(f, out, errOut))
 | 
				
			||||||
	cmd.AddCommand(NewCmdCreateDeployment(f, out))
 | 
						cmd.AddCommand(NewCmdCreateDeployment(f, out))
 | 
				
			||||||
 | 
						cmd.AddCommand(NewCmdCreateClusterRole(f, out))
 | 
				
			||||||
	cmd.AddCommand(NewCmdCreateClusterRoleBinding(f, out))
 | 
						cmd.AddCommand(NewCmdCreateClusterRoleBinding(f, out))
 | 
				
			||||||
	cmd.AddCommand(NewCmdCreateRole(f, out))
 | 
						cmd.AddCommand(NewCmdCreateRole(f, out))
 | 
				
			||||||
	cmd.AddCommand(NewCmdCreateRoleBinding(f, out))
 | 
						cmd.AddCommand(NewCmdCreateRoleBinding(f, out))
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										97
									
								
								pkg/kubectl/cmd/create_clusterrole.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								pkg/kubectl/cmd/create_clusterrole.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,97 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2017 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 cmd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/spf13/cobra"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/apis/rbac"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
 | 
				
			||||||
 | 
						cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						clusterRoleLong = templates.LongDesc(`
 | 
				
			||||||
 | 
							Create a ClusterRole.`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						clusterRoleExample = templates.Examples(`
 | 
				
			||||||
 | 
							# Create a ClusterRole named "pod-reader" that allows user to perform "get", "watch" and "list" on pods
 | 
				
			||||||
 | 
							kubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							# Create a ClusterRole named "pod-reader" with ResourceName specified
 | 
				
			||||||
 | 
							kubectl create clusterrole pod-reader --verb=get,list,watch --resource=pods --resource-name=readablepod`)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type CreateClusterRoleOptions struct {
 | 
				
			||||||
 | 
						*CreateRoleOptions
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ClusterRole is a command to ease creating ClusterRoles.
 | 
				
			||||||
 | 
					func NewCmdCreateClusterRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
 | 
				
			||||||
 | 
						c := &CreateClusterRoleOptions{
 | 
				
			||||||
 | 
							CreateRoleOptions: &CreateRoleOptions{
 | 
				
			||||||
 | 
								Out: cmdOut,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						cmd := &cobra.Command{
 | 
				
			||||||
 | 
							Use:     "clusterrole NAME --verb=verb --resource=resource.group [--resource-name=resourcename] [--dry-run]",
 | 
				
			||||||
 | 
							Short:   clusterRoleLong,
 | 
				
			||||||
 | 
							Long:    clusterRoleLong,
 | 
				
			||||||
 | 
							Example: clusterRoleExample,
 | 
				
			||||||
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
 | 
								cmdutil.CheckErr(c.Complete(f, cmd, args))
 | 
				
			||||||
 | 
								cmdutil.CheckErr(c.Validate())
 | 
				
			||||||
 | 
								cmdutil.CheckErr(c.RunCreateRole())
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						cmdutil.AddApplyAnnotationFlags(cmd)
 | 
				
			||||||
 | 
						cmdutil.AddValidateFlags(cmd)
 | 
				
			||||||
 | 
						cmdutil.AddPrinterFlags(cmd)
 | 
				
			||||||
 | 
						cmdutil.AddDryRunFlag(cmd)
 | 
				
			||||||
 | 
						cmd.Flags().StringSliceVar(&c.Verbs, "verb", []string{}, "verb that applies to the resources contained in the rule")
 | 
				
			||||||
 | 
						cmd.Flags().StringSlice("resource", []string{}, "resource that the rule applies to")
 | 
				
			||||||
 | 
						cmd.Flags().StringSliceVar(&c.ResourceNames, "resource-name", []string{}, "resource in the white list that the rule applies to")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return cmd
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *CreateClusterRoleOptions) RunCreateRole() error {
 | 
				
			||||||
 | 
						clusterRole := &rbac.ClusterRole{}
 | 
				
			||||||
 | 
						clusterRole.Name = c.Name
 | 
				
			||||||
 | 
						rules, err := generateResourcePolicyRules(c.Mapper, c.Verbs, c.Resources, c.ResourceNames)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						clusterRole.Rules = rules
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Create ClusterRole.
 | 
				
			||||||
 | 
						if !c.DryRun {
 | 
				
			||||||
 | 
							_, err = c.Client.ClusterRoles().Create(clusterRole)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if useShortOutput := c.OutputFormat == "name"; useShortOutput || len(c.OutputFormat) == 0 {
 | 
				
			||||||
 | 
							cmdutil.PrintSuccess(c.Mapper, useShortOutput, c.Out, "clusterroles", c.Name, c.DryRun, "created")
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return c.PrintObject(clusterRole)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										122
									
								
								pkg/kubectl/cmd/create_clusterrole_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								pkg/kubectl/cmd/create_clusterrole_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,122 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					Copyright 2017 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 cmd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"reflect"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/runtime"
 | 
				
			||||||
 | 
						"k8s.io/client-go/rest/fake"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/apis/rbac"
 | 
				
			||||||
 | 
						cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type testClusterRolePrinter struct {
 | 
				
			||||||
 | 
						CachedClusterRole *rbac.ClusterRole
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (t *testClusterRolePrinter) PrintObj(obj runtime.Object, out io.Writer) error {
 | 
				
			||||||
 | 
						t.CachedClusterRole = obj.(*rbac.ClusterRole)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (t *testClusterRolePrinter) AfterPrint(output io.Writer, res string) error {
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (t *testClusterRolePrinter) HandledResources() []string {
 | 
				
			||||||
 | 
						return []string{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestCreateClusterRole(t *testing.T) {
 | 
				
			||||||
 | 
						clusterRoleName := "my-cluster-role"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						f, tf, _, _ := cmdtesting.NewAPIFactory()
 | 
				
			||||||
 | 
						printer := &testClusterRolePrinter{}
 | 
				
			||||||
 | 
						tf.Printer = printer
 | 
				
			||||||
 | 
						tf.Namespace = "test"
 | 
				
			||||||
 | 
						tf.Client = &fake.RESTClient{}
 | 
				
			||||||
 | 
						tf.ClientConfig = defaultClientConfig()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tests := map[string]struct {
 | 
				
			||||||
 | 
							verbs               string
 | 
				
			||||||
 | 
							resources           string
 | 
				
			||||||
 | 
							resourceNames       string
 | 
				
			||||||
 | 
							expectedClusterRole *rbac.ClusterRole
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							"test-duplicate-resources": {
 | 
				
			||||||
 | 
								verbs:     "get,watch,list",
 | 
				
			||||||
 | 
								resources: "pods,pods",
 | 
				
			||||||
 | 
								expectedClusterRole: &rbac.ClusterRole{
 | 
				
			||||||
 | 
									ObjectMeta: v1.ObjectMeta{
 | 
				
			||||||
 | 
										Name: clusterRoleName,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									Rules: []rbac.PolicyRule{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Verbs:         []string{"get", "watch", "list"},
 | 
				
			||||||
 | 
											Resources:     []string{"pods"},
 | 
				
			||||||
 | 
											APIGroups:     []string{""},
 | 
				
			||||||
 | 
											ResourceNames: []string{},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"test-valid-case-with-multiple-apigroups": {
 | 
				
			||||||
 | 
								verbs:     "get,watch,list",
 | 
				
			||||||
 | 
								resources: "pods,deployments.extensions",
 | 
				
			||||||
 | 
								expectedClusterRole: &rbac.ClusterRole{
 | 
				
			||||||
 | 
									ObjectMeta: v1.ObjectMeta{
 | 
				
			||||||
 | 
										Name: clusterRoleName,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									Rules: []rbac.PolicyRule{
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Verbs:         []string{"get", "watch", "list"},
 | 
				
			||||||
 | 
											Resources:     []string{"pods"},
 | 
				
			||||||
 | 
											APIGroups:     []string{""},
 | 
				
			||||||
 | 
											ResourceNames: []string{},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											Verbs:         []string{"get", "watch", "list"},
 | 
				
			||||||
 | 
											Resources:     []string{"deployments"},
 | 
				
			||||||
 | 
											APIGroups:     []string{"extensions"},
 | 
				
			||||||
 | 
											ResourceNames: []string{},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for name, test := range tests {
 | 
				
			||||||
 | 
							buf := bytes.NewBuffer([]byte{})
 | 
				
			||||||
 | 
							cmd := NewCmdCreateClusterRole(f, buf)
 | 
				
			||||||
 | 
							cmd.Flags().Set("dry-run", "true")
 | 
				
			||||||
 | 
							cmd.Flags().Set("output", "object")
 | 
				
			||||||
 | 
							cmd.Flags().Set("verb", test.verbs)
 | 
				
			||||||
 | 
							cmd.Flags().Set("resource", test.resources)
 | 
				
			||||||
 | 
							if test.resourceNames != "" {
 | 
				
			||||||
 | 
								cmd.Flags().Set("resource-name", test.resourceNames)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							cmd.Run(cmd, []string{clusterRoleName})
 | 
				
			||||||
 | 
							if !reflect.DeepEqual(test.expectedClusterRole, printer.CachedClusterRole) {
 | 
				
			||||||
 | 
								t.Errorf("%s:\nexpected:\n%#v\nsaw:\n%#v", name, test.expectedClusterRole, printer.CachedClusterRole)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -23,9 +23,12 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"github.com/spf13/cobra"
 | 
						"github.com/spf13/cobra"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/api/meta"
 | 
				
			||||||
 | 
						"k8s.io/apimachinery/pkg/runtime"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/runtime/schema"
 | 
						"k8s.io/apimachinery/pkg/runtime/schema"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/sets"
 | 
						"k8s.io/apimachinery/pkg/util/sets"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/apis/rbac"
 | 
						"k8s.io/kubernetes/pkg/apis/rbac"
 | 
				
			||||||
 | 
						internalversionrbac "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
 | 
						"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
 | 
				
			||||||
	cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
 | 
						cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -50,20 +53,30 @@ type CreateRoleOptions struct {
 | 
				
			|||||||
	Verbs         []string
 | 
						Verbs         []string
 | 
				
			||||||
	Resources     []schema.GroupVersionResource
 | 
						Resources     []schema.GroupVersionResource
 | 
				
			||||||
	ResourceNames []string
 | 
						ResourceNames []string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DryRun       bool
 | 
				
			||||||
 | 
						OutputFormat string
 | 
				
			||||||
 | 
						Namespace    string
 | 
				
			||||||
 | 
						Client       internalversionrbac.RbacInterface
 | 
				
			||||||
 | 
						Mapper       meta.RESTMapper
 | 
				
			||||||
 | 
						Out          io.Writer
 | 
				
			||||||
 | 
						PrintObject  func(obj runtime.Object) error
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Role is a command to ease creating Roles.
 | 
					// Role is a command to ease creating Roles.
 | 
				
			||||||
func NewCmdCreateRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
 | 
					func NewCmdCreateRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
 | 
				
			||||||
	c := &CreateRoleOptions{}
 | 
						c := &CreateRoleOptions{
 | 
				
			||||||
 | 
							Out: cmdOut,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	cmd := &cobra.Command{
 | 
						cmd := &cobra.Command{
 | 
				
			||||||
		Use:     "role NAME --verb=verb --resource=resource.group [--resource-name=resourcename] [--dry-run]",
 | 
							Use:     "role NAME --verb=verb --resource=resource.group [--resource-name=resourcename] [--dry-run]",
 | 
				
			||||||
		Short:   roleLong,
 | 
							Short:   roleLong,
 | 
				
			||||||
		Long:    roleLong,
 | 
							Long:    roleLong,
 | 
				
			||||||
		Example: roleExample,
 | 
							Example: roleExample,
 | 
				
			||||||
		Run: func(cmd *cobra.Command, args []string) {
 | 
							Run: func(cmd *cobra.Command, args []string) {
 | 
				
			||||||
			cmdutil.CheckErr(c.Complete(cmd, args))
 | 
								cmdutil.CheckErr(c.Complete(f, cmd, args))
 | 
				
			||||||
			cmdutil.CheckErr(c.Validate(f))
 | 
								cmdutil.CheckErr(c.Validate())
 | 
				
			||||||
			cmdutil.CheckErr(c.RunCreateRole(f, cmdOut, cmd, args))
 | 
								cmdutil.CheckErr(c.RunCreateRole())
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cmdutil.AddApplyAnnotationFlags(cmd)
 | 
						cmdutil.AddApplyAnnotationFlags(cmd)
 | 
				
			||||||
@@ -77,7 +90,7 @@ func NewCmdCreateRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command {
 | 
				
			|||||||
	return cmd
 | 
						return cmd
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *CreateRoleOptions) Complete(cmd *cobra.Command, args []string) error {
 | 
					func (c *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
 | 
				
			||||||
	name, err := NameFromCommandArgs(cmd, args)
 | 
						name, err := NameFromCommandArgs(cmd, args)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
@@ -120,10 +133,31 @@ func (c *CreateRoleOptions) Complete(cmd *cobra.Command, args []string) error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	c.ResourceNames = resourceNames
 | 
						c.ResourceNames = resourceNames
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Complete other options for Run.
 | 
				
			||||||
 | 
						c.Mapper, _ = f.Object()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c.DryRun = cmdutil.GetDryRunFlag(cmd)
 | 
				
			||||||
 | 
						c.OutputFormat = cmdutil.GetFlagString(cmd, "output")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c.Namespace, _, err = f.DefaultNamespace()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c.PrintObject = func(obj runtime.Object) error {
 | 
				
			||||||
 | 
							return f.PrintObject(cmd, c.Mapper, obj, c.Out)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						clientSet, err := f.ClientSet()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c.Client = clientSet.Rbac()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *CreateRoleOptions) Validate(f cmdutil.Factory) error {
 | 
					func (c *CreateRoleOptions) Validate() error {
 | 
				
			||||||
	if c.Name == "" {
 | 
						if c.Name == "" {
 | 
				
			||||||
		return fmt.Errorf("name must be specified")
 | 
							return fmt.Errorf("name must be specified")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -140,14 +174,12 @@ func (c *CreateRoleOptions) Validate(f cmdutil.Factory) error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// validate resources.
 | 
						// validate resources.
 | 
				
			||||||
	mapper, _ := f.Object()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if len(c.Resources) == 0 {
 | 
						if len(c.Resources) == 0 {
 | 
				
			||||||
		return fmt.Errorf("at least one resource must be specified")
 | 
							return fmt.Errorf("at least one resource must be specified")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, r := range c.Resources {
 | 
						for _, r := range c.Resources {
 | 
				
			||||||
		_, err := mapper.ResourceFor(r)
 | 
							_, err := c.Mapper.ResourceFor(r)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -161,67 +193,29 @@ func (c *CreateRoleOptions) Validate(f cmdutil.Factory) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *CreateRoleOptions) RunCreateRole(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error {
 | 
					func (c *CreateRoleOptions) RunCreateRole() error {
 | 
				
			||||||
	mapper, _ := f.Object()
 | 
						role := &rbac.Role{}
 | 
				
			||||||
	dryRun, outputFormat := cmdutil.GetDryRunFlag(cmd), cmdutil.GetFlagString(cmd, "output")
 | 
						role.Name = c.Name
 | 
				
			||||||
 | 
						rules, err := generateResourcePolicyRules(c.Mapper, c.Verbs, c.Resources, c.ResourceNames)
 | 
				
			||||||
	// groupResourceMapping is a apigroup-resource map. The key of this map is api group, while the value
 | 
					 | 
				
			||||||
	// is a string array of resources under this api group.
 | 
					 | 
				
			||||||
	// E.g.  groupResourceMapping = {"extensions": ["replicasets", "deployments"], "batch":["jobs"]}
 | 
					 | 
				
			||||||
	groupResourceMapping := map[string][]string{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// This loop does the following work:
 | 
					 | 
				
			||||||
	// 1. Constructs groupResourceMapping based on input resources.
 | 
					 | 
				
			||||||
	// 2. Prevents pointing to non-existent resources.
 | 
					 | 
				
			||||||
	// 3. Transfers resource short name to long name. E.g. rs.extensions is transferred to replicasets.extensions
 | 
					 | 
				
			||||||
	for _, r := range c.Resources {
 | 
					 | 
				
			||||||
		resource, err := mapper.ResourceFor(r)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
		if !arrayContains(groupResourceMapping[resource.Group], resource.Resource) {
 | 
					 | 
				
			||||||
			groupResourceMapping[resource.Group] = append(groupResourceMapping[resource.Group], resource.Resource)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	role := &rbac.Role{}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Create separate rule for each of the api group.
 | 
					 | 
				
			||||||
	rules := []rbac.PolicyRule{}
 | 
					 | 
				
			||||||
	for _, g := range sets.StringKeySet(groupResourceMapping).List() {
 | 
					 | 
				
			||||||
		rule := rbac.PolicyRule{}
 | 
					 | 
				
			||||||
		rule.Verbs = c.Verbs
 | 
					 | 
				
			||||||
		rule.Resources = groupResourceMapping[g]
 | 
					 | 
				
			||||||
		rule.APIGroups = []string{g}
 | 
					 | 
				
			||||||
		rule.ResourceNames = c.ResourceNames
 | 
					 | 
				
			||||||
		rules = append(rules, rule)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	role.Name = c.Name
 | 
					 | 
				
			||||||
	role.Rules = rules
 | 
						role.Rules = rules
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Create role.
 | 
						// Create role.
 | 
				
			||||||
	namespace, _, err := f.DefaultNamespace()
 | 
						if !c.DryRun {
 | 
				
			||||||
	if err != nil {
 | 
							_, err = c.Client.Roles(c.Namespace).Create(role)
 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if !dryRun {
 | 
					 | 
				
			||||||
		client, err := f.ClientSet()
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		_, err = client.Rbac().Roles(namespace).Create(role)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if useShortOutput := outputFormat == "name"; useShortOutput || len(outputFormat) == 0 {
 | 
						if useShortOutput := c.OutputFormat == "name"; useShortOutput || len(c.OutputFormat) == 0 {
 | 
				
			||||||
		cmdutil.PrintSuccess(mapper, useShortOutput, cmdOut, "roles", c.Name, dryRun, "created")
 | 
							cmdutil.PrintSuccess(c.Mapper, useShortOutput, c.Out, "roles", c.Name, c.DryRun, "created")
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return f.PrintObject(cmd, mapper, role, cmdOut)
 | 
						return c.PrintObject(role)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func arrayContains(s []string, e string) bool {
 | 
					func arrayContains(s []string, e string) bool {
 | 
				
			||||||
@@ -232,3 +226,37 @@ func arrayContains(s []string, e string) bool {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return false
 | 
						return false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func generateResourcePolicyRules(mapper meta.RESTMapper, verbs []string, resources []schema.GroupVersionResource, resourceNames []string) ([]rbac.PolicyRule, error) {
 | 
				
			||||||
 | 
						// groupResourceMapping is a apigroup-resource map. The key of this map is api group, while the value
 | 
				
			||||||
 | 
						// is a string array of resources under this api group.
 | 
				
			||||||
 | 
						// E.g.  groupResourceMapping = {"extensions": ["replicasets", "deployments"], "batch":["jobs"]}
 | 
				
			||||||
 | 
						groupResourceMapping := map[string][]string{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// This loop does the following work:
 | 
				
			||||||
 | 
						// 1. Constructs groupResourceMapping based on input resources.
 | 
				
			||||||
 | 
						// 2. Prevents pointing to non-existent resources.
 | 
				
			||||||
 | 
						// 3. Transfers resource short name to long name. E.g. rs.extensions is transferred to replicasets.extensions
 | 
				
			||||||
 | 
						for _, r := range resources {
 | 
				
			||||||
 | 
							resource, err := mapper.ResourceFor(r)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return []rbac.PolicyRule{}, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if !arrayContains(groupResourceMapping[resource.Group], resource.Resource) {
 | 
				
			||||||
 | 
								groupResourceMapping[resource.Group] = append(groupResourceMapping[resource.Group], resource.Resource)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Create separate rule for each of the api group.
 | 
				
			||||||
 | 
						rules := []rbac.PolicyRule{}
 | 
				
			||||||
 | 
						for _, g := range sets.StringKeySet(groupResourceMapping).List() {
 | 
				
			||||||
 | 
							rule := rbac.PolicyRule{}
 | 
				
			||||||
 | 
							rule.Verbs = verbs
 | 
				
			||||||
 | 
							rule.Resources = groupResourceMapping[g]
 | 
				
			||||||
 | 
							rule.APIGroups = []string{g}
 | 
				
			||||||
 | 
							rule.ResourceNames = resourceNames
 | 
				
			||||||
 | 
							rules = append(rules, rule)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return rules, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,6 +25,7 @@ import (
 | 
				
			|||||||
	"k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						"k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/runtime"
 | 
						"k8s.io/apimachinery/pkg/runtime"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/runtime/schema"
 | 
						"k8s.io/apimachinery/pkg/runtime/schema"
 | 
				
			||||||
 | 
						"k8s.io/client-go/rest/fake"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/apis/rbac"
 | 
						"k8s.io/kubernetes/pkg/apis/rbac"
 | 
				
			||||||
	cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
 | 
						cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -53,6 +54,8 @@ func TestCreateRole(t *testing.T) {
 | 
				
			|||||||
	printer := &testRolePrinter{}
 | 
						printer := &testRolePrinter{}
 | 
				
			||||||
	tf.Printer = printer
 | 
						tf.Printer = printer
 | 
				
			||||||
	tf.Namespace = "test"
 | 
						tf.Namespace = "test"
 | 
				
			||||||
 | 
						tf.Client = &fake.RESTClient{}
 | 
				
			||||||
 | 
						tf.ClientConfig = defaultClientConfig()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tests := map[string]struct {
 | 
						tests := map[string]struct {
 | 
				
			||||||
		verbs         string
 | 
							verbs         string
 | 
				
			||||||
@@ -214,7 +217,8 @@ func TestValidate(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for name, test := range tests {
 | 
						for name, test := range tests {
 | 
				
			||||||
		err := test.roleOptions.Validate(f)
 | 
							test.roleOptions.Mapper, _ = f.Object()
 | 
				
			||||||
 | 
							err := test.roleOptions.Validate()
 | 
				
			||||||
		if test.expectErr && err != nil {
 | 
							if test.expectErr && err != nil {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -230,6 +234,8 @@ func TestComplete(t *testing.T) {
 | 
				
			|||||||
	f, tf, _, _ := cmdtesting.NewAPIFactory()
 | 
						f, tf, _, _ := cmdtesting.NewAPIFactory()
 | 
				
			||||||
	tf.Printer = &testPrinter{}
 | 
						tf.Printer = &testPrinter{}
 | 
				
			||||||
	tf.Namespace = "test"
 | 
						tf.Namespace = "test"
 | 
				
			||||||
 | 
						tf.Client = &fake.RESTClient{}
 | 
				
			||||||
 | 
						tf.ClientConfig = defaultClientConfig()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	buf := bytes.NewBuffer([]byte{})
 | 
						buf := bytes.NewBuffer([]byte{})
 | 
				
			||||||
	cmd := NewCmdCreateRole(f, buf)
 | 
						cmd := NewCmdCreateRole(f, buf)
 | 
				
			||||||
@@ -357,15 +363,28 @@ func TestComplete(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for name, test := range tests {
 | 
						for name, test := range tests {
 | 
				
			||||||
		err := test.roleOptions.Complete(cmd, test.params)
 | 
							err := test.roleOptions.Complete(f, cmd, test.params)
 | 
				
			||||||
		if !test.expectErr && err != nil {
 | 
							if !test.expectErr && err != nil {
 | 
				
			||||||
			t.Errorf("%s: unexpected error: %v", name, err)
 | 
								t.Errorf("%s: unexpected error: %v", name, err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if test.expectErr && err != nil {
 | 
							if test.expectErr && err != nil {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if !reflect.DeepEqual(test.roleOptions, test.expected) {
 | 
					
 | 
				
			||||||
			t.Errorf("%s:\nexpected:\n%#v\nsaw:\n%#v", name, test.expected, test.roleOptions)
 | 
							if test.roleOptions.Name != test.expected.Name {
 | 
				
			||||||
 | 
								t.Errorf("%s:\nexpected name:\n%#v\nsaw name:\n%#v", name, test.expected.Name, test.roleOptions.Name)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if !reflect.DeepEqual(test.roleOptions.Verbs, test.expected.Verbs) {
 | 
				
			||||||
 | 
								t.Errorf("%s:\nexpected verbs:\n%#v\nsaw verbs:\n%#v", name, test.expected.Verbs, test.roleOptions.Verbs)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if !reflect.DeepEqual(test.roleOptions.Resources, test.expected.Resources) {
 | 
				
			||||||
 | 
								t.Errorf("%s:\nexpected resources:\n%#v\nsaw resources:\n%#v", name, test.expected.Resources, test.roleOptions.Resources)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if !reflect.DeepEqual(test.roleOptions.ResourceNames, test.expected.ResourceNames) {
 | 
				
			||||||
 | 
								t.Errorf("%s:\nexpected resource names:\n%#v\nsaw resource names:\n%#v", name, test.expected.ResourceNames, test.roleOptions.ResourceNames)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user