2017-02-15 07:38:13 +00:00
/ *
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 (
2017-05-15 06:04:29 +00:00
"fmt"
2017-02-15 07:38:13 +00:00
"io"
2017-06-07 06:04:17 +00:00
"strings"
2017-02-15 07:38:13 +00:00
"github.com/spf13/cobra"
2017-10-28 01:31:42 +00:00
rbacv1 "k8s.io/api/rbac/v1"
2017-02-15 07:38:13 +00:00
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
2017-07-07 04:04:11 +00:00
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
2017-02-15 07:38:13 +00:00
)
var (
2017-03-15 03:49:10 +00:00
clusterRoleLong = templates . LongDesc ( i18n . T ( `
Create a ClusterRole . ` ) )
2017-02-15 07:38:13 +00:00
2017-03-15 03:49:10 +00:00
clusterRoleExample = templates . Examples ( i18n . T ( `
2017-02-15 07:38:13 +00:00
# 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
2017-04-26 09:55:16 +00:00
kubectl create clusterrole pod - reader -- verb = get , list , watch -- resource = pods -- resource - name = readablepod -- resource - name = anotherpod
2017-02-14 06:53:42 +00:00
# Create a ClusterRole named "foo" with API Group specified
kubectl create clusterrole foo -- verb = get , list , watch -- resource = rs . extensions
# Create a ClusterRole named "foo" with SubResource specified
2017-05-15 06:04:29 +00:00
kubectl create clusterrole foo -- verb = get , list , watch -- resource = pods , pods / status
# Create a ClusterRole name "foo" with NonResourceURL specified
kubectl create clusterrole "foo" -- verb = get -- non - resource - url = / logs / * ` ) )
// Valid nonResource verb list for validation.
validNonResourceVerbs = [ ] string { "*" , "get" , "post" , "put" , "delete" , "patch" , "head" , "options" }
2017-02-15 07:38:13 +00:00
)
type CreateClusterRoleOptions struct {
* CreateRoleOptions
2017-05-15 06:04:29 +00:00
NonResourceURLs [ ] string
2017-02-15 07:38:13 +00:00
}
// 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 {
2017-10-11 06:26:02 +00:00
Use : "clusterrole NAME --verb=verb --resource=resource.group [--resource-name=resourcename] [--dry-run]" ,
DisableFlagsInUseLine : true ,
2017-02-15 07:38:13 +00:00
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 )
2017-08-02 15:41:19 +00:00
cmd . Flags ( ) . StringSliceVar ( & c . Verbs , "verb" , [ ] string { } , "Verb that applies to the resources contained in the rule" )
cmd . Flags ( ) . StringSliceVar ( & c . NonResourceURLs , "non-resource-url" , [ ] string { } , "A partial url that user should have access to." )
cmd . Flags ( ) . StringSlice ( "resource" , [ ] string { } , "Resource that the rule applies to" )
cmd . Flags ( ) . StringArrayVar ( & c . ResourceNames , "resource-name" , [ ] string { } , "Resource in the white list that the rule applies to, repeat this flag for multiple items" )
2017-02-15 07:38:13 +00:00
return cmd
}
2017-05-15 06:04:29 +00:00
func ( c * CreateClusterRoleOptions ) Complete ( f cmdutil . Factory , cmd * cobra . Command , args [ ] string ) error {
// Remove duplicate nonResourceURLs
nonResourceURLs := [ ] string { }
for _ , n := range c . NonResourceURLs {
if ! arrayContains ( nonResourceURLs , n ) {
nonResourceURLs = append ( nonResourceURLs , n )
}
}
c . NonResourceURLs = nonResourceURLs
return c . CreateRoleOptions . Complete ( f , cmd , args )
}
func ( c * CreateClusterRoleOptions ) Validate ( ) error {
if c . Name == "" {
return fmt . Errorf ( "name must be specified" )
}
// validate verbs.
if len ( c . Verbs ) == 0 {
return fmt . Errorf ( "at least one verb must be specified" )
}
if len ( c . Resources ) == 0 && len ( c . NonResourceURLs ) == 0 {
return fmt . Errorf ( "one of resource or nonResourceURL must be specified" )
}
// validate resources
if len ( c . Resources ) > 0 {
for _ , v := range c . Verbs {
if ! arrayContains ( validResourceVerbs , v ) {
return fmt . Errorf ( "invalid verb: '%s'" , v )
}
}
if err := c . validateResource ( ) ; err != nil {
return err
}
}
//validate non-resource-url
if len ( c . NonResourceURLs ) > 0 {
for _ , v := range c . Verbs {
if ! arrayContains ( validNonResourceVerbs , v ) {
return fmt . Errorf ( "invalid verb: '%s' for nonResourceURL" , v )
}
}
2017-06-07 06:04:17 +00:00
for _ , nonResourceURL := range c . NonResourceURLs {
if nonResourceURL == "*" {
continue
}
if nonResourceURL == "" || ! strings . HasPrefix ( nonResourceURL , "/" ) {
return fmt . Errorf ( "nonResourceURL should start with /" )
}
if strings . ContainsRune ( nonResourceURL [ : len ( nonResourceURL ) - 1 ] , '*' ) {
return fmt . Errorf ( "nonResourceURL only supports wildcard matches when '*' is at the end" )
}
}
2017-05-15 06:04:29 +00:00
}
return nil
}
2017-02-15 07:38:13 +00:00
func ( c * CreateClusterRoleOptions ) RunCreateRole ( ) error {
2017-10-28 01:31:42 +00:00
clusterRole := & rbacv1 . ClusterRole { }
2017-02-15 07:38:13 +00:00
clusterRole . Name = c . Name
2017-05-15 06:04:29 +00:00
rules , err := generateResourcePolicyRules ( c . Mapper , c . Verbs , c . Resources , c . ResourceNames , c . NonResourceURLs )
2017-02-15 07:38:13 +00:00
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 {
2017-10-31 15:58:38 +00:00
c . PrintSuccess ( c . Mapper , useShortOutput , c . Out , "clusterroles" , c . Name , c . DryRun , "created" )
2017-02-15 07:38:13 +00:00
return nil
}
return c . PrintObject ( clusterRole )
}