...

Source file src/k8s.io/kubernetes/pkg/apis/rbac/v1/helpers.go

Documentation: k8s.io/kubernetes/pkg/apis/rbac/v1

     1  /*
     2  Copyright 2017 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 v1
    18  
    19  import (
    20  	"fmt"
    21  
    22  	rbacv1 "k8s.io/api/rbac/v1"
    23  
    24  	"sort"
    25  
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  )
    28  
    29  // +k8s:deepcopy-gen=false
    30  
    31  // PolicyRuleBuilder let's us attach methods.  A no-no for API types.
    32  // We use it to construct rules in code.  It's more compact than trying to write them
    33  // out in a literal and allows us to perform some basic checking during construction
    34  type PolicyRuleBuilder struct {
    35  	PolicyRule rbacv1.PolicyRule `protobuf:"bytes,1,opt,name=policyRule"`
    36  }
    37  
    38  func NewRule(verbs ...string) *PolicyRuleBuilder {
    39  	return &PolicyRuleBuilder{
    40  		PolicyRule: rbacv1.PolicyRule{Verbs: verbs},
    41  	}
    42  }
    43  
    44  func (r *PolicyRuleBuilder) Groups(groups ...string) *PolicyRuleBuilder {
    45  	r.PolicyRule.APIGroups = append(r.PolicyRule.APIGroups, groups...)
    46  	return r
    47  }
    48  
    49  func (r *PolicyRuleBuilder) Resources(resources ...string) *PolicyRuleBuilder {
    50  	r.PolicyRule.Resources = append(r.PolicyRule.Resources, resources...)
    51  	return r
    52  }
    53  
    54  func (r *PolicyRuleBuilder) Names(names ...string) *PolicyRuleBuilder {
    55  	r.PolicyRule.ResourceNames = append(r.PolicyRule.ResourceNames, names...)
    56  	return r
    57  }
    58  
    59  func (r *PolicyRuleBuilder) URLs(urls ...string) *PolicyRuleBuilder {
    60  	r.PolicyRule.NonResourceURLs = append(r.PolicyRule.NonResourceURLs, urls...)
    61  	return r
    62  }
    63  
    64  func (r *PolicyRuleBuilder) RuleOrDie() rbacv1.PolicyRule {
    65  	ret, err := r.Rule()
    66  	if err != nil {
    67  		panic(err)
    68  	}
    69  	return ret
    70  }
    71  
    72  func (r *PolicyRuleBuilder) Rule() (rbacv1.PolicyRule, error) {
    73  	if len(r.PolicyRule.Verbs) == 0 {
    74  		return rbacv1.PolicyRule{}, fmt.Errorf("verbs are required: %#v", r.PolicyRule)
    75  	}
    76  
    77  	switch {
    78  	case len(r.PolicyRule.NonResourceURLs) > 0:
    79  		if len(r.PolicyRule.APIGroups) != 0 || len(r.PolicyRule.Resources) != 0 || len(r.PolicyRule.ResourceNames) != 0 {
    80  			return rbacv1.PolicyRule{}, fmt.Errorf("non-resource rule may not have apiGroups, resources, or resourceNames: %#v", r.PolicyRule)
    81  		}
    82  	case len(r.PolicyRule.Resources) > 0:
    83  		if len(r.PolicyRule.NonResourceURLs) != 0 {
    84  			return rbacv1.PolicyRule{}, fmt.Errorf("resource rule may not have nonResourceURLs: %#v", r.PolicyRule)
    85  		}
    86  		if len(r.PolicyRule.APIGroups) == 0 {
    87  			// this a common bug
    88  			return rbacv1.PolicyRule{}, fmt.Errorf("resource rule must have apiGroups: %#v", r.PolicyRule)
    89  		}
    90  	default:
    91  		return rbacv1.PolicyRule{}, fmt.Errorf("a rule must have either nonResourceURLs or resources: %#v", r.PolicyRule)
    92  	}
    93  
    94  	sort.Strings(r.PolicyRule.Resources)
    95  	sort.Strings(r.PolicyRule.ResourceNames)
    96  	sort.Strings(r.PolicyRule.APIGroups)
    97  	sort.Strings(r.PolicyRule.NonResourceURLs)
    98  	sort.Strings(r.PolicyRule.Verbs)
    99  	return r.PolicyRule, nil
   100  }
   101  
   102  // +k8s:deepcopy-gen=false
   103  
   104  // ClusterRoleBindingBuilder let's us attach methods.  A no-no for API types.
   105  // We use it to construct bindings in code.  It's more compact than trying to write them
   106  // out in a literal.
   107  type ClusterRoleBindingBuilder struct {
   108  	ClusterRoleBinding rbacv1.ClusterRoleBinding `protobuf:"bytes,1,opt,name=clusterRoleBinding"`
   109  }
   110  
   111  func NewClusterBinding(clusterRoleName string) *ClusterRoleBindingBuilder {
   112  	return &ClusterRoleBindingBuilder{
   113  		ClusterRoleBinding: rbacv1.ClusterRoleBinding{
   114  			ObjectMeta: metav1.ObjectMeta{Name: clusterRoleName},
   115  			RoleRef: rbacv1.RoleRef{
   116  				APIGroup: GroupName,
   117  				Kind:     "ClusterRole",
   118  				Name:     clusterRoleName,
   119  			},
   120  		},
   121  	}
   122  }
   123  
   124  func (r *ClusterRoleBindingBuilder) Groups(groups ...string) *ClusterRoleBindingBuilder {
   125  	for _, group := range groups {
   126  		r.ClusterRoleBinding.Subjects = append(r.ClusterRoleBinding.Subjects, rbacv1.Subject{APIGroup: rbacv1.GroupName, Kind: rbacv1.GroupKind, Name: group})
   127  	}
   128  	return r
   129  }
   130  
   131  func (r *ClusterRoleBindingBuilder) Users(users ...string) *ClusterRoleBindingBuilder {
   132  	for _, user := range users {
   133  		r.ClusterRoleBinding.Subjects = append(r.ClusterRoleBinding.Subjects, rbacv1.Subject{APIGroup: rbacv1.GroupName, Kind: rbacv1.UserKind, Name: user})
   134  	}
   135  	return r
   136  }
   137  
   138  func (r *ClusterRoleBindingBuilder) SAs(namespace string, serviceAccountNames ...string) *ClusterRoleBindingBuilder {
   139  	for _, saName := range serviceAccountNames {
   140  		r.ClusterRoleBinding.Subjects = append(r.ClusterRoleBinding.Subjects, rbacv1.Subject{Kind: rbacv1.ServiceAccountKind, Namespace: namespace, Name: saName})
   141  	}
   142  	return r
   143  }
   144  
   145  func (r *ClusterRoleBindingBuilder) BindingOrDie() rbacv1.ClusterRoleBinding {
   146  	ret, err := r.Binding()
   147  	if err != nil {
   148  		panic(err)
   149  	}
   150  	return ret
   151  }
   152  
   153  func (r *ClusterRoleBindingBuilder) Binding() (rbacv1.ClusterRoleBinding, error) {
   154  	if len(r.ClusterRoleBinding.Subjects) == 0 {
   155  		return rbacv1.ClusterRoleBinding{}, fmt.Errorf("subjects are required: %#v", r.ClusterRoleBinding)
   156  	}
   157  
   158  	return r.ClusterRoleBinding, nil
   159  }
   160  
   161  // +k8s:deepcopy-gen=false
   162  
   163  // RoleBindingBuilder let's us attach methods. It is similar to
   164  // ClusterRoleBindingBuilder above.
   165  type RoleBindingBuilder struct {
   166  	RoleBinding rbacv1.RoleBinding
   167  }
   168  
   169  // NewRoleBinding creates a RoleBinding builder that can be used
   170  // to define the subjects of a role binding. At least one of
   171  // the `Groups`, `Users` or `SAs` method must be called before
   172  // calling the `Binding*` methods.
   173  func NewRoleBinding(roleName, namespace string) *RoleBindingBuilder {
   174  	return &RoleBindingBuilder{
   175  		RoleBinding: rbacv1.RoleBinding{
   176  			ObjectMeta: metav1.ObjectMeta{
   177  				Name:      roleName,
   178  				Namespace: namespace,
   179  			},
   180  			RoleRef: rbacv1.RoleRef{
   181  				APIGroup: GroupName,
   182  				Kind:     "Role",
   183  				Name:     roleName,
   184  			},
   185  		},
   186  	}
   187  }
   188  
   189  // Groups adds the specified groups as the subjects of the RoleBinding.
   190  func (r *RoleBindingBuilder) Groups(groups ...string) *RoleBindingBuilder {
   191  	for _, group := range groups {
   192  		r.RoleBinding.Subjects = append(r.RoleBinding.Subjects, rbacv1.Subject{Kind: rbacv1.GroupKind, APIGroup: GroupName, Name: group})
   193  	}
   194  	return r
   195  }
   196  
   197  // Users adds the specified users as the subjects of the RoleBinding.
   198  func (r *RoleBindingBuilder) Users(users ...string) *RoleBindingBuilder {
   199  	for _, user := range users {
   200  		r.RoleBinding.Subjects = append(r.RoleBinding.Subjects, rbacv1.Subject{Kind: rbacv1.UserKind, APIGroup: GroupName, Name: user})
   201  	}
   202  	return r
   203  }
   204  
   205  // SAs adds the specified service accounts as the subjects of the
   206  // RoleBinding.
   207  func (r *RoleBindingBuilder) SAs(namespace string, serviceAccountNames ...string) *RoleBindingBuilder {
   208  	for _, saName := range serviceAccountNames {
   209  		r.RoleBinding.Subjects = append(r.RoleBinding.Subjects, rbacv1.Subject{Kind: rbacv1.ServiceAccountKind, Namespace: namespace, Name: saName})
   210  	}
   211  	return r
   212  }
   213  
   214  // BindingOrDie calls the binding method and panics if there is an error.
   215  func (r *RoleBindingBuilder) BindingOrDie() rbacv1.RoleBinding {
   216  	ret, err := r.Binding()
   217  	if err != nil {
   218  		panic(err)
   219  	}
   220  	return ret
   221  }
   222  
   223  // Binding builds and returns the RoleBinding API object from the builder
   224  // object.
   225  func (r *RoleBindingBuilder) Binding() (rbacv1.RoleBinding, error) {
   226  	if len(r.RoleBinding.Subjects) == 0 {
   227  		return rbacv1.RoleBinding{}, fmt.Errorf("subjects are required: %#v", r.RoleBinding)
   228  	}
   229  
   230  	return r.RoleBinding, nil
   231  }
   232  

View as plain text