support NonResourceURL for kubectl create clusterrole

This commit is contained in:
Cao Shufeng
2017-05-15 14:04:29 +08:00
parent 749ac27e9a
commit 93e50b167e
4 changed files with 80 additions and 5 deletions

View File

@@ -17,6 +17,7 @@ limitations under the License.
package cmd
import (
"fmt"
"io"
"github.com/spf13/cobra"
@@ -42,11 +43,18 @@ var (
kubectl create clusterrole foo --verb=get,list,watch --resource=rs.extensions
# Create a ClusterRole named "foo" with SubResource specified
kubectl create clusterrole foo --verb=get,list,watch --resource=pods,pods/status`))
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"}
)
type CreateClusterRoleOptions struct {
*CreateRoleOptions
NonResourceURLs []string
}
// ClusterRole is a command to ease creating ClusterRoles.
@@ -72,16 +80,69 @@ func NewCmdCreateClusterRole(f cmdutil.Factory, cmdOut io.Writer) *cobra.Command
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().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")
return cmd
}
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)
}
}
}
return nil
}
func (c *CreateClusterRoleOptions) RunCreateRole() error {
clusterRole := &rbac.ClusterRole{}
clusterRole.Name = c.Name
rules, err := generateResourcePolicyRules(c.Mapper, c.Verbs, c.Resources, c.ResourceNames)
rules, err := generateResourcePolicyRules(c.Mapper, c.Verbs, c.Resources, c.ResourceNames, c.NonResourceURLs)
if err != nil {
return err
}