k8s.io/apiserver@v0.31.1/pkg/apis/flowcontrol/bootstrap/default.go (about)

     1  /*
     2  Copyright 2019 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 bootstrap
    18  
    19  import (
    20  	coordinationv1 "k8s.io/api/coordination/v1"
    21  	corev1 "k8s.io/api/core/v1"
    22  	flowcontrol "k8s.io/api/flowcontrol/v1"
    23  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    24  	"k8s.io/apiserver/pkg/authentication/serviceaccount"
    25  	"k8s.io/apiserver/pkg/authentication/user"
    26  	"k8s.io/utils/ptr"
    27  )
    28  
    29  // The objects that define an apiserver's initial behavior.  The
    30  // registered defaulting procedures make no changes to these
    31  // particular objects (this is verified in the unit tests of the
    32  // internalbootstrap package; it can not be verified in this package
    33  // because that would require importing k8s.io/kubernetes).
    34  var (
    35  	MandatoryPriorityLevelConfigurations = []*flowcontrol.PriorityLevelConfiguration{
    36  		MandatoryPriorityLevelConfigurationCatchAll,
    37  		MandatoryPriorityLevelConfigurationExempt,
    38  	}
    39  	MandatoryFlowSchemas = []*flowcontrol.FlowSchema{
    40  		MandatoryFlowSchemaExempt,
    41  		MandatoryFlowSchemaCatchAll,
    42  	}
    43  )
    44  
    45  // The objects that define the current suggested additional configuration
    46  var (
    47  	SuggestedPriorityLevelConfigurations = []*flowcontrol.PriorityLevelConfiguration{
    48  		// "system" priority-level is for the system components that affects self-maintenance of the
    49  		// cluster and the availability of those running pods in the cluster, including kubelet and
    50  		// kube-proxy.
    51  		SuggestedPriorityLevelConfigurationSystem,
    52  		// "node-high" priority-level is for the node health reporting. It is separated from "system"
    53  		// to make sure that nodes are able to report their health even if kube-apiserver is not capable of
    54  		// handling load caused by pod startup (fetching secrets, events etc).
    55  		// NOTE: In large clusters 50% - 90% of all API calls use this priority-level.
    56  		SuggestedPriorityLevelConfigurationNodeHigh,
    57  		// "leader-election" is dedicated for controllers' leader-election, which majorly affects the
    58  		// availability of any controller runs in the cluster.
    59  		SuggestedPriorityLevelConfigurationLeaderElection,
    60  		// "workload-high" is used by those workloads with higher priority but their failure won't directly
    61  		// impact the existing running pods in the cluster, which includes kube-scheduler, and those well-known
    62  		// built-in workloads such as "deployments", "replicasets" and other low-level custom workload which
    63  		// is important for the cluster.
    64  		SuggestedPriorityLevelConfigurationWorkloadHigh,
    65  		// "workload-low" is used by those workloads with lower priority which availability only has a
    66  		// minor impact on the cluster.
    67  		SuggestedPriorityLevelConfigurationWorkloadLow,
    68  		// "global-default" serves the rest traffic not handled by the other suggested flow-schemas above.
    69  		SuggestedPriorityLevelConfigurationGlobalDefault,
    70  	}
    71  	SuggestedFlowSchemas = []*flowcontrol.FlowSchema{
    72  		SuggestedFlowSchemaSystemNodes,               // references "system" priority-level
    73  		SuggestedFlowSchemaSystemNodeHigh,            // references "node-high" priority-level
    74  		SuggestedFlowSchemaProbes,                    // references "exempt" priority-level
    75  		SuggestedFlowSchemaSystemLeaderElection,      // references "leader-election" priority-level
    76  		SuggestedFlowSchemaWorkloadLeaderElection,    // references "leader-election" priority-level
    77  		SuggestedFlowSchemaEndpointsController,       // references "workload-high" priority-level
    78  		SuggestedFlowSchemaKubeControllerManager,     // references "workload-high" priority-level
    79  		SuggestedFlowSchemaKubeScheduler,             // references "workload-high" priority-level
    80  		SuggestedFlowSchemaKubeSystemServiceAccounts, // references "workload-high" priority-level
    81  		SuggestedFlowSchemaServiceAccounts,           // references "workload-low" priority-level
    82  		SuggestedFlowSchemaGlobalDefault,             // references "global-default" priority-level
    83  	}
    84  )
    85  
    86  // Mandatory PriorityLevelConfiguration objects
    87  var (
    88  	MandatoryPriorityLevelConfigurationExempt = newPriorityLevelConfiguration(
    89  		flowcontrol.PriorityLevelConfigurationNameExempt,
    90  		flowcontrol.PriorityLevelConfigurationSpec{
    91  			Type: flowcontrol.PriorityLevelEnablementExempt,
    92  			Exempt: &flowcontrol.ExemptPriorityLevelConfiguration{
    93  				NominalConcurrencyShares: ptr.To(int32(0)),
    94  				LendablePercent:          ptr.To(int32(0)),
    95  			},
    96  		},
    97  	)
    98  	MandatoryPriorityLevelConfigurationCatchAll = newPriorityLevelConfiguration(
    99  		flowcontrol.PriorityLevelConfigurationNameCatchAll,
   100  		flowcontrol.PriorityLevelConfigurationSpec{
   101  			Type: flowcontrol.PriorityLevelEnablementLimited,
   102  			Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
   103  				NominalConcurrencyShares: ptr.To(int32(5)),
   104  				LendablePercent:          ptr.To(int32(0)),
   105  				LimitResponse: flowcontrol.LimitResponse{
   106  					Type: flowcontrol.LimitResponseTypeReject,
   107  				},
   108  			},
   109  		})
   110  )
   111  
   112  // Mandatory FlowSchema objects
   113  var (
   114  	// "exempt" priority-level is used for preventing priority inversion and ensuring that sysadmin
   115  	// requests are always possible.
   116  	MandatoryFlowSchemaExempt = newFlowSchema(
   117  		"exempt",
   118  		flowcontrol.PriorityLevelConfigurationNameExempt,
   119  		1,  // matchingPrecedence
   120  		"", // distinguisherMethodType
   121  		flowcontrol.PolicyRulesWithSubjects{
   122  			Subjects: groups(user.SystemPrivilegedGroup),
   123  			ResourceRules: []flowcontrol.ResourcePolicyRule{
   124  				resourceRule(
   125  					[]string{flowcontrol.VerbAll},
   126  					[]string{flowcontrol.APIGroupAll},
   127  					[]string{flowcontrol.ResourceAll},
   128  					[]string{flowcontrol.NamespaceEvery},
   129  					true,
   130  				),
   131  			},
   132  			NonResourceRules: []flowcontrol.NonResourcePolicyRule{
   133  				nonResourceRule(
   134  					[]string{flowcontrol.VerbAll},
   135  					[]string{flowcontrol.NonResourceAll},
   136  				),
   137  			},
   138  		},
   139  	)
   140  	// "catch-all" priority-level only gets a minimal positive share of concurrency and won't be reaching
   141  	// ideally unless you intentionally deleted the suggested "global-default".
   142  	MandatoryFlowSchemaCatchAll = newFlowSchema(
   143  		flowcontrol.FlowSchemaNameCatchAll,
   144  		flowcontrol.PriorityLevelConfigurationNameCatchAll,
   145  		10000, // matchingPrecedence
   146  		flowcontrol.FlowDistinguisherMethodByUserType, // distinguisherMethodType
   147  		flowcontrol.PolicyRulesWithSubjects{
   148  			Subjects: groups(user.AllUnauthenticated, user.AllAuthenticated),
   149  			ResourceRules: []flowcontrol.ResourcePolicyRule{
   150  				resourceRule(
   151  					[]string{flowcontrol.VerbAll},
   152  					[]string{flowcontrol.APIGroupAll},
   153  					[]string{flowcontrol.ResourceAll},
   154  					[]string{flowcontrol.NamespaceEvery},
   155  					true,
   156  				),
   157  			},
   158  			NonResourceRules: []flowcontrol.NonResourcePolicyRule{
   159  				nonResourceRule(
   160  					[]string{flowcontrol.VerbAll},
   161  					[]string{flowcontrol.NonResourceAll},
   162  				),
   163  			},
   164  		},
   165  	)
   166  )
   167  
   168  // Suggested PriorityLevelConfiguration objects
   169  var (
   170  	// system priority-level
   171  	SuggestedPriorityLevelConfigurationSystem = newPriorityLevelConfiguration(
   172  		"system",
   173  		flowcontrol.PriorityLevelConfigurationSpec{
   174  			Type: flowcontrol.PriorityLevelEnablementLimited,
   175  			Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
   176  				NominalConcurrencyShares: ptr.To(int32(30)),
   177  				LendablePercent:          ptr.To(int32(33)),
   178  				LimitResponse: flowcontrol.LimitResponse{
   179  					Type: flowcontrol.LimitResponseTypeQueue,
   180  					Queuing: &flowcontrol.QueuingConfiguration{
   181  						Queues:           64,
   182  						HandSize:         6,
   183  						QueueLengthLimit: 50,
   184  					},
   185  				},
   186  			},
   187  		})
   188  	SuggestedPriorityLevelConfigurationNodeHigh = newPriorityLevelConfiguration(
   189  		"node-high",
   190  		flowcontrol.PriorityLevelConfigurationSpec{
   191  			Type: flowcontrol.PriorityLevelEnablementLimited,
   192  			Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
   193  				NominalConcurrencyShares: ptr.To(int32(40)),
   194  				LendablePercent:          ptr.To(int32(25)),
   195  				LimitResponse: flowcontrol.LimitResponse{
   196  					Type: flowcontrol.LimitResponseTypeQueue,
   197  					Queuing: &flowcontrol.QueuingConfiguration{
   198  						Queues:           64,
   199  						HandSize:         6,
   200  						QueueLengthLimit: 50,
   201  					},
   202  				},
   203  			},
   204  		})
   205  	// leader-election priority-level
   206  	SuggestedPriorityLevelConfigurationLeaderElection = newPriorityLevelConfiguration(
   207  		"leader-election",
   208  		flowcontrol.PriorityLevelConfigurationSpec{
   209  			Type: flowcontrol.PriorityLevelEnablementLimited,
   210  			Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
   211  				NominalConcurrencyShares: ptr.To(int32(10)),
   212  				LendablePercent:          ptr.To(int32(0)),
   213  				LimitResponse: flowcontrol.LimitResponse{
   214  					Type: flowcontrol.LimitResponseTypeQueue,
   215  					Queuing: &flowcontrol.QueuingConfiguration{
   216  						Queues:           16,
   217  						HandSize:         4,
   218  						QueueLengthLimit: 50,
   219  					},
   220  				},
   221  			},
   222  		})
   223  	// workload-high priority-level
   224  	SuggestedPriorityLevelConfigurationWorkloadHigh = newPriorityLevelConfiguration(
   225  		"workload-high",
   226  		flowcontrol.PriorityLevelConfigurationSpec{
   227  			Type: flowcontrol.PriorityLevelEnablementLimited,
   228  			Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
   229  				NominalConcurrencyShares: ptr.To(int32(40)),
   230  				LendablePercent:          ptr.To(int32(50)),
   231  				LimitResponse: flowcontrol.LimitResponse{
   232  					Type: flowcontrol.LimitResponseTypeQueue,
   233  					Queuing: &flowcontrol.QueuingConfiguration{
   234  						Queues:           128,
   235  						HandSize:         6,
   236  						QueueLengthLimit: 50,
   237  					},
   238  				},
   239  			},
   240  		})
   241  	// workload-low priority-level
   242  	SuggestedPriorityLevelConfigurationWorkloadLow = newPriorityLevelConfiguration(
   243  		"workload-low",
   244  		flowcontrol.PriorityLevelConfigurationSpec{
   245  			Type: flowcontrol.PriorityLevelEnablementLimited,
   246  			Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
   247  				NominalConcurrencyShares: ptr.To(int32(100)),
   248  				LendablePercent:          ptr.To(int32(90)),
   249  				LimitResponse: flowcontrol.LimitResponse{
   250  					Type: flowcontrol.LimitResponseTypeQueue,
   251  					Queuing: &flowcontrol.QueuingConfiguration{
   252  						Queues:           128,
   253  						HandSize:         6,
   254  						QueueLengthLimit: 50,
   255  					},
   256  				},
   257  			},
   258  		})
   259  	// global-default priority-level
   260  	SuggestedPriorityLevelConfigurationGlobalDefault = newPriorityLevelConfiguration(
   261  		"global-default",
   262  		flowcontrol.PriorityLevelConfigurationSpec{
   263  			Type: flowcontrol.PriorityLevelEnablementLimited,
   264  			Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
   265  				NominalConcurrencyShares: ptr.To(int32(20)),
   266  				LendablePercent:          ptr.To(int32(50)),
   267  				LimitResponse: flowcontrol.LimitResponse{
   268  					Type: flowcontrol.LimitResponseTypeQueue,
   269  					Queuing: &flowcontrol.QueuingConfiguration{
   270  						Queues:           128,
   271  						HandSize:         6,
   272  						QueueLengthLimit: 50,
   273  					},
   274  				},
   275  			},
   276  		})
   277  )
   278  
   279  // Suggested FlowSchema objects.
   280  // Ordered by matching precedence, so that their interactions are easier
   281  // to follow while reading this source.
   282  var (
   283  	// the following flow schema exempts probes
   284  	SuggestedFlowSchemaProbes = newFlowSchema(
   285  		"probes", "exempt", 2,
   286  		"", // distinguisherMethodType
   287  		flowcontrol.PolicyRulesWithSubjects{
   288  			Subjects: groups(user.AllUnauthenticated, user.AllAuthenticated),
   289  			NonResourceRules: []flowcontrol.NonResourcePolicyRule{
   290  				nonResourceRule(
   291  					[]string{"get"},
   292  					[]string{"/healthz", "/readyz", "/livez"}),
   293  			},
   294  		},
   295  	)
   296  	SuggestedFlowSchemaSystemLeaderElection = newFlowSchema(
   297  		"system-leader-election", "leader-election", 100,
   298  		flowcontrol.FlowDistinguisherMethodByUserType,
   299  		flowcontrol.PolicyRulesWithSubjects{
   300  			Subjects: append(
   301  				users(user.KubeControllerManager, user.KubeScheduler),
   302  				kubeSystemServiceAccount(flowcontrol.NameAll)...),
   303  			ResourceRules: []flowcontrol.ResourcePolicyRule{
   304  				resourceRule(
   305  					[]string{"get", "create", "update"},
   306  					[]string{coordinationv1.GroupName},
   307  					[]string{"leases"},
   308  					[]string{flowcontrol.NamespaceEvery},
   309  					false),
   310  			},
   311  		},
   312  	)
   313  	// We add an explicit rule for endpoint-controller with high precedence
   314  	// to ensure that those calls won't get caught by the following
   315  	// <workload-leader-election> flow-schema.
   316  	//
   317  	// TODO(#80289): Get rid of this rule once we get rid of support for
   318  	//   using endpoints and configmaps objects for leader election.
   319  	SuggestedFlowSchemaEndpointsController = newFlowSchema(
   320  		"endpoint-controller", "workload-high", 150,
   321  		flowcontrol.FlowDistinguisherMethodByUserType,
   322  		flowcontrol.PolicyRulesWithSubjects{
   323  			Subjects: append(
   324  				users(user.KubeControllerManager),
   325  				kubeSystemServiceAccount("endpoint-controller", "endpointslicemirroring-controller")...),
   326  			ResourceRules: []flowcontrol.ResourcePolicyRule{
   327  				resourceRule(
   328  					[]string{"get", "create", "update"},
   329  					[]string{corev1.GroupName},
   330  					[]string{"endpoints"},
   331  					[]string{flowcontrol.NamespaceEvery},
   332  					false),
   333  			},
   334  		},
   335  	)
   336  	// TODO(#80289): Get rid of this rule once we get rid of support for
   337  	//   using endpoints and configmaps objects for leader election.
   338  	SuggestedFlowSchemaWorkloadLeaderElection = newFlowSchema(
   339  		"workload-leader-election", "leader-election", 200,
   340  		flowcontrol.FlowDistinguisherMethodByUserType,
   341  		flowcontrol.PolicyRulesWithSubjects{
   342  			Subjects: kubeSystemServiceAccount(flowcontrol.NameAll),
   343  			ResourceRules: []flowcontrol.ResourcePolicyRule{
   344  				resourceRule(
   345  					[]string{"get", "create", "update"},
   346  					[]string{corev1.GroupName},
   347  					[]string{"endpoints", "configmaps"},
   348  					[]string{flowcontrol.NamespaceEvery},
   349  					false),
   350  				resourceRule(
   351  					[]string{"get", "create", "update"},
   352  					[]string{coordinationv1.GroupName},
   353  					[]string{"leases"},
   354  					[]string{flowcontrol.NamespaceEvery},
   355  					false),
   356  			},
   357  		},
   358  	)
   359  	SuggestedFlowSchemaSystemNodeHigh = newFlowSchema(
   360  		"system-node-high", "node-high", 400,
   361  		flowcontrol.FlowDistinguisherMethodByUserType,
   362  		flowcontrol.PolicyRulesWithSubjects{
   363  			Subjects: groups(user.NodesGroup), // the nodes group
   364  			ResourceRules: []flowcontrol.ResourcePolicyRule{
   365  				resourceRule(
   366  					[]string{flowcontrol.VerbAll},
   367  					[]string{corev1.GroupName},
   368  					[]string{"nodes", "nodes/status"},
   369  					[]string{flowcontrol.NamespaceEvery},
   370  					true),
   371  				resourceRule(
   372  					[]string{flowcontrol.VerbAll},
   373  					[]string{coordinationv1.GroupName},
   374  					[]string{"leases"},
   375  					[]string{flowcontrol.NamespaceEvery},
   376  					false),
   377  			},
   378  		},
   379  	)
   380  	SuggestedFlowSchemaSystemNodes = newFlowSchema(
   381  		"system-nodes", "system", 500,
   382  		flowcontrol.FlowDistinguisherMethodByUserType,
   383  		flowcontrol.PolicyRulesWithSubjects{
   384  			Subjects: groups(user.NodesGroup), // the nodes group
   385  			ResourceRules: []flowcontrol.ResourcePolicyRule{resourceRule(
   386  				[]string{flowcontrol.VerbAll},
   387  				[]string{flowcontrol.APIGroupAll},
   388  				[]string{flowcontrol.ResourceAll},
   389  				[]string{flowcontrol.NamespaceEvery},
   390  				true)},
   391  			NonResourceRules: []flowcontrol.NonResourcePolicyRule{
   392  				nonResourceRule(
   393  					[]string{flowcontrol.VerbAll},
   394  					[]string{flowcontrol.NonResourceAll}),
   395  			},
   396  		},
   397  	)
   398  	SuggestedFlowSchemaKubeControllerManager = newFlowSchema(
   399  		"kube-controller-manager", "workload-high", 800,
   400  		flowcontrol.FlowDistinguisherMethodByNamespaceType,
   401  		flowcontrol.PolicyRulesWithSubjects{
   402  			Subjects: users(user.KubeControllerManager),
   403  			ResourceRules: []flowcontrol.ResourcePolicyRule{resourceRule(
   404  				[]string{flowcontrol.VerbAll},
   405  				[]string{flowcontrol.APIGroupAll},
   406  				[]string{flowcontrol.ResourceAll},
   407  				[]string{flowcontrol.NamespaceEvery},
   408  				true)},
   409  			NonResourceRules: []flowcontrol.NonResourcePolicyRule{
   410  				nonResourceRule(
   411  					[]string{flowcontrol.VerbAll},
   412  					[]string{flowcontrol.NonResourceAll}),
   413  			},
   414  		},
   415  	)
   416  	SuggestedFlowSchemaKubeScheduler = newFlowSchema(
   417  		"kube-scheduler", "workload-high", 800,
   418  		flowcontrol.FlowDistinguisherMethodByNamespaceType,
   419  		flowcontrol.PolicyRulesWithSubjects{
   420  			Subjects: users(user.KubeScheduler),
   421  			ResourceRules: []flowcontrol.ResourcePolicyRule{resourceRule(
   422  				[]string{flowcontrol.VerbAll},
   423  				[]string{flowcontrol.APIGroupAll},
   424  				[]string{flowcontrol.ResourceAll},
   425  				[]string{flowcontrol.NamespaceEvery},
   426  				true)},
   427  			NonResourceRules: []flowcontrol.NonResourcePolicyRule{
   428  				nonResourceRule(
   429  					[]string{flowcontrol.VerbAll},
   430  					[]string{flowcontrol.NonResourceAll}),
   431  			},
   432  		},
   433  	)
   434  	SuggestedFlowSchemaKubeSystemServiceAccounts = newFlowSchema(
   435  		"kube-system-service-accounts", "workload-high", 900,
   436  		flowcontrol.FlowDistinguisherMethodByNamespaceType,
   437  		flowcontrol.PolicyRulesWithSubjects{
   438  			Subjects: kubeSystemServiceAccount(flowcontrol.NameAll),
   439  			ResourceRules: []flowcontrol.ResourcePolicyRule{resourceRule(
   440  				[]string{flowcontrol.VerbAll},
   441  				[]string{flowcontrol.APIGroupAll},
   442  				[]string{flowcontrol.ResourceAll},
   443  				[]string{flowcontrol.NamespaceEvery},
   444  				true)},
   445  			NonResourceRules: []flowcontrol.NonResourcePolicyRule{
   446  				nonResourceRule(
   447  					[]string{flowcontrol.VerbAll},
   448  					[]string{flowcontrol.NonResourceAll}),
   449  			},
   450  		},
   451  	)
   452  	SuggestedFlowSchemaServiceAccounts = newFlowSchema(
   453  		"service-accounts", "workload-low", 9000,
   454  		flowcontrol.FlowDistinguisherMethodByUserType,
   455  		flowcontrol.PolicyRulesWithSubjects{
   456  			Subjects: groups(serviceaccount.AllServiceAccountsGroup),
   457  			ResourceRules: []flowcontrol.ResourcePolicyRule{resourceRule(
   458  				[]string{flowcontrol.VerbAll},
   459  				[]string{flowcontrol.APIGroupAll},
   460  				[]string{flowcontrol.ResourceAll},
   461  				[]string{flowcontrol.NamespaceEvery},
   462  				true)},
   463  			NonResourceRules: []flowcontrol.NonResourcePolicyRule{
   464  				nonResourceRule(
   465  					[]string{flowcontrol.VerbAll},
   466  					[]string{flowcontrol.NonResourceAll}),
   467  			},
   468  		},
   469  	)
   470  	SuggestedFlowSchemaGlobalDefault = newFlowSchema(
   471  		"global-default", "global-default", 9900,
   472  		flowcontrol.FlowDistinguisherMethodByUserType,
   473  		flowcontrol.PolicyRulesWithSubjects{
   474  			Subjects: groups(user.AllUnauthenticated, user.AllAuthenticated),
   475  			ResourceRules: []flowcontrol.ResourcePolicyRule{resourceRule(
   476  				[]string{flowcontrol.VerbAll},
   477  				[]string{flowcontrol.APIGroupAll},
   478  				[]string{flowcontrol.ResourceAll},
   479  				[]string{flowcontrol.NamespaceEvery},
   480  				true)},
   481  			NonResourceRules: []flowcontrol.NonResourcePolicyRule{
   482  				nonResourceRule(
   483  					[]string{flowcontrol.VerbAll},
   484  					[]string{flowcontrol.NonResourceAll}),
   485  			},
   486  		},
   487  	)
   488  )
   489  
   490  func newPriorityLevelConfiguration(name string, spec flowcontrol.PriorityLevelConfigurationSpec) *flowcontrol.PriorityLevelConfiguration {
   491  	return &flowcontrol.PriorityLevelConfiguration{
   492  		ObjectMeta: metav1.ObjectMeta{
   493  			Name: name,
   494  			Annotations: map[string]string{
   495  				flowcontrol.AutoUpdateAnnotationKey: "true",
   496  			},
   497  		},
   498  		Spec: spec,
   499  	}
   500  }
   501  
   502  func newFlowSchema(name, plName string, matchingPrecedence int32, dmType flowcontrol.FlowDistinguisherMethodType, rules ...flowcontrol.PolicyRulesWithSubjects) *flowcontrol.FlowSchema {
   503  	var dm *flowcontrol.FlowDistinguisherMethod
   504  	if dmType != "" {
   505  		dm = &flowcontrol.FlowDistinguisherMethod{Type: dmType}
   506  	}
   507  	return &flowcontrol.FlowSchema{
   508  		ObjectMeta: metav1.ObjectMeta{
   509  			Name: name,
   510  			Annotations: map[string]string{
   511  				flowcontrol.AutoUpdateAnnotationKey: "true",
   512  			},
   513  		},
   514  		Spec: flowcontrol.FlowSchemaSpec{
   515  			PriorityLevelConfiguration: flowcontrol.PriorityLevelConfigurationReference{
   516  				Name: plName,
   517  			},
   518  			MatchingPrecedence:  matchingPrecedence,
   519  			DistinguisherMethod: dm,
   520  			Rules:               rules},
   521  	}
   522  
   523  }
   524  
   525  func groups(names ...string) []flowcontrol.Subject {
   526  	ans := make([]flowcontrol.Subject, len(names))
   527  	for idx, name := range names {
   528  		ans[idx] = flowcontrol.Subject{
   529  			Kind: flowcontrol.SubjectKindGroup,
   530  			Group: &flowcontrol.GroupSubject{
   531  				Name: name,
   532  			},
   533  		}
   534  	}
   535  	return ans
   536  }
   537  
   538  func users(names ...string) []flowcontrol.Subject {
   539  	ans := make([]flowcontrol.Subject, len(names))
   540  	for idx, name := range names {
   541  		ans[idx] = flowcontrol.Subject{
   542  			Kind: flowcontrol.SubjectKindUser,
   543  			User: &flowcontrol.UserSubject{
   544  				Name: name,
   545  			},
   546  		}
   547  	}
   548  	return ans
   549  }
   550  
   551  func kubeSystemServiceAccount(names ...string) []flowcontrol.Subject {
   552  	subjects := []flowcontrol.Subject{}
   553  	for _, name := range names {
   554  		subjects = append(subjects, flowcontrol.Subject{
   555  			Kind: flowcontrol.SubjectKindServiceAccount,
   556  			ServiceAccount: &flowcontrol.ServiceAccountSubject{
   557  				Name:      name,
   558  				Namespace: metav1.NamespaceSystem,
   559  			},
   560  		})
   561  	}
   562  	return subjects
   563  }
   564  
   565  func resourceRule(verbs []string, groups []string, resources []string, namespaces []string, clusterScoped bool) flowcontrol.ResourcePolicyRule {
   566  	return flowcontrol.ResourcePolicyRule{
   567  		Verbs:        verbs,
   568  		APIGroups:    groups,
   569  		Resources:    resources,
   570  		Namespaces:   namespaces,
   571  		ClusterScope: clusterScoped,
   572  	}
   573  }
   574  
   575  func nonResourceRule(verbs []string, nonResourceURLs []string) flowcontrol.NonResourcePolicyRule {
   576  	return flowcontrol.NonResourcePolicyRule{Verbs: verbs, NonResourceURLs: nonResourceURLs}
   577  }