Commit 433941f1 authored by Xing Zhou's avatar Xing Zhou

Added `kubectl create clusterrole` command.

Added `kubectl create clusterrole` command.
parent 98d693e9
...@@ -37,6 +37,7 @@ docs/man/man1/kubectl-config.1 ...@@ -37,6 +37,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
...@@ -122,6 +123,7 @@ docs/user-guide/kubectl/kubectl_convert.md ...@@ -122,6 +123,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
......
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.
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() { ...@@ -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
......
...@@ -24,6 +24,7 @@ go_library( ...@@ -24,6 +24,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",
...@@ -74,6 +75,7 @@ go_library( ...@@ -74,6 +75,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",
...@@ -141,6 +143,7 @@ go_test( ...@@ -141,6 +143,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 { ...@@ -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))
......
/*
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)
}
/*
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 ( ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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,10 +193,41 @@ func (c *CreateRoleOptions) Validate(f cmdutil.Factory) error { ...@@ -161,10 +193,41 @@ 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)
if err != nil {
return err
}
role.Rules = rules
// Create role.
if !c.DryRun {
_, err = c.Client.Roles(c.Namespace).Create(role)
if err != nil {
return err
}
}
if useShortOutput := c.OutputFormat == "name"; useShortOutput || len(c.OutputFormat) == 0 {
cmdutil.PrintSuccess(c.Mapper, useShortOutput, c.Out, "roles", c.Name, c.DryRun, "created")
return nil
}
return c.PrintObject(role)
}
func arrayContains(s []string, e string) bool {
for _, a := range s {
if a == e {
return true
}
}
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 // 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. // is a string array of resources under this api group.
// E.g. groupResourceMapping = {"extensions": ["replicasets", "deployments"], "batch":["jobs"]} // E.g. groupResourceMapping = {"extensions": ["replicasets", "deployments"], "batch":["jobs"]}
...@@ -174,61 +237,26 @@ func (c *CreateRoleOptions) RunCreateRole(f cmdutil.Factory, cmdOut io.Writer, c ...@@ -174,61 +237,26 @@ func (c *CreateRoleOptions) RunCreateRole(f cmdutil.Factory, cmdOut io.Writer, c
// 1. Constructs groupResourceMapping based on input resources. // 1. Constructs groupResourceMapping based on input resources.
// 2. Prevents pointing to non-existent 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 // 3. Transfers resource short name to long name. E.g. rs.extensions is transferred to replicasets.extensions
for _, r := range c.Resources { for _, r := range resources {
resource, err := mapper.ResourceFor(r) resource, err := mapper.ResourceFor(r)
if err != nil { if err != nil {
return err return []rbac.PolicyRule{}, err
} }
if !arrayContains(groupResourceMapping[resource.Group], resource.Resource) { if !arrayContains(groupResourceMapping[resource.Group], resource.Resource) {
groupResourceMapping[resource.Group] = append(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. // Create separate rule for each of the api group.
rules := []rbac.PolicyRule{} rules := []rbac.PolicyRule{}
for _, g := range sets.StringKeySet(groupResourceMapping).List() { for _, g := range sets.StringKeySet(groupResourceMapping).List() {
rule := rbac.PolicyRule{} rule := rbac.PolicyRule{}
rule.Verbs = c.Verbs rule.Verbs = verbs
rule.Resources = groupResourceMapping[g] rule.Resources = groupResourceMapping[g]
rule.APIGroups = []string{g} rule.APIGroups = []string{g}
rule.ResourceNames = c.ResourceNames rule.ResourceNames = resourceNames
rules = append(rules, rule) rules = append(rules, rule)
} }
role.Name = c.Name
role.Rules = rules
// Create role.
namespace, _, err := f.DefaultNamespace()
if err != nil {
return err
}
if !dryRun {
client, err := f.ClientSet()
if err != nil {
return err
}
_, err = client.Rbac().Roles(namespace).Create(role)
if err != nil {
return err
}
}
if useShortOutput := outputFormat == "name"; useShortOutput || len(outputFormat) == 0 {
cmdutil.PrintSuccess(mapper, useShortOutput, cmdOut, "roles", c.Name, dryRun, "created")
return nil
}
return f.PrintObject(cmd, mapper, role, cmdOut) return rules, nil
}
func arrayContains(s []string, e string) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
} }
...@@ -25,6 +25,7 @@ import ( ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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)
} }
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment