...

Source file src/k8s.io/kubectl/pkg/cmd/create/create_clusterrolebinding.go

Documentation: k8s.io/kubectl/pkg/cmd/create

     1  /*
     2  Copyright 2016 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package create
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"strings"
    23  
    24  	"github.com/spf13/cobra"
    25  
    26  	rbacv1 "k8s.io/api/rbac/v1"
    27  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    28  	"k8s.io/apimachinery/pkg/runtime"
    29  	"k8s.io/cli-runtime/pkg/genericclioptions"
    30  	"k8s.io/cli-runtime/pkg/genericiooptions"
    31  	rbacclientv1 "k8s.io/client-go/kubernetes/typed/rbac/v1"
    32  	cmdutil "k8s.io/kubectl/pkg/cmd/util"
    33  	"k8s.io/kubectl/pkg/scheme"
    34  	"k8s.io/kubectl/pkg/util"
    35  	"k8s.io/kubectl/pkg/util/completion"
    36  	"k8s.io/kubectl/pkg/util/i18n"
    37  	"k8s.io/kubectl/pkg/util/templates"
    38  )
    39  
    40  var (
    41  	clusterRoleBindingLong = templates.LongDesc(i18n.T(`
    42  		Create a cluster role binding for a particular cluster role.`))
    43  
    44  	clusterRoleBindingExample = templates.Examples(i18n.T(`
    45  		  # Create a cluster role binding for user1, user2, and group1 using the cluster-admin cluster role
    46  		  kubectl create clusterrolebinding cluster-admin --clusterrole=cluster-admin --user=user1 --user=user2 --group=group1`))
    47  )
    48  
    49  // ClusterRoleBindingOptions is returned by NewCmdCreateClusterRoleBinding
    50  type ClusterRoleBindingOptions struct {
    51  	PrintFlags *genericclioptions.PrintFlags
    52  	PrintObj   func(obj runtime.Object) error
    53  
    54  	Name             string
    55  	ClusterRole      string
    56  	Users            []string
    57  	Groups           []string
    58  	ServiceAccounts  []string
    59  	FieldManager     string
    60  	CreateAnnotation bool
    61  
    62  	Client              rbacclientv1.RbacV1Interface
    63  	DryRunStrategy      cmdutil.DryRunStrategy
    64  	ValidationDirective string
    65  
    66  	genericiooptions.IOStreams
    67  }
    68  
    69  // NewClusterRoleBindingOptions creates a new *ClusterRoleBindingOptions with sane defaults
    70  func NewClusterRoleBindingOptions(ioStreams genericiooptions.IOStreams) *ClusterRoleBindingOptions {
    71  	return &ClusterRoleBindingOptions{
    72  		Users:           []string{},
    73  		Groups:          []string{},
    74  		ServiceAccounts: []string{},
    75  		PrintFlags:      genericclioptions.NewPrintFlags("created").WithTypeSetter(scheme.Scheme),
    76  		IOStreams:       ioStreams,
    77  	}
    78  }
    79  
    80  // NewCmdCreateClusterRoleBinding returns an initialized command instance of ClusterRoleBinding
    81  func NewCmdCreateClusterRoleBinding(f cmdutil.Factory, ioStreams genericiooptions.IOStreams) *cobra.Command {
    82  	o := NewClusterRoleBindingOptions(ioStreams)
    83  
    84  	cmd := &cobra.Command{
    85  		Use:                   "clusterrolebinding NAME --clusterrole=NAME [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run=server|client|none]",
    86  		DisableFlagsInUseLine: true,
    87  		Short:                 i18n.T("Create a cluster role binding for a particular cluster role"),
    88  		Long:                  clusterRoleBindingLong,
    89  		Example:               clusterRoleBindingExample,
    90  		Run: func(cmd *cobra.Command, args []string) {
    91  			cmdutil.CheckErr(o.Complete(f, cmd, args))
    92  			cmdutil.CheckErr(o.Run())
    93  		},
    94  	}
    95  
    96  	o.PrintFlags.AddFlags(cmd)
    97  
    98  	cmdutil.AddApplyAnnotationFlags(cmd)
    99  	cmdutil.AddValidateFlags(cmd)
   100  	cmdutil.AddDryRunFlag(cmd)
   101  	cmd.Flags().StringVar(&o.ClusterRole, "clusterrole", "", i18n.T("ClusterRole this ClusterRoleBinding should reference"))
   102  	cmd.MarkFlagRequired("clusterrole")
   103  	cmd.Flags().StringArrayVar(&o.Users, "user", o.Users, "Usernames to bind to the clusterrole. The flag can be repeated to add multiple users.")
   104  	cmd.Flags().StringArrayVar(&o.Groups, "group", o.Groups, "Groups to bind to the clusterrole. The flag can be repeated to add multiple groups.")
   105  	cmd.Flags().StringArrayVar(&o.ServiceAccounts, "serviceaccount", o.ServiceAccounts, "Service accounts to bind to the clusterrole, in the format <namespace>:<name>. The flag can be repeated to add multiple service accounts.")
   106  	cmdutil.AddFieldManagerFlagVar(cmd, &o.FieldManager, "kubectl-create")
   107  
   108  	// Completion for relevant flags
   109  	cmdutil.CheckErr(cmd.RegisterFlagCompletionFunc(
   110  		"clusterrole",
   111  		func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
   112  			return completion.CompGetResource(f, "clusterrole", toComplete), cobra.ShellCompDirectiveNoFileComp
   113  		}))
   114  
   115  	return cmd
   116  }
   117  
   118  // Complete completes all the required options
   119  func (o *ClusterRoleBindingOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
   120  	var err error
   121  	o.Name, err = NameFromCommandArgs(cmd, args)
   122  	if err != nil {
   123  		return err
   124  	}
   125  
   126  	cs, err := f.KubernetesClientSet()
   127  	if err != nil {
   128  		return err
   129  	}
   130  	o.Client = cs.RbacV1()
   131  
   132  	o.CreateAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag)
   133  
   134  	o.DryRunStrategy, err = cmdutil.GetDryRunStrategy(cmd)
   135  	if err != nil {
   136  		return err
   137  	}
   138  	cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
   139  
   140  	printer, err := o.PrintFlags.ToPrinter()
   141  	if err != nil {
   142  		return err
   143  	}
   144  	o.PrintObj = func(obj runtime.Object) error {
   145  		return printer.PrintObj(obj, o.Out)
   146  	}
   147  	o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
   148  	if err != nil {
   149  		return err
   150  	}
   151  
   152  	return nil
   153  }
   154  
   155  // Run calls the CreateSubcommandOptions.Run in ClusterRoleBindingOptions instance
   156  func (o *ClusterRoleBindingOptions) Run() error {
   157  	clusterRoleBinding, err := o.createClusterRoleBinding()
   158  	if err != nil {
   159  		return err
   160  	}
   161  
   162  	if err := util.CreateOrUpdateAnnotation(o.CreateAnnotation, clusterRoleBinding, scheme.DefaultJSONEncoder()); err != nil {
   163  		return err
   164  	}
   165  
   166  	if o.DryRunStrategy != cmdutil.DryRunClient {
   167  		createOptions := metav1.CreateOptions{}
   168  		if o.FieldManager != "" {
   169  			createOptions.FieldManager = o.FieldManager
   170  		}
   171  		createOptions.FieldValidation = o.ValidationDirective
   172  		if o.DryRunStrategy == cmdutil.DryRunServer {
   173  			createOptions.DryRun = []string{metav1.DryRunAll}
   174  		}
   175  		var err error
   176  		clusterRoleBinding, err = o.Client.ClusterRoleBindings().Create(context.TODO(), clusterRoleBinding, createOptions)
   177  		if err != nil {
   178  			return fmt.Errorf("failed to create clusterrolebinding: %v", err)
   179  		}
   180  	}
   181  
   182  	return o.PrintObj(clusterRoleBinding)
   183  }
   184  
   185  func (o *ClusterRoleBindingOptions) createClusterRoleBinding() (*rbacv1.ClusterRoleBinding, error) {
   186  	clusterRoleBinding := &rbacv1.ClusterRoleBinding{
   187  		TypeMeta: metav1.TypeMeta{APIVersion: rbacv1.SchemeGroupVersion.String(), Kind: "ClusterRoleBinding"},
   188  		ObjectMeta: metav1.ObjectMeta{
   189  			Name: o.Name,
   190  		},
   191  		RoleRef: rbacv1.RoleRef{
   192  			APIGroup: rbacv1.GroupName,
   193  			Kind:     "ClusterRole",
   194  			Name:     o.ClusterRole,
   195  		},
   196  	}
   197  
   198  	for _, user := range o.Users {
   199  		clusterRoleBinding.Subjects = append(clusterRoleBinding.Subjects, rbacv1.Subject{
   200  			Kind:     rbacv1.UserKind,
   201  			APIGroup: rbacv1.GroupName,
   202  			Name:     user,
   203  		})
   204  	}
   205  
   206  	for _, group := range o.Groups {
   207  		clusterRoleBinding.Subjects = append(clusterRoleBinding.Subjects, rbacv1.Subject{
   208  			Kind:     rbacv1.GroupKind,
   209  			APIGroup: rbacv1.GroupName,
   210  			Name:     group,
   211  		})
   212  	}
   213  
   214  	for _, sa := range o.ServiceAccounts {
   215  		tokens := strings.Split(sa, ":")
   216  		if len(tokens) != 2 || tokens[0] == "" || tokens[1] == "" {
   217  			return nil, fmt.Errorf("serviceaccount must be <namespace>:<name>")
   218  		}
   219  		clusterRoleBinding.Subjects = append(clusterRoleBinding.Subjects, rbacv1.Subject{
   220  			Kind:      rbacv1.ServiceAccountKind,
   221  			APIGroup:  "",
   222  			Namespace: tokens[0],
   223  			Name:      tokens[1],
   224  		})
   225  	}
   226  
   227  	return clusterRoleBinding, nil
   228  }
   229  

View as plain text