From e300f01a1bc8771d610f8568e0799527e72826b9 Mon Sep 17 00:00:00 2001 From: deads2k Date: Fri, 18 Nov 2016 11:23:59 -0500 Subject: [PATCH] add create clusterrolebinding command --- .generated_docs | 2 + .../man1/kubectl-create-clusterrolebinding.1 | 3 + .../kubectl_create_clusterrolebinding.md | 7 + hack/make-rules/test-cmd.sh | 2 + pkg/kubectl/BUILD | 1 + pkg/kubectl/clusterrolebinding.go | 132 ++++++++++++++++++ pkg/kubectl/cmd/BUILD | 1 + pkg/kubectl/cmd/create.go | 1 + pkg/kubectl/cmd/create_clusterrolebinding.go | 86 ++++++++++++ pkg/kubectl/cmd/util/factory.go | 1 + 10 files changed, 236 insertions(+) create mode 100644 docs/man/man1/kubectl-create-clusterrolebinding.1 create mode 100644 docs/user-guide/kubectl/kubectl_create_clusterrolebinding.md create mode 100644 pkg/kubectl/clusterrolebinding.go create mode 100644 pkg/kubectl/cmd/create_clusterrolebinding.go diff --git a/.generated_docs b/.generated_docs index 354466cea2b..19ec6a5c755 100644 --- a/.generated_docs +++ b/.generated_docs @@ -37,6 +37,7 @@ docs/man/man1/kubectl-config.1 docs/man/man1/kubectl-convert.1 docs/man/man1/kubectl-cordon.1 docs/man/man1/kubectl-cp.1 +docs/man/man1/kubectl-create-clusterrolebinding.1 docs/man/man1/kubectl-create-configmap.1 docs/man/man1/kubectl-create-deployment.1 docs/man/man1/kubectl-create-namespace.1 @@ -116,6 +117,7 @@ docs/user-guide/kubectl/kubectl_convert.md docs/user-guide/kubectl/kubectl_cordon.md docs/user-guide/kubectl/kubectl_cp.md docs/user-guide/kubectl/kubectl_create.md +docs/user-guide/kubectl/kubectl_create_clusterrolebinding.md docs/user-guide/kubectl/kubectl_create_configmap.md docs/user-guide/kubectl/kubectl_create_deployment.md docs/user-guide/kubectl/kubectl_create_namespace.md diff --git a/docs/man/man1/kubectl-create-clusterrolebinding.1 b/docs/man/man1/kubectl-create-clusterrolebinding.1 new file mode 100644 index 00000000000..b6fd7a0f989 --- /dev/null +++ b/docs/man/man1/kubectl-create-clusterrolebinding.1 @@ -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. diff --git a/docs/user-guide/kubectl/kubectl_create_clusterrolebinding.md b/docs/user-guide/kubectl/kubectl_create_clusterrolebinding.md new file mode 100644 index 00000000000..1dd11fc7264 --- /dev/null +++ b/docs/user-guide/kubectl/kubectl_create_clusterrolebinding.md @@ -0,0 +1,7 @@ +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. + + +[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/user-guide/kubectl/kubectl_create_clusterrolebinding.md?pixel)]() + diff --git a/hack/make-rules/test-cmd.sh b/hack/make-rules/test-cmd.sh index 893225e38e4..8a33a5c91a5 100755 --- a/hack/make-rules/test-cmd.sh +++ b/hack/make-rules/test-cmd.sh @@ -422,6 +422,8 @@ runTests() { # 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 clusterrolebindings/cluster-admin "{{.metadata.name}}" 'cluster-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:' ########################### # POD creation / deletion # diff --git a/pkg/kubectl/BUILD b/pkg/kubectl/BUILD index cc112dd3ef0..dacb8ec90f7 100644 --- a/pkg/kubectl/BUILD +++ b/pkg/kubectl/BUILD @@ -17,6 +17,7 @@ go_library( "autoscale.go", "bash_comp_utils.go", "cluster.go", + "clusterrolebinding.go", "configmap.go", "custom_column_printer.go", "deployment.go", diff --git a/pkg/kubectl/clusterrolebinding.go b/pkg/kubectl/clusterrolebinding.go new file mode 100644 index 00000000000..cf2708f3214 --- /dev/null +++ b/pkg/kubectl/clusterrolebinding.go @@ -0,0 +1,132 @@ +/* +Copyright 2016 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 kubectl + +import ( + "fmt" + + "k8s.io/kubernetes/pkg/apis/rbac" + "k8s.io/kubernetes/pkg/runtime" +) + +// ClusterRoleBindingGeneratorV1 supports stable generation of a clusterRoleBinding. +type ClusterRoleBindingGeneratorV1 struct { + // Name of clusterRoleBinding (required) + Name string + // ClusterRole for the clusterRoleBinding (required) + ClusterRole string + // Users to derive the clusterRoleBinding from (optional) + Users []string + // Groups to derive the clusterRoleBinding from (optional) + Groups []string +} + +// Ensure it supports the generator pattern that uses parameter injection. +var _ Generator = &ClusterRoleBindingGeneratorV1{} + +// Ensure it supports the generator pattern that uses parameters specified during construction. +var _ StructuredGenerator = &ClusterRoleBindingGeneratorV1{} + +// Generate returns a clusterRoleBinding using the specified parameters. +func (s ClusterRoleBindingGeneratorV1) Generate(genericParams map[string]interface{}) (runtime.Object, error) { + err := ValidateParams(s.ParamNames(), genericParams) + if err != nil { + return nil, err + } + delegate := &ClusterRoleBindingGeneratorV1{} + fromFileStrings, found := genericParams["user"] + if found { + fromFileArray, isArray := fromFileStrings.([]string) + if !isArray { + return nil, fmt.Errorf("expected []string, found :%v", fromFileStrings) + } + delegate.Users = fromFileArray + delete(genericParams, "user") + } + fromLiteralStrings, found := genericParams["group"] + if found { + fromLiteralArray, isArray := fromLiteralStrings.([]string) + if !isArray { + return nil, fmt.Errorf("expected []string, found :%v", fromFileStrings) + } + delegate.Groups = fromLiteralArray + delete(genericParams, "group") + } + params := map[string]string{} + for key, value := range genericParams { + strVal, isString := value.(string) + if !isString { + return nil, fmt.Errorf("expected string, saw %v for '%s'", value, key) + } + params[key] = strVal + } + delegate.Name = params["name"] + delegate.ClusterRole = params["clusterrole"] + return delegate.StructuredGenerate() +} + +// ParamNames returns the set of supported input parameters when using the parameter injection generator pattern. +func (s ClusterRoleBindingGeneratorV1) ParamNames() []GeneratorParam { + return []GeneratorParam{ + {"name", true}, + {"clusterrole", false}, + {"user", false}, + {"group", false}, + {"force", false}, + } +} + +// StructuredGenerate outputs a clusterRoleBinding object using the configured fields. +func (s ClusterRoleBindingGeneratorV1) StructuredGenerate() (runtime.Object, error) { + if err := s.validate(); err != nil { + return nil, err + } + clusterRoleBinding := &rbac.ClusterRoleBinding{} + clusterRoleBinding.Name = s.Name + clusterRoleBinding.RoleRef = rbac.RoleRef{ + APIGroup: rbac.GroupName, + Kind: "ClusterRole", + Name: s.ClusterRole, + } + for _, user := range s.Users { + clusterRoleBinding.Subjects = append(clusterRoleBinding.Subjects, rbac.Subject{ + Kind: rbac.UserKind, + APIVersion: "rbac/v1alpha1", + Name: user, + }) + } + for _, group := range s.Groups { + clusterRoleBinding.Subjects = append(clusterRoleBinding.Subjects, rbac.Subject{ + Kind: rbac.GroupKind, + APIVersion: "rbac/v1alpha1", + Name: group, + }) + } + + return clusterRoleBinding, nil +} + +// validate validates required fields are set to support structured generation. +func (s ClusterRoleBindingGeneratorV1) validate() error { + if len(s.Name) == 0 { + return fmt.Errorf("name must be specified") + } + if len(s.ClusterRole) == 0 { + return fmt.Errorf("clusterrole must be specified") + } + return nil +} diff --git a/pkg/kubectl/cmd/BUILD b/pkg/kubectl/cmd/BUILD index f82463d870c..a29173fa81d 100644 --- a/pkg/kubectl/cmd/BUILD +++ b/pkg/kubectl/cmd/BUILD @@ -26,6 +26,7 @@ go_library( "convert.go", "cp.go", "create.go", + "create_clusterrolebinding.go", "create_configmap.go", "create_deployment.go", "create_namespace.go", diff --git a/pkg/kubectl/cmd/create.go b/pkg/kubectl/cmd/create.go index bc8f34ef6c1..7d03c0508ef 100644 --- a/pkg/kubectl/cmd/create.go +++ b/pkg/kubectl/cmd/create.go @@ -87,6 +87,7 @@ func NewCmdCreate(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { cmd.AddCommand(NewCmdCreateServiceAccount(f, out)) cmd.AddCommand(NewCmdCreateService(f, out, errOut)) cmd.AddCommand(NewCmdCreateDeployment(f, out)) + cmd.AddCommand(NewCmdCreateClusterRoleBinding(f, out)) return cmd } diff --git a/pkg/kubectl/cmd/create_clusterrolebinding.go b/pkg/kubectl/cmd/create_clusterrolebinding.go new file mode 100644 index 00000000000..0f185c28140 --- /dev/null +++ b/pkg/kubectl/cmd/create_clusterrolebinding.go @@ -0,0 +1,86 @@ +/* +Copyright 2016 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 ( + "fmt" + "io" + + "github.com/spf13/cobra" + + "k8s.io/kubernetes/pkg/kubectl" + "k8s.io/kubernetes/pkg/kubectl/cmd/templates" + cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" +) + +var ( + clusterRoleBindingLong = templates.LongDesc(` + Create a ClusterRoleBinding for a particular ClusterRole.`) + + clusterRoleBindingExample = templates.Examples(` + # Create a ClusterRoleBinding for user1, user2, and group1 using the cluster-admin ClusterRole + kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-admin --user=user1 --user=user2 --group=group1`) +) + +// ClusterRoleBinding is a command to ease creating ClusterRoleBindings. +func NewCmdCreateClusterRoleBinding(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command { + cmd := &cobra.Command{ + Use: "clusterrolebinding NAME --clusterrole=NAME [--user=username] [--group=groupname] [--dry-run]", + Aliases: []string{"cm"}, + Short: "Create a ClusterRoleBinding for a particular ClusterRole", + Long: clusterRoleBindingLong, + Example: clusterRoleBindingExample, + Run: func(cmd *cobra.Command, args []string) { + err := CreateClusterRoleBinding(f, cmdOut, cmd, args) + cmdutil.CheckErr(err) + }, + } + cmdutil.AddApplyAnnotationFlags(cmd) + cmdutil.AddValidateFlags(cmd) + cmdutil.AddPrinterFlags(cmd) + cmdutil.AddGeneratorFlags(cmd, cmdutil.ClusterRoleBindingV1GeneratorName) + cmd.Flags().String("clusterrole", "", "ClusterRole this ClusterRoleBinding should reference") + cmd.Flags().StringSlice("user", []string{}, "usernames to bind to the role") + cmd.Flags().StringSlice("group", []string{}, "groups to bind to the role") + return cmd +} + +// CreateClusterRoleBinding is the implementation of the create configmap command. +func CreateClusterRoleBinding(f cmdutil.Factory, cmdOut io.Writer, cmd *cobra.Command, args []string) error { + name, err := NameFromCommandArgs(cmd, args) + if err != nil { + return err + } + var generator kubectl.StructuredGenerator + switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName { + case cmdutil.ClusterRoleBindingV1GeneratorName: + generator = &kubectl.ClusterRoleBindingGeneratorV1{ + Name: name, + ClusterRole: cmdutil.GetFlagString(cmd, "clusterrole"), + Users: cmdutil.GetFlagStringSlice(cmd, "user"), + Groups: cmdutil.GetFlagStringSlice(cmd, "group"), + } + default: + return cmdutil.UsageError(cmd, fmt.Sprintf("Generator: %s not supported.", generatorName)) + } + return RunCreateSubcommand(f, cmd, cmdOut, &CreateSubcommandOptions{ + Name: name, + StructuredGenerator: generator, + DryRun: cmdutil.GetDryRunFlag(cmd), + OutputFormat: cmdutil.GetFlagString(cmd, "output"), + }) +} diff --git a/pkg/kubectl/cmd/util/factory.go b/pkg/kubectl/cmd/util/factory.go index bd5dc146140..e2766119f83 100644 --- a/pkg/kubectl/cmd/util/factory.go +++ b/pkg/kubectl/cmd/util/factory.go @@ -206,6 +206,7 @@ const ( SecretForDockerRegistryV1GeneratorName = "secret-for-docker-registry/v1" SecretForTLSV1GeneratorName = "secret-for-tls/v1" ConfigMapV1GeneratorName = "configmap/v1" + ClusterRoleBindingV1GeneratorName = "clusterrolebinding.rbac.authorization.k8s.io/v1alpha1" ClusterV1Beta1GeneratorName = "cluster/v1beta1" )