...

Source file src/k8s.io/kubernetes/pkg/registry/flowcontrol/ensurer/prioritylevelconfiguration_test.go

Documentation: k8s.io/kubernetes/pkg/registry/flowcontrol/ensurer

     1  /*
     2  Copyright 2021 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 ensurer
    18  
    19  import (
    20  	"context"
    21  	"reflect"
    22  	"testing"
    23  
    24  	flowcontrolv1 "k8s.io/api/flowcontrol/v1"
    25  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  	"k8s.io/apiserver/pkg/apis/flowcontrol/bootstrap"
    28  	"k8s.io/client-go/kubernetes/fake"
    29  	flowcontrollisters "k8s.io/client-go/listers/flowcontrol/v1"
    30  	toolscache "k8s.io/client-go/tools/cache"
    31  	flowcontrolapisv1 "k8s.io/kubernetes/pkg/apis/flowcontrol/v1"
    32  	"k8s.io/utils/pointer"
    33  	"k8s.io/utils/ptr"
    34  
    35  	"github.com/google/go-cmp/cmp"
    36  )
    37  
    38  func TestEnsurePriorityLevel(t *testing.T) {
    39  	validExemptPL := func() *flowcontrolv1.PriorityLevelConfiguration {
    40  		copy := bootstrap.MandatoryPriorityLevelConfigurationExempt.DeepCopy()
    41  		copy.Annotations[flowcontrolv1.AutoUpdateAnnotationKey] = "true"
    42  		copy.Spec.Exempt.NominalConcurrencyShares = pointer.Int32(10)
    43  		copy.Spec.Exempt.LendablePercent = pointer.Int32(50)
    44  		return copy
    45  	}()
    46  
    47  	tests := []struct {
    48  		name      string
    49  		strategy  func() EnsureStrategy[*flowcontrolv1.PriorityLevelConfiguration]
    50  		current   *flowcontrolv1.PriorityLevelConfiguration
    51  		bootstrap *flowcontrolv1.PriorityLevelConfiguration
    52  		expected  *flowcontrolv1.PriorityLevelConfiguration
    53  	}{
    54  		// for suggested configurations
    55  		{
    56  			name:      "suggested priority level configuration does not exist - the object should always be re-created",
    57  			strategy:  NewSuggestedEnsureStrategy[*flowcontrolv1.PriorityLevelConfiguration],
    58  			bootstrap: newPLConfiguration("pl1").WithLimited(10).Object(),
    59  			current:   nil,
    60  			expected:  newPLConfiguration("pl1").WithLimited(10).Object(),
    61  		},
    62  		{
    63  			name:      "suggested priority level configuration exists, auto update is enabled, spec does not match - current object should be updated",
    64  			strategy:  NewSuggestedEnsureStrategy[*flowcontrolv1.PriorityLevelConfiguration],
    65  			bootstrap: newPLConfiguration("pl1").WithLimited(20).Object(),
    66  			current:   newPLConfiguration("pl1").WithAutoUpdateAnnotation("true").WithLimited(10).Object(),
    67  			expected:  newPLConfiguration("pl1").WithAutoUpdateAnnotation("true").WithLimited(20).Object(),
    68  		},
    69  		{
    70  			name:      "suggested priority level configuration exists, auto update is disabled, spec does not match - current object should not be updated",
    71  			strategy:  NewSuggestedEnsureStrategy[*flowcontrolv1.PriorityLevelConfiguration],
    72  			bootstrap: newPLConfiguration("pl1").WithLimited(20).Object(),
    73  			current:   newPLConfiguration("pl1").WithAutoUpdateAnnotation("false").WithLimited(10).Object(),
    74  			expected:  newPLConfiguration("pl1").WithAutoUpdateAnnotation("false").WithLimited(10).Object(),
    75  		},
    76  
    77  		// for mandatory configurations
    78  		{
    79  			name:      "mandatory priority level configuration does not exist - new object should be created",
    80  			strategy:  NewMandatoryEnsureStrategy[*flowcontrolv1.PriorityLevelConfiguration],
    81  			bootstrap: newPLConfiguration("pl1").WithLimited(10).WithAutoUpdateAnnotation("true").Object(),
    82  			current:   nil,
    83  			expected:  newPLConfiguration("pl1").WithLimited(10).WithAutoUpdateAnnotation("true").Object(),
    84  		},
    85  		{
    86  			name:      "mandatory priority level configuration exists, annotation is missing - annotation is added",
    87  			strategy:  NewMandatoryEnsureStrategy[*flowcontrolv1.PriorityLevelConfiguration],
    88  			bootstrap: newPLConfiguration("pl1").WithLimited(20).Object(),
    89  			current:   newPLConfiguration("pl1").WithLimited(20).Object(),
    90  			expected:  newPLConfiguration("pl1").WithAutoUpdateAnnotation("true").WithLimited(20).Object(),
    91  		},
    92  		{
    93  			name:      "mandatory priority level configuration exists, auto update is disabled, spec does not match - current object should be updated",
    94  			strategy:  NewMandatoryEnsureStrategy[*flowcontrolv1.PriorityLevelConfiguration],
    95  			bootstrap: newPLConfiguration("pl1").WithLimited(20).Object(),
    96  			current:   newPLConfiguration("pl1").WithAutoUpdateAnnotation("false").WithLimited(10).Object(),
    97  			expected:  newPLConfiguration("pl1").WithAutoUpdateAnnotation("true").WithLimited(20).Object(),
    98  		},
    99  		{
   100  			name:     "admin changes the Exempt field of the exempt priority level configuration",
   101  			strategy: NewMandatoryEnsureStrategy[*flowcontrolv1.PriorityLevelConfiguration],
   102  			bootstrap: func() *flowcontrolv1.PriorityLevelConfiguration {
   103  				return bootstrap.MandatoryPriorityLevelConfigurationExempt
   104  			}(),
   105  			current:  validExemptPL,
   106  			expected: validExemptPL,
   107  		},
   108  	}
   109  
   110  	for _, test := range tests {
   111  		t.Run(test.name, func(t *testing.T) {
   112  			client := fake.NewSimpleClientset().FlowcontrolV1().PriorityLevelConfigurations()
   113  			indexer := toolscache.NewIndexer(toolscache.MetaNamespaceKeyFunc, toolscache.Indexers{})
   114  			if test.current != nil {
   115  				client.Create(context.TODO(), test.current, metav1.CreateOptions{})
   116  				indexer.Add(test.current)
   117  			}
   118  
   119  			ops := NewPriorityLevelConfigurationOps(client, flowcontrollisters.NewPriorityLevelConfigurationLister(indexer))
   120  			boots := []*flowcontrolv1.PriorityLevelConfiguration{test.bootstrap}
   121  			strategy := test.strategy()
   122  
   123  			err := EnsureConfigurations(context.Background(), ops, boots, strategy)
   124  			if err != nil {
   125  				t.Fatalf("Expected no error, but got: %v", err)
   126  			}
   127  
   128  			plGot, err := client.Get(context.TODO(), test.bootstrap.Name, metav1.GetOptions{})
   129  			switch {
   130  			case test.expected == nil:
   131  				if !apierrors.IsNotFound(err) {
   132  					t.Fatalf("Expected GET to return an %q error, but got: %v", metav1.StatusReasonNotFound, err)
   133  				}
   134  			case err != nil:
   135  				t.Fatalf("Expected GET to return no error, but got: %v", err)
   136  			}
   137  
   138  			if !reflect.DeepEqual(test.expected, plGot) {
   139  				t.Errorf("PriorityLevelConfiguration does not match - diff: %s", cmp.Diff(test.expected, plGot))
   140  			}
   141  		})
   142  	}
   143  }
   144  
   145  func TestSuggestedPLEnsureStrategy_ShouldUpdate(t *testing.T) {
   146  	tests := []struct {
   147  		name              string
   148  		current           *flowcontrolv1.PriorityLevelConfiguration
   149  		bootstrap         *flowcontrolv1.PriorityLevelConfiguration
   150  		newObjectExpected *flowcontrolv1.PriorityLevelConfiguration
   151  	}{
   152  		{
   153  			name:              "auto update is enabled, first generation, spec does not match - spec update expected",
   154  			current:           newPLConfiguration("foo").WithAutoUpdateAnnotation("true").WithGeneration(1).WithLimited(5).Object(),
   155  			bootstrap:         newPLConfiguration("foo").WithLimited(10).Object(),
   156  			newObjectExpected: newPLConfiguration("foo").WithAutoUpdateAnnotation("true").WithGeneration(1).WithLimited(10).Object(),
   157  		},
   158  		{
   159  			name:              "auto update is enabled, first generation, spec matches - no update expected",
   160  			current:           newPLConfiguration("foo").WithAutoUpdateAnnotation("true").WithGeneration(1).WithLimited(5).Object(),
   161  			bootstrap:         newPLConfiguration("foo").WithGeneration(1).WithLimited(5).Object(),
   162  			newObjectExpected: nil,
   163  		},
   164  		{
   165  			name:              "auto update is enabled, second generation, spec does not match - spec update expected",
   166  			current:           newPLConfiguration("foo").WithAutoUpdateAnnotation("true").WithGeneration(2).WithLimited(5).Object(),
   167  			bootstrap:         newPLConfiguration("foo").WithLimited(10).Object(),
   168  			newObjectExpected: newPLConfiguration("foo").WithAutoUpdateAnnotation("true").WithGeneration(2).WithLimited(10).Object(),
   169  		},
   170  		{
   171  			name:              "auto update is enabled, second generation, spec matches - no update expected",
   172  			current:           newPLConfiguration("foo").WithAutoUpdateAnnotation("true").WithGeneration(2).WithLimited(5).Object(),
   173  			bootstrap:         newPLConfiguration("foo").WithLimited(5).Object(),
   174  			newObjectExpected: nil,
   175  		},
   176  		{
   177  			name:              "auto update is disabled, first generation, spec does not match - no update expected",
   178  			current:           newPLConfiguration("foo").WithAutoUpdateAnnotation("false").WithGeneration(1).WithLimited(5).Object(),
   179  			bootstrap:         newPLConfiguration("foo").WithLimited(10).Object(),
   180  			newObjectExpected: nil,
   181  		},
   182  		{
   183  			name:              "auto update is disabled, first generation, spec matches - no update expected",
   184  			current:           newPLConfiguration("foo").WithAutoUpdateAnnotation("false").WithGeneration(1).WithLimited(5).Object(),
   185  			bootstrap:         newPLConfiguration("foo").WithLimited(5).Object(),
   186  			newObjectExpected: nil,
   187  		},
   188  		{
   189  			name:              "auto update is disabled, second generation, spec does not match - no update expected",
   190  			current:           newPLConfiguration("foo").WithAutoUpdateAnnotation("false").WithGeneration(2).WithLimited(5).Object(),
   191  			bootstrap:         newPLConfiguration("foo").WithLimited(10).Object(),
   192  			newObjectExpected: nil,
   193  		},
   194  		{
   195  			name:              "auto update is disabled, second generation, spec matches - no update expected",
   196  			current:           newPLConfiguration("foo").WithAutoUpdateAnnotation("false").WithGeneration(2).WithLimited(5).Object(),
   197  			bootstrap:         newPLConfiguration("foo").WithLimited(5).Object(),
   198  			newObjectExpected: nil,
   199  		},
   200  		{
   201  			name:              "annotation is missing, first generation, spec does not match - both annotation and spec update expected",
   202  			current:           newPLConfiguration("foo").WithGeneration(1).WithLimited(5).Object(),
   203  			bootstrap:         newPLConfiguration("foo").WithLimited(10).Object(),
   204  			newObjectExpected: newPLConfiguration("foo").WithAutoUpdateAnnotation("true").WithGeneration(1).WithLimited(10).Object(),
   205  		},
   206  		{
   207  			name:              "annotation is missing, first generation, spec matches - annotation update is expected",
   208  			current:           newPLConfiguration("foo").WithGeneration(1).WithLimited(5).Object(),
   209  			bootstrap:         newPLConfiguration("foo").WithLimited(5).Object(),
   210  			newObjectExpected: newPLConfiguration("foo").WithAutoUpdateAnnotation("true").WithGeneration(1).WithLimited(5).Object(),
   211  		},
   212  		{
   213  			name:              "annotation is missing, second generation, spec does not match - annotation update is expected",
   214  			current:           newPLConfiguration("foo").WithGeneration(2).WithLimited(5).Object(),
   215  			bootstrap:         newPLConfiguration("foo").WithLimited(10).Object(),
   216  			newObjectExpected: newPLConfiguration("foo").WithAutoUpdateAnnotation("false").WithGeneration(2).WithLimited(5).Object(),
   217  		},
   218  		{
   219  			name:              "annotation is missing, second generation, spec matches - annotation update is expected",
   220  			current:           newPLConfiguration("foo").WithGeneration(2).WithLimited(5).Object(),
   221  			bootstrap:         newPLConfiguration("foo").WithLimited(5).Object(),
   222  			newObjectExpected: newPLConfiguration("foo").WithAutoUpdateAnnotation("false").WithGeneration(2).WithLimited(5).Object(),
   223  		},
   224  	}
   225  
   226  	ops := NewPriorityLevelConfigurationOps(nil, nil)
   227  	for _, test := range tests {
   228  		t.Run(test.name, func(t *testing.T) {
   229  			strategy := NewSuggestedEnsureStrategy[*flowcontrolv1.PriorityLevelConfiguration]()
   230  			updatableGot, updateGot, err := strategy.ReviseIfNeeded(ops, test.current, test.bootstrap)
   231  			if err != nil {
   232  				t.Errorf("Expected no error, but got: %v", err)
   233  			}
   234  			if test.newObjectExpected == nil {
   235  				if updatableGot != nil {
   236  					t.Errorf("Expected a nil object, but got: %#v", updatableGot)
   237  				}
   238  				if updateGot {
   239  					t.Errorf("Expected update=%t but got: %t", false, updateGot)
   240  				}
   241  				return
   242  			}
   243  
   244  			if !updateGot {
   245  				t.Errorf("Expected update=%t but got: %t", true, updateGot)
   246  			}
   247  			if !reflect.DeepEqual(test.newObjectExpected, updatableGot) {
   248  				t.Errorf("Expected the object to be updated to match - diff: %s", cmp.Diff(test.newObjectExpected, updatableGot))
   249  			}
   250  		})
   251  	}
   252  }
   253  
   254  func TestPriorityLevelSpecChanged(t *testing.T) {
   255  	pl1 := &flowcontrolv1.PriorityLevelConfiguration{
   256  		Spec: flowcontrolv1.PriorityLevelConfigurationSpec{
   257  			Type: flowcontrolv1.PriorityLevelEnablementLimited,
   258  			Limited: &flowcontrolv1.LimitedPriorityLevelConfiguration{
   259  				LimitResponse: flowcontrolv1.LimitResponse{
   260  					Type: flowcontrolv1.LimitResponseTypeReject,
   261  				},
   262  			},
   263  		},
   264  	}
   265  	pl2 := &flowcontrolv1.PriorityLevelConfiguration{
   266  		Spec: flowcontrolv1.PriorityLevelConfigurationSpec{
   267  			Type: flowcontrolv1.PriorityLevelEnablementLimited,
   268  			Limited: &flowcontrolv1.LimitedPriorityLevelConfiguration{
   269  				NominalConcurrencyShares: ptr.To(int32(1)),
   270  			},
   271  		},
   272  	}
   273  	pl1Defaulted := &flowcontrolv1.PriorityLevelConfiguration{
   274  		Spec: flowcontrolv1.PriorityLevelConfigurationSpec{
   275  			Type: flowcontrolv1.PriorityLevelEnablementLimited,
   276  			Limited: &flowcontrolv1.LimitedPriorityLevelConfiguration{
   277  				NominalConcurrencyShares: ptr.To(flowcontrolapisv1.PriorityLevelConfigurationDefaultNominalConcurrencyShares),
   278  				LendablePercent:          pointer.Int32(0),
   279  				LimitResponse: flowcontrolv1.LimitResponse{
   280  					Type: flowcontrolv1.LimitResponseTypeReject,
   281  				},
   282  			},
   283  		},
   284  	}
   285  	ple1 := &flowcontrolv1.PriorityLevelConfiguration{
   286  		ObjectMeta: metav1.ObjectMeta{Name: "exempt"},
   287  		Spec: flowcontrolv1.PriorityLevelConfigurationSpec{
   288  			Type: flowcontrolv1.PriorityLevelEnablementExempt,
   289  			Exempt: &flowcontrolv1.ExemptPriorityLevelConfiguration{
   290  				NominalConcurrencyShares: pointer.Int32(42),
   291  				LendablePercent:          pointer.Int32(33),
   292  			},
   293  		},
   294  	}
   295  	ple2 := &flowcontrolv1.PriorityLevelConfiguration{
   296  		ObjectMeta: metav1.ObjectMeta{Name: "exempt"},
   297  		Spec: flowcontrolv1.PriorityLevelConfigurationSpec{
   298  			Type: flowcontrolv1.PriorityLevelEnablementExempt,
   299  			Exempt: &flowcontrolv1.ExemptPriorityLevelConfiguration{
   300  				NominalConcurrencyShares: pointer.Int32(24),
   301  				LendablePercent:          pointer.Int32(86),
   302  			},
   303  		},
   304  	}
   305  	pleWrong := &flowcontrolv1.PriorityLevelConfiguration{
   306  		ObjectMeta: metav1.ObjectMeta{Name: "exempt"},
   307  		Spec: flowcontrolv1.PriorityLevelConfigurationSpec{
   308  			Type: flowcontrolv1.PriorityLevelEnablementLimited,
   309  			Limited: &flowcontrolv1.LimitedPriorityLevelConfiguration{
   310  				NominalConcurrencyShares: ptr.To(int32(1)),
   311  			},
   312  		},
   313  	}
   314  	pleInvalid := &flowcontrolv1.PriorityLevelConfiguration{
   315  		ObjectMeta: metav1.ObjectMeta{Name: "exempt"},
   316  		Spec: flowcontrolv1.PriorityLevelConfigurationSpec{
   317  			Type: "widget",
   318  		},
   319  	}
   320  	testCases := []struct {
   321  		name        string
   322  		expected    *flowcontrolv1.PriorityLevelConfiguration
   323  		actual      *flowcontrolv1.PriorityLevelConfiguration
   324  		specChanged bool
   325  	}{
   326  		{
   327  			name:        "identical priority-level should work",
   328  			expected:    bootstrap.MandatoryPriorityLevelConfigurationCatchAll,
   329  			actual:      bootstrap.MandatoryPriorityLevelConfigurationCatchAll,
   330  			specChanged: false,
   331  		},
   332  		{
   333  			name:        "defaulted priority-level should work",
   334  			expected:    pl1,
   335  			actual:      pl1Defaulted,
   336  			specChanged: false,
   337  		},
   338  		{
   339  			name:        "non-defaulted priority-level has wrong spec",
   340  			expected:    pl1,
   341  			actual:      pl2,
   342  			specChanged: true,
   343  		},
   344  		{
   345  			name:        "tweaked exempt config",
   346  			expected:    ple1,
   347  			actual:      ple2,
   348  			specChanged: false,
   349  		},
   350  		{
   351  			name:        "exempt with wrong tag",
   352  			expected:    ple1,
   353  			actual:      pleWrong,
   354  			specChanged: true,
   355  		},
   356  		{
   357  			name:        "exempt with invalid tag",
   358  			expected:    ple1,
   359  			actual:      pleInvalid,
   360  			specChanged: true,
   361  		},
   362  	}
   363  	for _, testCase := range testCases {
   364  		t.Run(testCase.name, func(t *testing.T) {
   365  			w := !plcSpecEqualish(testCase.expected, testCase.actual)
   366  			if testCase.specChanged != w {
   367  				t.Errorf("Expected priorityLevelSpecChanged to return %t, but got: %t - diff: %s", testCase.specChanged, w,
   368  					cmp.Diff(testCase.expected, testCase.actual))
   369  			}
   370  		})
   371  	}
   372  }
   373  
   374  func TestRemovePriorityLevelConfiguration(t *testing.T) {
   375  	tests := []struct {
   376  		name           string
   377  		current        *flowcontrolv1.PriorityLevelConfiguration
   378  		bootstrapName  string
   379  		removeExpected bool
   380  	}{
   381  		{
   382  			name:          "no priority level configuration objects exist",
   383  			bootstrapName: "pl1",
   384  			current:       nil,
   385  		},
   386  		{
   387  			name:           "priority level configuration not wanted, auto update is enabled",
   388  			bootstrapName:  "pl0",
   389  			current:        newPLConfiguration("pl1").WithAutoUpdateAnnotation("true").Object(),
   390  			removeExpected: true,
   391  		},
   392  		{
   393  			name:           "priority level configuration not wanted, auto update is disabled",
   394  			bootstrapName:  "pl0",
   395  			current:        newPLConfiguration("pl1").WithAutoUpdateAnnotation("false").Object(),
   396  			removeExpected: false,
   397  		},
   398  		{
   399  			name:           "priority level configuration not wanted, the auto-update annotation is malformed",
   400  			bootstrapName:  "pl0",
   401  			current:        newPLConfiguration("pl1").WithAutoUpdateAnnotation("invalid").Object(),
   402  			removeExpected: false,
   403  		},
   404  		{
   405  			name:           "priority level configuration wanted, auto update is enabled",
   406  			bootstrapName:  "pl1",
   407  			current:        newPLConfiguration("pl1").WithAutoUpdateAnnotation("true").Object(),
   408  			removeExpected: false,
   409  		},
   410  		{
   411  			name:           "priority level configuration wanted, auto update is disabled",
   412  			bootstrapName:  "pl1",
   413  			current:        newPLConfiguration("pl1").WithAutoUpdateAnnotation("false").Object(),
   414  			removeExpected: false,
   415  		},
   416  		{
   417  			name:           "priority level configuration wanted, the auto-update annotation is malformed",
   418  			bootstrapName:  "pl1",
   419  			current:        newPLConfiguration("pl1").WithAutoUpdateAnnotation("invalid").Object(),
   420  			removeExpected: false,
   421  		},
   422  	}
   423  
   424  	for _, test := range tests {
   425  		t.Run(test.name, func(t *testing.T) {
   426  			client := fake.NewSimpleClientset().FlowcontrolV1().PriorityLevelConfigurations()
   427  			indexer := toolscache.NewIndexer(toolscache.MetaNamespaceKeyFunc, toolscache.Indexers{})
   428  			if test.current != nil {
   429  				client.Create(context.TODO(), test.current, metav1.CreateOptions{})
   430  				indexer.Add(test.current)
   431  			}
   432  
   433  			boot := newPLConfiguration(test.bootstrapName).Object()
   434  			boots := []*flowcontrolv1.PriorityLevelConfiguration{boot}
   435  			ops := NewPriorityLevelConfigurationOps(client, flowcontrollisters.NewPriorityLevelConfigurationLister(indexer))
   436  			err := RemoveUnwantedObjects(context.Background(), ops, boots)
   437  			if err != nil {
   438  				t.Fatalf("Expected no error, but got: %v", err)
   439  			}
   440  
   441  			if test.current == nil {
   442  				return
   443  			}
   444  			_, err = client.Get(context.TODO(), test.current.Name, metav1.GetOptions{})
   445  			switch {
   446  			case test.removeExpected:
   447  				if !apierrors.IsNotFound(err) {
   448  					t.Errorf("Expected error: %q, but got: %v", metav1.StatusReasonNotFound, err)
   449  				}
   450  			default:
   451  				if err != nil {
   452  					t.Errorf("Expected no error, but got: %v", err)
   453  				}
   454  			}
   455  		})
   456  	}
   457  }
   458  
   459  type plBuilder struct {
   460  	object *flowcontrolv1.PriorityLevelConfiguration
   461  }
   462  
   463  func newPLConfiguration(name string) *plBuilder {
   464  	return &plBuilder{
   465  		object: &flowcontrolv1.PriorityLevelConfiguration{
   466  			ObjectMeta: metav1.ObjectMeta{
   467  				Name: name,
   468  			},
   469  		},
   470  	}
   471  }
   472  
   473  func (b *plBuilder) Object() *flowcontrolv1.PriorityLevelConfiguration {
   474  	return b.object
   475  }
   476  
   477  func (b *plBuilder) WithGeneration(value int64) *plBuilder {
   478  	b.object.SetGeneration(value)
   479  	return b
   480  }
   481  
   482  func (b *plBuilder) WithAutoUpdateAnnotation(value string) *plBuilder {
   483  	setAnnotation(b.object, value)
   484  	return b
   485  }
   486  
   487  func (b *plBuilder) WithLimited(nominalConcurrencyShares int32) *plBuilder {
   488  	b.object.Spec.Type = flowcontrolv1.PriorityLevelEnablementLimited
   489  	b.object.Spec.Limited = &flowcontrolv1.LimitedPriorityLevelConfiguration{
   490  		NominalConcurrencyShares: ptr.To(nominalConcurrencyShares),
   491  		LendablePercent:          pointer.Int32(0),
   492  		LimitResponse: flowcontrolv1.LimitResponse{
   493  			Type: flowcontrolv1.LimitResponseTypeReject,
   494  		},
   495  	}
   496  	return b
   497  }
   498  
   499  // must be called after WithLimited
   500  func (b *plBuilder) WithQueuing(queues, handSize, queueLengthLimit int32) *plBuilder {
   501  	limited := b.object.Spec.Limited
   502  	if limited == nil {
   503  		return b
   504  	}
   505  
   506  	limited.LimitResponse.Type = flowcontrolv1.LimitResponseTypeQueue
   507  	limited.LimitResponse.Queuing = &flowcontrolv1.QueuingConfiguration{
   508  		Queues:           queues,
   509  		HandSize:         handSize,
   510  		QueueLengthLimit: queueLengthLimit,
   511  	}
   512  
   513  	return b
   514  }
   515  

View as plain text