Merge pull request #118782 from MikeSpreitzer/exempt-borrowing-impl

Exempt borrowing implementation
This commit is contained in:
Kubernetes Prow Robot
2023-07-14 09:16:00 -07:00
committed by GitHub
73 changed files with 3165 additions and 544 deletions

View File

@@ -33,5 +33,16 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
obj.LendablePercent = &i
}
},
func(obj *flowcontrol.ExemptPriorityLevelConfiguration, c fuzz.Continue) {
c.FuzzNoCustom(obj) // fuzz self without calling this function again
if obj.NominalConcurrencyShares == nil {
i := int32(0)
obj.NominalConcurrencyShares = &i
}
if obj.LendablePercent == nil {
i := int32(0)
obj.LendablePercent = &i
}
},
}
}

View File

@@ -377,6 +377,14 @@ type PriorityLevelConfigurationSpec struct {
// This field must be non-empty if and only if `type` is `"Limited"`.
// +optional
Limited *LimitedPriorityLevelConfiguration
// `exempt` specifies how requests are handled for an exempt priority level.
// This field MUST be empty if `type` is `"Limited"`.
// This field MAY be non-empty if `type` is `"Exempt"`.
// If empty and `type` is `"Exempt"` then the default values
// for `ExemptPriorityLevelConfiguration` apply.
// +optional
Exempt *ExemptPriorityLevelConfiguration
}
// PriorityLevelEnablement indicates whether limits on execution are enabled for the priority level
@@ -406,10 +414,10 @@ type LimitedPriorityLevelConfiguration struct {
// Limited priority levels in proportion to their NCS values:
//
// NominalCL(i) = ceil( ServerCL * NCS(i) / sum_ncs )
// sum_ncs = sum[limited priority level k] NCS(k)
// sum_ncs = sum[priority level k] NCS(k)
//
// Bigger numbers mean a larger nominal concurrency limit,
// at the expense of every other Limited priority level.
// at the expense of every other priority level.
// This field has a default value of 30.
// +optional
NominalConcurrencyShares int32
@@ -447,6 +455,43 @@ type LimitedPriorityLevelConfiguration struct {
BorrowingLimitPercent *int32
}
// ExemptPriorityLevelConfiguration describes the configurable aspects
// of the handling of exempt requests.
// In the mandatory exempt configuration object the values in the fields
// here can be modified by authorized users, unlike the rest of the `spec`.
type ExemptPriorityLevelConfiguration struct {
// `nominalConcurrencyShares` (NCS) contributes to the computation of the
// NominalConcurrencyLimit (NominalCL) of this level.
// This is the number of execution seats nominally reserved for this priority level.
// This DOES NOT limit the dispatching from this priority level
// but affects the other priority levels through the borrowing mechanism.
// The server's concurrency limit (ServerCL) is divided among all the
// priority levels in proportion to their NCS values:
//
// NominalCL(i) = ceil( ServerCL * NCS(i) / sum_ncs )
// sum_ncs = sum[priority level k] NCS(k)
//
// Bigger numbers mean a larger nominal concurrency limit,
// at the expense of every other priority level.
// This field has a default value of zero.
// +optional
NominalConcurrencyShares *int32
// `lendablePercent` prescribes the fraction of the level's NominalCL that
// can be borrowed by other priority levels. This value of this
// field must be between 0 and 100, inclusive, and it defaults to 0.
// The number of seats that other levels can borrow from this level, known
// as this level's LendableConcurrencyLimit (LendableCL), is defined as follows.
//
// LendableCL(i) = round( NominalCL(i) * lendablePercent(i)/100.0 )
//
// +optional
LendablePercent *int32
// The `BorrowingCL` of an Exempt priority level is implicitly `ServerCL`.
// In other words, an exempt priority level
// has no meaningful limit on how much it borrows.
// There is no explicit representation of that here.
}
// LimitResponse defines how to handle requests that can not be executed right now.
// +union
type LimitResponse struct {

View File

@@ -40,6 +40,17 @@ func SetDefaults_FlowSchemaSpec(spec *v1alpha1.FlowSchemaSpec) {
}
}
func SetDefaults_ExemptPriorityLevelConfiguration(eplc *v1alpha1.ExemptPriorityLevelConfiguration) {
if eplc.NominalConcurrencyShares == nil {
eplc.NominalConcurrencyShares = new(int32)
*eplc.NominalConcurrencyShares = 0
}
if eplc.LendablePercent == nil {
eplc.LendablePercent = new(int32)
*eplc.LendablePercent = 0
}
}
func SetDefaults_LimitedPriorityLevelConfiguration(lplc *v1alpha1.LimitedPriorityLevelConfiguration) {
if lplc.AssuredConcurrencyShares == 0 {
lplc.AssuredConcurrencyShares = PriorityLevelConfigurationDefaultAssuredConcurrencyShares

View File

@@ -33,6 +33,24 @@ func TestDefaultWithPriorityLevelConfiguration(t *testing.T) {
original runtime.Object
expected runtime.Object
}{
{
name: "Defaulting for Exempt",
original: &flowcontrolv1alpha1.PriorityLevelConfiguration{
Spec: flowcontrolv1alpha1.PriorityLevelConfigurationSpec{
Type: flowcontrolv1alpha1.PriorityLevelEnablementExempt,
Exempt: &flowcontrolv1alpha1.ExemptPriorityLevelConfiguration{},
},
},
expected: &flowcontrolv1alpha1.PriorityLevelConfiguration{
Spec: flowcontrolv1alpha1.PriorityLevelConfigurationSpec{
Type: flowcontrolv1alpha1.PriorityLevelEnablementExempt,
Exempt: &flowcontrolv1alpha1.ExemptPriorityLevelConfiguration{
NominalConcurrencyShares: pointer.Int32(0),
LendablePercent: pointer.Int32(0),
},
},
},
},
{
name: "LendablePercent is not specified, should default to zero",
original: &flowcontrolv1alpha1.PriorityLevelConfiguration{

View File

@@ -37,6 +37,16 @@ func init() {
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(s *runtime.Scheme) error {
if err := s.AddGeneratedConversionFunc((*v1alpha1.ExemptPriorityLevelConfiguration)(nil), (*flowcontrol.ExemptPriorityLevelConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_ExemptPriorityLevelConfiguration_To_flowcontrol_ExemptPriorityLevelConfiguration(a.(*v1alpha1.ExemptPriorityLevelConfiguration), b.(*flowcontrol.ExemptPriorityLevelConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*flowcontrol.ExemptPriorityLevelConfiguration)(nil), (*v1alpha1.ExemptPriorityLevelConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_flowcontrol_ExemptPriorityLevelConfiguration_To_v1alpha1_ExemptPriorityLevelConfiguration(a.(*flowcontrol.ExemptPriorityLevelConfiguration), b.(*v1alpha1.ExemptPriorityLevelConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1alpha1.FlowDistinguisherMethod)(nil), (*flowcontrol.FlowDistinguisherMethod)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1alpha1_FlowDistinguisherMethod_To_flowcontrol_FlowDistinguisherMethod(a.(*v1alpha1.FlowDistinguisherMethod), b.(*flowcontrol.FlowDistinguisherMethod), scope)
}); err != nil {
@@ -260,6 +270,28 @@ func RegisterConversions(s *runtime.Scheme) error {
return nil
}
func autoConvert_v1alpha1_ExemptPriorityLevelConfiguration_To_flowcontrol_ExemptPriorityLevelConfiguration(in *v1alpha1.ExemptPriorityLevelConfiguration, out *flowcontrol.ExemptPriorityLevelConfiguration, s conversion.Scope) error {
out.NominalConcurrencyShares = (*int32)(unsafe.Pointer(in.NominalConcurrencyShares))
out.LendablePercent = (*int32)(unsafe.Pointer(in.LendablePercent))
return nil
}
// Convert_v1alpha1_ExemptPriorityLevelConfiguration_To_flowcontrol_ExemptPriorityLevelConfiguration is an autogenerated conversion function.
func Convert_v1alpha1_ExemptPriorityLevelConfiguration_To_flowcontrol_ExemptPriorityLevelConfiguration(in *v1alpha1.ExemptPriorityLevelConfiguration, out *flowcontrol.ExemptPriorityLevelConfiguration, s conversion.Scope) error {
return autoConvert_v1alpha1_ExemptPriorityLevelConfiguration_To_flowcontrol_ExemptPriorityLevelConfiguration(in, out, s)
}
func autoConvert_flowcontrol_ExemptPriorityLevelConfiguration_To_v1alpha1_ExemptPriorityLevelConfiguration(in *flowcontrol.ExemptPriorityLevelConfiguration, out *v1alpha1.ExemptPriorityLevelConfiguration, s conversion.Scope) error {
out.NominalConcurrencyShares = (*int32)(unsafe.Pointer(in.NominalConcurrencyShares))
out.LendablePercent = (*int32)(unsafe.Pointer(in.LendablePercent))
return nil
}
// Convert_flowcontrol_ExemptPriorityLevelConfiguration_To_v1alpha1_ExemptPriorityLevelConfiguration is an autogenerated conversion function.
func Convert_flowcontrol_ExemptPriorityLevelConfiguration_To_v1alpha1_ExemptPriorityLevelConfiguration(in *flowcontrol.ExemptPriorityLevelConfiguration, out *v1alpha1.ExemptPriorityLevelConfiguration, s conversion.Scope) error {
return autoConvert_flowcontrol_ExemptPriorityLevelConfiguration_To_v1alpha1_ExemptPriorityLevelConfiguration(in, out, s)
}
func autoConvert_v1alpha1_FlowDistinguisherMethod_To_flowcontrol_FlowDistinguisherMethod(in *v1alpha1.FlowDistinguisherMethod, out *flowcontrol.FlowDistinguisherMethod, s conversion.Scope) error {
out.Type = flowcontrol.FlowDistinguisherMethodType(in.Type)
return nil
@@ -653,6 +685,7 @@ func autoConvert_v1alpha1_PriorityLevelConfigurationSpec_To_flowcontrol_Priority
} else {
out.Limited = nil
}
out.Exempt = (*flowcontrol.ExemptPriorityLevelConfiguration)(unsafe.Pointer(in.Exempt))
return nil
}
@@ -672,6 +705,7 @@ func autoConvert_flowcontrol_PriorityLevelConfigurationSpec_To_v1alpha1_Priority
} else {
out.Limited = nil
}
out.Exempt = (*v1alpha1.ExemptPriorityLevelConfiguration)(unsafe.Pointer(in.Exempt))
return nil
}

View File

@@ -59,6 +59,9 @@ func SetObjectDefaults_PriorityLevelConfiguration(in *v1alpha1.PriorityLevelConf
SetDefaults_QueuingConfiguration(in.Spec.Limited.LimitResponse.Queuing)
}
}
if in.Spec.Exempt != nil {
SetDefaults_ExemptPriorityLevelConfiguration(in.Spec.Exempt)
}
}
func SetObjectDefaults_PriorityLevelConfigurationList(in *v1alpha1.PriorityLevelConfigurationList) {

View File

@@ -40,6 +40,17 @@ func SetDefaults_FlowSchemaSpec(spec *v1beta1.FlowSchemaSpec) {
}
}
func SetDefaults_ExemptPriorityLevelConfiguration(eplc *v1beta1.ExemptPriorityLevelConfiguration) {
if eplc.NominalConcurrencyShares == nil {
eplc.NominalConcurrencyShares = new(int32)
*eplc.NominalConcurrencyShares = 0
}
if eplc.LendablePercent == nil {
eplc.LendablePercent = new(int32)
*eplc.LendablePercent = 0
}
}
func SetDefaults_LimitedPriorityLevelConfiguration(lplc *v1beta1.LimitedPriorityLevelConfiguration) {
if lplc.AssuredConcurrencyShares == 0 {
lplc.AssuredConcurrencyShares = PriorityLevelConfigurationDefaultAssuredConcurrencyShares

View File

@@ -33,6 +33,24 @@ func TestDefaultWithPriorityLevelConfiguration(t *testing.T) {
original runtime.Object
expected runtime.Object
}{
{
name: "Defaulting for Exempt",
original: &flowcontrolv1beta1.PriorityLevelConfiguration{
Spec: flowcontrolv1beta1.PriorityLevelConfigurationSpec{
Type: flowcontrolv1beta1.PriorityLevelEnablementExempt,
Exempt: &flowcontrolv1beta1.ExemptPriorityLevelConfiguration{},
},
},
expected: &flowcontrolv1beta1.PriorityLevelConfiguration{
Spec: flowcontrolv1beta1.PriorityLevelConfigurationSpec{
Type: flowcontrolv1beta1.PriorityLevelEnablementExempt,
Exempt: &flowcontrolv1beta1.ExemptPriorityLevelConfiguration{
NominalConcurrencyShares: pointer.Int32(0),
LendablePercent: pointer.Int32(0),
},
},
},
},
{
name: "LendablePercent is not specified, should default to zero",
original: &flowcontrolv1beta1.PriorityLevelConfiguration{

View File

@@ -37,6 +37,16 @@ func init() {
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(s *runtime.Scheme) error {
if err := s.AddGeneratedConversionFunc((*v1beta1.ExemptPriorityLevelConfiguration)(nil), (*flowcontrol.ExemptPriorityLevelConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_ExemptPriorityLevelConfiguration_To_flowcontrol_ExemptPriorityLevelConfiguration(a.(*v1beta1.ExemptPriorityLevelConfiguration), b.(*flowcontrol.ExemptPriorityLevelConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*flowcontrol.ExemptPriorityLevelConfiguration)(nil), (*v1beta1.ExemptPriorityLevelConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_flowcontrol_ExemptPriorityLevelConfiguration_To_v1beta1_ExemptPriorityLevelConfiguration(a.(*flowcontrol.ExemptPriorityLevelConfiguration), b.(*v1beta1.ExemptPriorityLevelConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1beta1.FlowDistinguisherMethod)(nil), (*flowcontrol.FlowDistinguisherMethod)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta1_FlowDistinguisherMethod_To_flowcontrol_FlowDistinguisherMethod(a.(*v1beta1.FlowDistinguisherMethod), b.(*flowcontrol.FlowDistinguisherMethod), scope)
}); err != nil {
@@ -260,6 +270,28 @@ func RegisterConversions(s *runtime.Scheme) error {
return nil
}
func autoConvert_v1beta1_ExemptPriorityLevelConfiguration_To_flowcontrol_ExemptPriorityLevelConfiguration(in *v1beta1.ExemptPriorityLevelConfiguration, out *flowcontrol.ExemptPriorityLevelConfiguration, s conversion.Scope) error {
out.NominalConcurrencyShares = (*int32)(unsafe.Pointer(in.NominalConcurrencyShares))
out.LendablePercent = (*int32)(unsafe.Pointer(in.LendablePercent))
return nil
}
// Convert_v1beta1_ExemptPriorityLevelConfiguration_To_flowcontrol_ExemptPriorityLevelConfiguration is an autogenerated conversion function.
func Convert_v1beta1_ExemptPriorityLevelConfiguration_To_flowcontrol_ExemptPriorityLevelConfiguration(in *v1beta1.ExemptPriorityLevelConfiguration, out *flowcontrol.ExemptPriorityLevelConfiguration, s conversion.Scope) error {
return autoConvert_v1beta1_ExemptPriorityLevelConfiguration_To_flowcontrol_ExemptPriorityLevelConfiguration(in, out, s)
}
func autoConvert_flowcontrol_ExemptPriorityLevelConfiguration_To_v1beta1_ExemptPriorityLevelConfiguration(in *flowcontrol.ExemptPriorityLevelConfiguration, out *v1beta1.ExemptPriorityLevelConfiguration, s conversion.Scope) error {
out.NominalConcurrencyShares = (*int32)(unsafe.Pointer(in.NominalConcurrencyShares))
out.LendablePercent = (*int32)(unsafe.Pointer(in.LendablePercent))
return nil
}
// Convert_flowcontrol_ExemptPriorityLevelConfiguration_To_v1beta1_ExemptPriorityLevelConfiguration is an autogenerated conversion function.
func Convert_flowcontrol_ExemptPriorityLevelConfiguration_To_v1beta1_ExemptPriorityLevelConfiguration(in *flowcontrol.ExemptPriorityLevelConfiguration, out *v1beta1.ExemptPriorityLevelConfiguration, s conversion.Scope) error {
return autoConvert_flowcontrol_ExemptPriorityLevelConfiguration_To_v1beta1_ExemptPriorityLevelConfiguration(in, out, s)
}
func autoConvert_v1beta1_FlowDistinguisherMethod_To_flowcontrol_FlowDistinguisherMethod(in *v1beta1.FlowDistinguisherMethod, out *flowcontrol.FlowDistinguisherMethod, s conversion.Scope) error {
out.Type = flowcontrol.FlowDistinguisherMethodType(in.Type)
return nil
@@ -653,6 +685,7 @@ func autoConvert_v1beta1_PriorityLevelConfigurationSpec_To_flowcontrol_PriorityL
} else {
out.Limited = nil
}
out.Exempt = (*flowcontrol.ExemptPriorityLevelConfiguration)(unsafe.Pointer(in.Exempt))
return nil
}
@@ -672,6 +705,7 @@ func autoConvert_flowcontrol_PriorityLevelConfigurationSpec_To_v1beta1_PriorityL
} else {
out.Limited = nil
}
out.Exempt = (*v1beta1.ExemptPriorityLevelConfiguration)(unsafe.Pointer(in.Exempt))
return nil
}

View File

@@ -59,6 +59,9 @@ func SetObjectDefaults_PriorityLevelConfiguration(in *v1beta1.PriorityLevelConfi
SetDefaults_QueuingConfiguration(in.Spec.Limited.LimitResponse.Queuing)
}
}
if in.Spec.Exempt != nil {
SetDefaults_ExemptPriorityLevelConfiguration(in.Spec.Exempt)
}
}
func SetObjectDefaults_PriorityLevelConfigurationList(in *v1beta1.PriorityLevelConfigurationList) {

View File

@@ -40,6 +40,17 @@ func SetDefaults_FlowSchemaSpec(spec *v1beta2.FlowSchemaSpec) {
}
}
func SetDefaults_ExemptPriorityLevelConfiguration(eplc *v1beta2.ExemptPriorityLevelConfiguration) {
if eplc.NominalConcurrencyShares == nil {
eplc.NominalConcurrencyShares = new(int32)
*eplc.NominalConcurrencyShares = 0
}
if eplc.LendablePercent == nil {
eplc.LendablePercent = new(int32)
*eplc.LendablePercent = 0
}
}
func SetDefaults_LimitedPriorityLevelConfiguration(lplc *v1beta2.LimitedPriorityLevelConfiguration) {
if lplc.AssuredConcurrencyShares == 0 {
lplc.AssuredConcurrencyShares = PriorityLevelConfigurationDefaultAssuredConcurrencyShares

View File

@@ -33,6 +33,24 @@ func TestDefaultWithPriorityLevelConfiguration(t *testing.T) {
original runtime.Object
expected runtime.Object
}{
{
name: "Defaulting for Exempt",
original: &flowcontrolv1beta2.PriorityLevelConfiguration{
Spec: flowcontrolv1beta2.PriorityLevelConfigurationSpec{
Type: flowcontrolv1beta2.PriorityLevelEnablementExempt,
Exempt: &flowcontrolv1beta2.ExemptPriorityLevelConfiguration{},
},
},
expected: &flowcontrolv1beta2.PriorityLevelConfiguration{
Spec: flowcontrolv1beta2.PriorityLevelConfigurationSpec{
Type: flowcontrolv1beta2.PriorityLevelEnablementExempt,
Exempt: &flowcontrolv1beta2.ExemptPriorityLevelConfiguration{
NominalConcurrencyShares: pointer.Int32(0),
LendablePercent: pointer.Int32(0),
},
},
},
},
{
name: "LendablePercent is not specified, should default to zero",
original: &flowcontrolv1beta2.PriorityLevelConfiguration{

View File

@@ -37,6 +37,16 @@ func init() {
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(s *runtime.Scheme) error {
if err := s.AddGeneratedConversionFunc((*v1beta2.ExemptPriorityLevelConfiguration)(nil), (*flowcontrol.ExemptPriorityLevelConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta2_ExemptPriorityLevelConfiguration_To_flowcontrol_ExemptPriorityLevelConfiguration(a.(*v1beta2.ExemptPriorityLevelConfiguration), b.(*flowcontrol.ExemptPriorityLevelConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*flowcontrol.ExemptPriorityLevelConfiguration)(nil), (*v1beta2.ExemptPriorityLevelConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_flowcontrol_ExemptPriorityLevelConfiguration_To_v1beta2_ExemptPriorityLevelConfiguration(a.(*flowcontrol.ExemptPriorityLevelConfiguration), b.(*v1beta2.ExemptPriorityLevelConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1beta2.FlowDistinguisherMethod)(nil), (*flowcontrol.FlowDistinguisherMethod)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta2_FlowDistinguisherMethod_To_flowcontrol_FlowDistinguisherMethod(a.(*v1beta2.FlowDistinguisherMethod), b.(*flowcontrol.FlowDistinguisherMethod), scope)
}); err != nil {
@@ -260,6 +270,28 @@ func RegisterConversions(s *runtime.Scheme) error {
return nil
}
func autoConvert_v1beta2_ExemptPriorityLevelConfiguration_To_flowcontrol_ExemptPriorityLevelConfiguration(in *v1beta2.ExemptPriorityLevelConfiguration, out *flowcontrol.ExemptPriorityLevelConfiguration, s conversion.Scope) error {
out.NominalConcurrencyShares = (*int32)(unsafe.Pointer(in.NominalConcurrencyShares))
out.LendablePercent = (*int32)(unsafe.Pointer(in.LendablePercent))
return nil
}
// Convert_v1beta2_ExemptPriorityLevelConfiguration_To_flowcontrol_ExemptPriorityLevelConfiguration is an autogenerated conversion function.
func Convert_v1beta2_ExemptPriorityLevelConfiguration_To_flowcontrol_ExemptPriorityLevelConfiguration(in *v1beta2.ExemptPriorityLevelConfiguration, out *flowcontrol.ExemptPriorityLevelConfiguration, s conversion.Scope) error {
return autoConvert_v1beta2_ExemptPriorityLevelConfiguration_To_flowcontrol_ExemptPriorityLevelConfiguration(in, out, s)
}
func autoConvert_flowcontrol_ExemptPriorityLevelConfiguration_To_v1beta2_ExemptPriorityLevelConfiguration(in *flowcontrol.ExemptPriorityLevelConfiguration, out *v1beta2.ExemptPriorityLevelConfiguration, s conversion.Scope) error {
out.NominalConcurrencyShares = (*int32)(unsafe.Pointer(in.NominalConcurrencyShares))
out.LendablePercent = (*int32)(unsafe.Pointer(in.LendablePercent))
return nil
}
// Convert_flowcontrol_ExemptPriorityLevelConfiguration_To_v1beta2_ExemptPriorityLevelConfiguration is an autogenerated conversion function.
func Convert_flowcontrol_ExemptPriorityLevelConfiguration_To_v1beta2_ExemptPriorityLevelConfiguration(in *flowcontrol.ExemptPriorityLevelConfiguration, out *v1beta2.ExemptPriorityLevelConfiguration, s conversion.Scope) error {
return autoConvert_flowcontrol_ExemptPriorityLevelConfiguration_To_v1beta2_ExemptPriorityLevelConfiguration(in, out, s)
}
func autoConvert_v1beta2_FlowDistinguisherMethod_To_flowcontrol_FlowDistinguisherMethod(in *v1beta2.FlowDistinguisherMethod, out *flowcontrol.FlowDistinguisherMethod, s conversion.Scope) error {
out.Type = flowcontrol.FlowDistinguisherMethodType(in.Type)
return nil
@@ -653,6 +685,7 @@ func autoConvert_v1beta2_PriorityLevelConfigurationSpec_To_flowcontrol_PriorityL
} else {
out.Limited = nil
}
out.Exempt = (*flowcontrol.ExemptPriorityLevelConfiguration)(unsafe.Pointer(in.Exempt))
return nil
}
@@ -672,6 +705,7 @@ func autoConvert_flowcontrol_PriorityLevelConfigurationSpec_To_v1beta2_PriorityL
} else {
out.Limited = nil
}
out.Exempt = (*v1beta2.ExemptPriorityLevelConfiguration)(unsafe.Pointer(in.Exempt))
return nil
}

View File

@@ -59,6 +59,9 @@ func SetObjectDefaults_PriorityLevelConfiguration(in *v1beta2.PriorityLevelConfi
SetDefaults_QueuingConfiguration(in.Spec.Limited.LimitResponse.Queuing)
}
}
if in.Spec.Exempt != nil {
SetDefaults_ExemptPriorityLevelConfiguration(in.Spec.Exempt)
}
}
func SetObjectDefaults_PriorityLevelConfigurationList(in *v1beta2.PriorityLevelConfigurationList) {

View File

@@ -40,6 +40,17 @@ func SetDefaults_FlowSchemaSpec(spec *v1beta3.FlowSchemaSpec) {
}
}
func SetDefaults_ExemptPriorityLevelConfiguration(eplc *v1beta3.ExemptPriorityLevelConfiguration) {
if eplc.NominalConcurrencyShares == nil {
eplc.NominalConcurrencyShares = new(int32)
*eplc.NominalConcurrencyShares = 0
}
if eplc.LendablePercent == nil {
eplc.LendablePercent = new(int32)
*eplc.LendablePercent = 0
}
}
func SetDefaults_LimitedPriorityLevelConfiguration(lplc *v1beta3.LimitedPriorityLevelConfiguration) {
if lplc.NominalConcurrencyShares == 0 {
lplc.NominalConcurrencyShares = PriorityLevelConfigurationDefaultNominalConcurrencyShares

View File

@@ -34,7 +34,25 @@ func TestDefaultWithPriorityLevelConfiguration(t *testing.T) {
expected runtime.Object
}{
{
name: "LendablePercent is not specified, should default to zero",
name: "Defaulting for Exempt",
original: &flowcontrolv1beta3.PriorityLevelConfiguration{
Spec: flowcontrolv1beta3.PriorityLevelConfigurationSpec{
Type: flowcontrolv1beta3.PriorityLevelEnablementExempt,
Exempt: &flowcontrolv1beta3.ExemptPriorityLevelConfiguration{},
},
},
expected: &flowcontrolv1beta3.PriorityLevelConfiguration{
Spec: flowcontrolv1beta3.PriorityLevelConfigurationSpec{
Type: flowcontrolv1beta3.PriorityLevelEnablementExempt,
Exempt: &flowcontrolv1beta3.ExemptPriorityLevelConfiguration{
NominalConcurrencyShares: pointer.Int32(0),
LendablePercent: pointer.Int32(0),
},
},
},
},
{
name: "LendablePercent is not specified in Limited, should default to zero",
original: &flowcontrolv1beta3.PriorityLevelConfiguration{
Spec: flowcontrolv1beta3.PriorityLevelConfigurationSpec{
Type: flowcontrolv1beta3.PriorityLevelEnablementLimited,

View File

@@ -37,6 +37,16 @@ func init() {
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(s *runtime.Scheme) error {
if err := s.AddGeneratedConversionFunc((*v1beta3.ExemptPriorityLevelConfiguration)(nil), (*flowcontrol.ExemptPriorityLevelConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta3_ExemptPriorityLevelConfiguration_To_flowcontrol_ExemptPriorityLevelConfiguration(a.(*v1beta3.ExemptPriorityLevelConfiguration), b.(*flowcontrol.ExemptPriorityLevelConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*flowcontrol.ExemptPriorityLevelConfiguration)(nil), (*v1beta3.ExemptPriorityLevelConfiguration)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_flowcontrol_ExemptPriorityLevelConfiguration_To_v1beta3_ExemptPriorityLevelConfiguration(a.(*flowcontrol.ExemptPriorityLevelConfiguration), b.(*v1beta3.ExemptPriorityLevelConfiguration), scope)
}); err != nil {
return err
}
if err := s.AddGeneratedConversionFunc((*v1beta3.FlowDistinguisherMethod)(nil), (*flowcontrol.FlowDistinguisherMethod)(nil), func(a, b interface{}, scope conversion.Scope) error {
return Convert_v1beta3_FlowDistinguisherMethod_To_flowcontrol_FlowDistinguisherMethod(a.(*v1beta3.FlowDistinguisherMethod), b.(*flowcontrol.FlowDistinguisherMethod), scope)
}); err != nil {
@@ -260,6 +270,28 @@ func RegisterConversions(s *runtime.Scheme) error {
return nil
}
func autoConvert_v1beta3_ExemptPriorityLevelConfiguration_To_flowcontrol_ExemptPriorityLevelConfiguration(in *v1beta3.ExemptPriorityLevelConfiguration, out *flowcontrol.ExemptPriorityLevelConfiguration, s conversion.Scope) error {
out.NominalConcurrencyShares = (*int32)(unsafe.Pointer(in.NominalConcurrencyShares))
out.LendablePercent = (*int32)(unsafe.Pointer(in.LendablePercent))
return nil
}
// Convert_v1beta3_ExemptPriorityLevelConfiguration_To_flowcontrol_ExemptPriorityLevelConfiguration is an autogenerated conversion function.
func Convert_v1beta3_ExemptPriorityLevelConfiguration_To_flowcontrol_ExemptPriorityLevelConfiguration(in *v1beta3.ExemptPriorityLevelConfiguration, out *flowcontrol.ExemptPriorityLevelConfiguration, s conversion.Scope) error {
return autoConvert_v1beta3_ExemptPriorityLevelConfiguration_To_flowcontrol_ExemptPriorityLevelConfiguration(in, out, s)
}
func autoConvert_flowcontrol_ExemptPriorityLevelConfiguration_To_v1beta3_ExemptPriorityLevelConfiguration(in *flowcontrol.ExemptPriorityLevelConfiguration, out *v1beta3.ExemptPriorityLevelConfiguration, s conversion.Scope) error {
out.NominalConcurrencyShares = (*int32)(unsafe.Pointer(in.NominalConcurrencyShares))
out.LendablePercent = (*int32)(unsafe.Pointer(in.LendablePercent))
return nil
}
// Convert_flowcontrol_ExemptPriorityLevelConfiguration_To_v1beta3_ExemptPriorityLevelConfiguration is an autogenerated conversion function.
func Convert_flowcontrol_ExemptPriorityLevelConfiguration_To_v1beta3_ExemptPriorityLevelConfiguration(in *flowcontrol.ExemptPriorityLevelConfiguration, out *v1beta3.ExemptPriorityLevelConfiguration, s conversion.Scope) error {
return autoConvert_flowcontrol_ExemptPriorityLevelConfiguration_To_v1beta3_ExemptPriorityLevelConfiguration(in, out, s)
}
func autoConvert_v1beta3_FlowDistinguisherMethod_To_flowcontrol_FlowDistinguisherMethod(in *v1beta3.FlowDistinguisherMethod, out *flowcontrol.FlowDistinguisherMethod, s conversion.Scope) error {
out.Type = flowcontrol.FlowDistinguisherMethodType(in.Type)
return nil
@@ -635,6 +667,7 @@ func Convert_flowcontrol_PriorityLevelConfigurationReference_To_v1beta3_Priority
func autoConvert_v1beta3_PriorityLevelConfigurationSpec_To_flowcontrol_PriorityLevelConfigurationSpec(in *v1beta3.PriorityLevelConfigurationSpec, out *flowcontrol.PriorityLevelConfigurationSpec, s conversion.Scope) error {
out.Type = flowcontrol.PriorityLevelEnablement(in.Type)
out.Limited = (*flowcontrol.LimitedPriorityLevelConfiguration)(unsafe.Pointer(in.Limited))
out.Exempt = (*flowcontrol.ExemptPriorityLevelConfiguration)(unsafe.Pointer(in.Exempt))
return nil
}
@@ -646,6 +679,7 @@ func Convert_v1beta3_PriorityLevelConfigurationSpec_To_flowcontrol_PriorityLevel
func autoConvert_flowcontrol_PriorityLevelConfigurationSpec_To_v1beta3_PriorityLevelConfigurationSpec(in *flowcontrol.PriorityLevelConfigurationSpec, out *v1beta3.PriorityLevelConfigurationSpec, s conversion.Scope) error {
out.Type = v1beta3.PriorityLevelEnablement(in.Type)
out.Limited = (*v1beta3.LimitedPriorityLevelConfiguration)(unsafe.Pointer(in.Limited))
out.Exempt = (*v1beta3.ExemptPriorityLevelConfiguration)(unsafe.Pointer(in.Exempt))
return nil
}

View File

@@ -59,6 +59,9 @@ func SetObjectDefaults_PriorityLevelConfiguration(in *v1beta3.PriorityLevelConfi
SetDefaults_QueuingConfiguration(in.Spec.Limited.LimitResponse.Queuing)
}
}
if in.Spec.Exempt != nil {
SetDefaults_ExemptPriorityLevelConfiguration(in.Spec.Exempt)
}
}
func SetObjectDefaults_PriorityLevelConfigurationList(in *v1beta3.PriorityLevelConfigurationList) {

View File

@@ -345,19 +345,41 @@ func ValidatePriorityLevelConfiguration(pl *flowcontrol.PriorityLevelConfigurati
allErrs := apivalidation.ValidateObjectMeta(&pl.ObjectMeta, false, ValidatePriorityLevelConfigurationName, field.NewPath("metadata"))
specPath := field.NewPath("spec")
allErrs = append(allErrs, ValidatePriorityLevelConfigurationSpec(&pl.Spec, requestGV, pl.Name, specPath)...)
if mand, ok := internalbootstrap.MandatoryPriorityLevelConfigurations[pl.Name]; ok {
// Check for almost exact equality. This is a pretty
// strict test, and it is OK in this context because both
// sides of this comparison are intended to ultimately
// come from the same code.
if !apiequality.Semantic.DeepEqual(pl.Spec, mand.Spec) {
allErrs = append(allErrs, field.Invalid(specPath, pl.Spec, fmt.Sprintf("spec of '%s' must equal the fixed value", pl.Name)))
}
}
allErrs = append(allErrs, ValidateIfMandatoryPriorityLevelConfigurationObject(pl, specPath)...)
allErrs = append(allErrs, ValidatePriorityLevelConfigurationStatus(&pl.Status, field.NewPath("status"))...)
return allErrs
}
func ValidateIfMandatoryPriorityLevelConfigurationObject(pl *flowcontrol.PriorityLevelConfiguration, fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList
mand, ok := internalbootstrap.MandatoryPriorityLevelConfigurations[pl.Name]
if !ok {
return allErrs
}
if pl.Name == flowcontrol.PriorityLevelConfigurationNameExempt {
// we allow the admin to change the contents of the 'Exempt' field of
// the singleton 'exempt' priority level object, every other fields of
// the Spec should not be allowed to change.
want := &mand.Spec
have := pl.Spec.DeepCopy()
have.Exempt = want.Exempt
if !apiequality.Semantic.DeepEqual(want, have) {
allErrs = append(allErrs, field.Invalid(fldPath, pl.Spec, fmt.Sprintf("spec of '%s' except the 'spec.exempt' field must equal the fixed value", pl.Name)))
}
return allErrs
}
// Check for almost exact equality. This is a pretty
// strict test, and it is OK in this context because both
// sides of this comparison are intended to ultimately
// come from the same code.
if !apiequality.Semantic.DeepEqual(pl.Spec, mand.Spec) {
allErrs = append(allErrs, field.Invalid(fldPath, pl.Spec, fmt.Sprintf("spec of '%s' must equal the fixed value", pl.Name)))
}
return allErrs
}
// ValidatePriorityLevelConfigurationSpec validates priority-level-configuration's spec.
func ValidatePriorityLevelConfigurationSpec(spec *flowcontrol.PriorityLevelConfigurationSpec, requestGV schema.GroupVersion, name string, fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList
@@ -369,7 +391,14 @@ func ValidatePriorityLevelConfigurationSpec(spec *flowcontrol.PriorityLevelConfi
if spec.Limited != nil {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("limited"), "must be nil if the type is not Limited"))
}
if spec.Exempt != nil {
allErrs = append(allErrs, ValidateExemptPriorityLevelConfiguration(spec.Exempt, fldPath.Child("exempt"))...)
}
case flowcontrol.PriorityLevelEnablementLimited:
if spec.Exempt != nil {
allErrs = append(allErrs, field.Forbidden(fldPath.Child("exempt"), "must be nil if the type is Limited"))
}
if spec.Limited == nil {
allErrs = append(allErrs, field.Required(fldPath.Child("limited"), "must not be empty when type is Limited"))
} else {
@@ -399,6 +428,17 @@ func ValidateLimitedPriorityLevelConfiguration(lplc *flowcontrol.LimitedPriority
return allErrs
}
func ValidateExemptPriorityLevelConfiguration(eplc *flowcontrol.ExemptPriorityLevelConfiguration, fldPath *field.Path) field.ErrorList {
var allErrs field.ErrorList
if eplc.NominalConcurrencyShares != nil && *eplc.NominalConcurrencyShares < 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("nominalConcurrencyShares"), *eplc.NominalConcurrencyShares, "must be a non-negative integer"))
}
if eplc.LendablePercent != nil && !(*eplc.LendablePercent >= 0 && *eplc.LendablePercent <= 100) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("lendablePercent"), *eplc.LendablePercent, "must be between 0 and 100, inclusive"))
}
return allErrs
}
func getVersionedFieldNameForConcurrencyShares(requestGV schema.GroupVersion) string {
switch {
case requestGV == flowcontrolv1alpha1.SchemeGroupVersion ||

View File

@@ -32,6 +32,7 @@ import (
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/kubernetes/pkg/apis/flowcontrol"
"k8s.io/kubernetes/pkg/apis/flowcontrol/internalbootstrap"
"k8s.io/utils/pointer"
)
@@ -743,6 +744,59 @@ func TestPriorityLevelConfigurationValidation(t *testing.T) {
Type: flowcontrol.LimitResponseTypeReject},
},
}
badExemptSpec1 := flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementExempt,
Exempt: &flowcontrol.ExemptPriorityLevelConfiguration{
NominalConcurrencyShares: pointer.Int32(-1),
LendablePercent: pointer.Int32(101),
},
}
badExemptSpec2 := flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementExempt,
Exempt: &flowcontrol.ExemptPriorityLevelConfiguration{
NominalConcurrencyShares: pointer.Int32(-1),
LendablePercent: pointer.Int32(-1),
},
}
badExemptSpec3 := flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementExempt,
Exempt: &flowcontrol.ExemptPriorityLevelConfiguration{},
Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: 42,
LimitResponse: flowcontrol.LimitResponse{
Type: flowcontrol.LimitResponseTypeReject},
},
}
validChangesInExemptFieldOfExemptPLFn := func() flowcontrol.PriorityLevelConfigurationSpec {
have, _ := internalbootstrap.MandatoryPriorityLevelConfigurations[flowcontrol.PriorityLevelConfigurationNameExempt]
return flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementExempt,
Exempt: &flowcontrol.ExemptPriorityLevelConfiguration{
NominalConcurrencyShares: pointer.Int32(*have.Spec.Exempt.NominalConcurrencyShares + 10),
LendablePercent: pointer.Int32(*have.Spec.Exempt.LendablePercent + 10),
},
}
}
exemptTypeRepurposed := &flowcontrol.PriorityLevelConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: flowcontrol.PriorityLevelConfigurationNameExempt,
},
Spec: flowcontrol.PriorityLevelConfigurationSpec{
// changing the type from exempt to limited
Type: flowcontrol.PriorityLevelEnablementLimited,
Exempt: &flowcontrol.ExemptPriorityLevelConfiguration{},
Limited: &flowcontrol.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: 42,
LimitResponse: flowcontrol.LimitResponse{
Type: flowcontrol.LimitResponseTypeReject},
},
},
}
testCases := []struct {
name string
priorityLevelConfiguration *flowcontrol.PriorityLevelConfiguration
@@ -755,6 +809,10 @@ func TestPriorityLevelConfigurationValidation(t *testing.T) {
},
Spec: flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementExempt,
Exempt: &flowcontrol.ExemptPriorityLevelConfiguration{
NominalConcurrencyShares: pointer.Int32(0),
LendablePercent: pointer.Int32(0),
},
},
},
expectedErrors: field.ErrorList{},
@@ -768,7 +826,75 @@ func TestPriorityLevelConfigurationValidation(t *testing.T) {
},
expectedErrors: field.ErrorList{
field.Invalid(field.NewPath("spec").Child("type"), flowcontrol.PriorityLevelEnablementLimited, "type must be 'Exempt' if and only if name is 'exempt'"),
field.Invalid(field.NewPath("spec"), badSpec, "spec of 'exempt' must equal the fixed value"),
field.Invalid(field.NewPath("spec"), badSpec, "spec of 'exempt' except the 'spec.exempt' field must equal the fixed value"),
},
}, {
name: "exempt priority level should have appropriate values for Exempt field",
priorityLevelConfiguration: &flowcontrol.PriorityLevelConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: flowcontrol.PriorityLevelConfigurationNameExempt,
},
Spec: badExemptSpec1,
},
expectedErrors: field.ErrorList{
field.Invalid(field.NewPath("spec").Child("exempt").Child("nominalConcurrencyShares"), int32(-1), "must be a non-negative integer"),
field.Invalid(field.NewPath("spec").Child("exempt").Child("lendablePercent"), int32(101), "must be between 0 and 100, inclusive"),
},
}, {
name: "exempt priority level should have appropriate values for Exempt field",
priorityLevelConfiguration: &flowcontrol.PriorityLevelConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: flowcontrol.PriorityLevelConfigurationNameExempt,
},
Spec: badExemptSpec2,
},
expectedErrors: field.ErrorList{
field.Invalid(field.NewPath("spec").Child("exempt").Child("nominalConcurrencyShares"), int32(-1), "must be a non-negative integer"),
field.Invalid(field.NewPath("spec").Child("exempt").Child("lendablePercent"), int32(-1), "must be between 0 and 100, inclusive"),
},
}, {
name: "admins are not allowed to repurpose the 'exempt' pl to a limited type",
priorityLevelConfiguration: exemptTypeRepurposed,
expectedErrors: field.ErrorList{
field.Invalid(field.NewPath("spec").Child("type"), flowcontrol.PriorityLevelEnablementLimited, "type must be 'Exempt' if and only if name is 'exempt'"),
field.Forbidden(field.NewPath("spec").Child("exempt"), "must be nil if the type is Limited"),
field.Invalid(field.NewPath("spec"), exemptTypeRepurposed.Spec, "spec of 'exempt' except the 'spec.exempt' field must equal the fixed value"),
},
}, {
name: "admins are not allowed to change any field of the 'exempt' pl except 'Exempt'",
priorityLevelConfiguration: &flowcontrol.PriorityLevelConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: flowcontrol.PriorityLevelConfigurationNameExempt,
},
Spec: badExemptSpec3,
},
expectedErrors: field.ErrorList{
field.Invalid(field.NewPath("spec"), badExemptSpec3, "spec of 'exempt' except the 'spec.exempt' field must equal the fixed value"),
field.Forbidden(field.NewPath("spec").Child("limited"), "must be nil if the type is not Limited"),
},
}, {
name: "admins are allowed to change the Exempt field of the 'exempt' pl",
priorityLevelConfiguration: &flowcontrol.PriorityLevelConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: flowcontrol.PriorityLevelConfigurationNameExempt,
},
Spec: validChangesInExemptFieldOfExemptPLFn(),
},
expectedErrors: field.ErrorList{},
}, {
name: "limited must not set exempt priority level configuration for borrowing",
priorityLevelConfiguration: &flowcontrol.PriorityLevelConfiguration{
ObjectMeta: metav1.ObjectMeta{
Name: "broken-limited",
},
Spec: flowcontrol.PriorityLevelConfigurationSpec{
Type: flowcontrol.PriorityLevelEnablementLimited,
Exempt: &flowcontrol.ExemptPriorityLevelConfiguration{},
},
},
expectedErrors: field.ErrorList{
field.Forbidden(field.NewPath("spec").Child("exempt"), "must be nil if the type is Limited"),
field.Required(field.NewPath("spec").Child("limited"), "must not be empty when type is Limited"),
},
}, {
name: "limited requires more details",

View File

@@ -25,6 +25,32 @@ import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExemptPriorityLevelConfiguration) DeepCopyInto(out *ExemptPriorityLevelConfiguration) {
*out = *in
if in.NominalConcurrencyShares != nil {
in, out := &in.NominalConcurrencyShares, &out.NominalConcurrencyShares
*out = new(int32)
**out = **in
}
if in.LendablePercent != nil {
in, out := &in.LendablePercent, &out.LendablePercent
*out = new(int32)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExemptPriorityLevelConfiguration.
func (in *ExemptPriorityLevelConfiguration) DeepCopy() *ExemptPriorityLevelConfiguration {
if in == nil {
return nil
}
out := new(ExemptPriorityLevelConfiguration)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FlowDistinguisherMethod) DeepCopyInto(out *FlowDistinguisherMethod) {
*out = *in
@@ -400,6 +426,11 @@ func (in *PriorityLevelConfigurationSpec) DeepCopyInto(out *PriorityLevelConfigu
*out = new(LimitedPriorityLevelConfiguration)
(*in).DeepCopyInto(*out)
}
if in.Exempt != nil {
in, out := &in.Exempt, &out.Exempt
*out = new(ExemptPriorityLevelConfiguration)
(*in).DeepCopyInto(*out)
}
return
}

View File

@@ -620,6 +620,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"k8s.io/api/extensions/v1beta1.Scale": schema_k8sio_api_extensions_v1beta1_Scale(ref),
"k8s.io/api/extensions/v1beta1.ScaleSpec": schema_k8sio_api_extensions_v1beta1_ScaleSpec(ref),
"k8s.io/api/extensions/v1beta1.ScaleStatus": schema_k8sio_api_extensions_v1beta1_ScaleStatus(ref),
"k8s.io/api/flowcontrol/v1alpha1.ExemptPriorityLevelConfiguration": schema_k8sio_api_flowcontrol_v1alpha1_ExemptPriorityLevelConfiguration(ref),
"k8s.io/api/flowcontrol/v1alpha1.FlowDistinguisherMethod": schema_k8sio_api_flowcontrol_v1alpha1_FlowDistinguisherMethod(ref),
"k8s.io/api/flowcontrol/v1alpha1.FlowSchema": schema_k8sio_api_flowcontrol_v1alpha1_FlowSchema(ref),
"k8s.io/api/flowcontrol/v1alpha1.FlowSchemaCondition": schema_k8sio_api_flowcontrol_v1alpha1_FlowSchemaCondition(ref),
@@ -642,6 +643,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"k8s.io/api/flowcontrol/v1alpha1.ServiceAccountSubject": schema_k8sio_api_flowcontrol_v1alpha1_ServiceAccountSubject(ref),
"k8s.io/api/flowcontrol/v1alpha1.Subject": schema_k8sio_api_flowcontrol_v1alpha1_Subject(ref),
"k8s.io/api/flowcontrol/v1alpha1.UserSubject": schema_k8sio_api_flowcontrol_v1alpha1_UserSubject(ref),
"k8s.io/api/flowcontrol/v1beta1.ExemptPriorityLevelConfiguration": schema_k8sio_api_flowcontrol_v1beta1_ExemptPriorityLevelConfiguration(ref),
"k8s.io/api/flowcontrol/v1beta1.FlowDistinguisherMethod": schema_k8sio_api_flowcontrol_v1beta1_FlowDistinguisherMethod(ref),
"k8s.io/api/flowcontrol/v1beta1.FlowSchema": schema_k8sio_api_flowcontrol_v1beta1_FlowSchema(ref),
"k8s.io/api/flowcontrol/v1beta1.FlowSchemaCondition": schema_k8sio_api_flowcontrol_v1beta1_FlowSchemaCondition(ref),
@@ -664,6 +666,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"k8s.io/api/flowcontrol/v1beta1.ServiceAccountSubject": schema_k8sio_api_flowcontrol_v1beta1_ServiceAccountSubject(ref),
"k8s.io/api/flowcontrol/v1beta1.Subject": schema_k8sio_api_flowcontrol_v1beta1_Subject(ref),
"k8s.io/api/flowcontrol/v1beta1.UserSubject": schema_k8sio_api_flowcontrol_v1beta1_UserSubject(ref),
"k8s.io/api/flowcontrol/v1beta2.ExemptPriorityLevelConfiguration": schema_k8sio_api_flowcontrol_v1beta2_ExemptPriorityLevelConfiguration(ref),
"k8s.io/api/flowcontrol/v1beta2.FlowDistinguisherMethod": schema_k8sio_api_flowcontrol_v1beta2_FlowDistinguisherMethod(ref),
"k8s.io/api/flowcontrol/v1beta2.FlowSchema": schema_k8sio_api_flowcontrol_v1beta2_FlowSchema(ref),
"k8s.io/api/flowcontrol/v1beta2.FlowSchemaCondition": schema_k8sio_api_flowcontrol_v1beta2_FlowSchemaCondition(ref),
@@ -686,6 +689,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
"k8s.io/api/flowcontrol/v1beta2.ServiceAccountSubject": schema_k8sio_api_flowcontrol_v1beta2_ServiceAccountSubject(ref),
"k8s.io/api/flowcontrol/v1beta2.Subject": schema_k8sio_api_flowcontrol_v1beta2_Subject(ref),
"k8s.io/api/flowcontrol/v1beta2.UserSubject": schema_k8sio_api_flowcontrol_v1beta2_UserSubject(ref),
"k8s.io/api/flowcontrol/v1beta3.ExemptPriorityLevelConfiguration": schema_k8sio_api_flowcontrol_v1beta3_ExemptPriorityLevelConfiguration(ref),
"k8s.io/api/flowcontrol/v1beta3.FlowDistinguisherMethod": schema_k8sio_api_flowcontrol_v1beta3_FlowDistinguisherMethod(ref),
"k8s.io/api/flowcontrol/v1beta3.FlowSchema": schema_k8sio_api_flowcontrol_v1beta3_FlowSchema(ref),
"k8s.io/api/flowcontrol/v1beta3.FlowSchemaCondition": schema_k8sio_api_flowcontrol_v1beta3_FlowSchemaCondition(ref),
@@ -31782,6 +31786,33 @@ func schema_k8sio_api_extensions_v1beta1_ScaleStatus(ref common.ReferenceCallbac
}
}
func schema_k8sio_api_flowcontrol_v1alpha1_ExemptPriorityLevelConfiguration(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "ExemptPriorityLevelConfiguration describes the configurable aspects of the handling of exempt requests. In the mandatory exempt configuration object the values in the fields here can be modified by authorized users, unlike the rest of the `spec`.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"nominalConcurrencyShares": {
SchemaProps: spec.SchemaProps{
Description: "`nominalConcurrencyShares` (NCS) contributes to the computation of the NominalConcurrencyLimit (NominalCL) of this level. This is the number of execution seats nominally reserved for this priority level. This DOES NOT limit the dispatching from this priority level but affects the other priority levels through the borrowing mechanism. The server's concurrency limit (ServerCL) is divided among all the priority levels in proportion to their NCS values:\n\nNominalCL(i) = ceil( ServerCL * NCS(i) / sum_ncs ) sum_ncs = sum[priority level k] NCS(k)\n\nBigger numbers mean a larger nominal concurrency limit, at the expense of every other priority level. This field has a default value of zero.",
Type: []string{"integer"},
Format: "int32",
},
},
"lendablePercent": {
SchemaProps: spec.SchemaProps{
Description: "`lendablePercent` prescribes the fraction of the level's NominalCL that can be borrowed by other priority levels. This value of this field must be between 0 and 100, inclusive, and it defaults to 0. The number of seats that other levels can borrow from this level, known as this level's LendableConcurrencyLimit (LendableCL), is defined as follows.\n\nLendableCL(i) = round( NominalCL(i) * lendablePercent(i)/100.0 )",
Type: []string{"integer"},
Format: "int32",
},
},
},
},
},
}
}
func schema_k8sio_api_flowcontrol_v1alpha1_FlowDistinguisherMethod(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -32477,6 +32508,12 @@ func schema_k8sio_api_flowcontrol_v1alpha1_PriorityLevelConfigurationSpec(ref co
Ref: ref("k8s.io/api/flowcontrol/v1alpha1.LimitedPriorityLevelConfiguration"),
},
},
"exempt": {
SchemaProps: spec.SchemaProps{
Description: "`exempt` specifies how requests are handled for an exempt priority level. This field MUST be empty if `type` is `\"Limited\"`. This field MAY be non-empty if `type` is `\"Exempt\"`. If empty and `type` is `\"Exempt\"` then the default values for `ExemptPriorityLevelConfiguration` apply.",
Ref: ref("k8s.io/api/flowcontrol/v1alpha1.ExemptPriorityLevelConfiguration"),
},
},
},
Required: []string{"type"},
},
@@ -32486,6 +32523,7 @@ func schema_k8sio_api_flowcontrol_v1alpha1_PriorityLevelConfigurationSpec(ref co
map[string]interface{}{
"discriminator": "type",
"fields-to-discriminateBy": map[string]interface{}{
"exempt": "Exempt",
"limited": "Limited",
},
},
@@ -32494,7 +32532,7 @@ func schema_k8sio_api_flowcontrol_v1alpha1_PriorityLevelConfigurationSpec(ref co
},
},
Dependencies: []string{
"k8s.io/api/flowcontrol/v1alpha1.LimitedPriorityLevelConfiguration"},
"k8s.io/api/flowcontrol/v1alpha1.ExemptPriorityLevelConfiguration", "k8s.io/api/flowcontrol/v1alpha1.LimitedPriorityLevelConfiguration"},
}
}
@@ -32781,6 +32819,33 @@ func schema_k8sio_api_flowcontrol_v1alpha1_UserSubject(ref common.ReferenceCallb
}
}
func schema_k8sio_api_flowcontrol_v1beta1_ExemptPriorityLevelConfiguration(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "ExemptPriorityLevelConfiguration describes the configurable aspects of the handling of exempt requests. In the mandatory exempt configuration object the values in the fields here can be modified by authorized users, unlike the rest of the `spec`.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"nominalConcurrencyShares": {
SchemaProps: spec.SchemaProps{
Description: "`nominalConcurrencyShares` (NCS) contributes to the computation of the NominalConcurrencyLimit (NominalCL) of this level. This is the number of execution seats nominally reserved for this priority level. This DOES NOT limit the dispatching from this priority level but affects the other priority levels through the borrowing mechanism. The server's concurrency limit (ServerCL) is divided among all the priority levels in proportion to their NCS values:\n\nNominalCL(i) = ceil( ServerCL * NCS(i) / sum_ncs ) sum_ncs = sum[priority level k] NCS(k)\n\nBigger numbers mean a larger nominal concurrency limit, at the expense of every other priority level. This field has a default value of zero.",
Type: []string{"integer"},
Format: "int32",
},
},
"lendablePercent": {
SchemaProps: spec.SchemaProps{
Description: "`lendablePercent` prescribes the fraction of the level's NominalCL that can be borrowed by other priority levels. This value of this field must be between 0 and 100, inclusive, and it defaults to 0. The number of seats that other levels can borrow from this level, known as this level's LendableConcurrencyLimit (LendableCL), is defined as follows.\n\nLendableCL(i) = round( NominalCL(i) * lendablePercent(i)/100.0 )",
Type: []string{"integer"},
Format: "int32",
},
},
},
},
},
}
}
func schema_k8sio_api_flowcontrol_v1beta1_FlowDistinguisherMethod(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -33476,6 +33541,12 @@ func schema_k8sio_api_flowcontrol_v1beta1_PriorityLevelConfigurationSpec(ref com
Ref: ref("k8s.io/api/flowcontrol/v1beta1.LimitedPriorityLevelConfiguration"),
},
},
"exempt": {
SchemaProps: spec.SchemaProps{
Description: "`exempt` specifies how requests are handled for an exempt priority level. This field MUST be empty if `type` is `\"Limited\"`. This field MAY be non-empty if `type` is `\"Exempt\"`. If empty and `type` is `\"Exempt\"` then the default values for `ExemptPriorityLevelConfiguration` apply.",
Ref: ref("k8s.io/api/flowcontrol/v1beta1.ExemptPriorityLevelConfiguration"),
},
},
},
Required: []string{"type"},
},
@@ -33485,6 +33556,7 @@ func schema_k8sio_api_flowcontrol_v1beta1_PriorityLevelConfigurationSpec(ref com
map[string]interface{}{
"discriminator": "type",
"fields-to-discriminateBy": map[string]interface{}{
"exempt": "Exempt",
"limited": "Limited",
},
},
@@ -33493,7 +33565,7 @@ func schema_k8sio_api_flowcontrol_v1beta1_PriorityLevelConfigurationSpec(ref com
},
},
Dependencies: []string{
"k8s.io/api/flowcontrol/v1beta1.LimitedPriorityLevelConfiguration"},
"k8s.io/api/flowcontrol/v1beta1.ExemptPriorityLevelConfiguration", "k8s.io/api/flowcontrol/v1beta1.LimitedPriorityLevelConfiguration"},
}
}
@@ -33780,6 +33852,33 @@ func schema_k8sio_api_flowcontrol_v1beta1_UserSubject(ref common.ReferenceCallba
}
}
func schema_k8sio_api_flowcontrol_v1beta2_ExemptPriorityLevelConfiguration(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "ExemptPriorityLevelConfiguration describes the configurable aspects of the handling of exempt requests. In the mandatory exempt configuration object the values in the fields here can be modified by authorized users, unlike the rest of the `spec`.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"nominalConcurrencyShares": {
SchemaProps: spec.SchemaProps{
Description: "`nominalConcurrencyShares` (NCS) contributes to the computation of the NominalConcurrencyLimit (NominalCL) of this level. This is the number of execution seats nominally reserved for this priority level. This DOES NOT limit the dispatching from this priority level but affects the other priority levels through the borrowing mechanism. The server's concurrency limit (ServerCL) is divided among all the priority levels in proportion to their NCS values:\n\nNominalCL(i) = ceil( ServerCL * NCS(i) / sum_ncs ) sum_ncs = sum[priority level k] NCS(k)\n\nBigger numbers mean a larger nominal concurrency limit, at the expense of every other priority level. This field has a default value of zero.",
Type: []string{"integer"},
Format: "int32",
},
},
"lendablePercent": {
SchemaProps: spec.SchemaProps{
Description: "`lendablePercent` prescribes the fraction of the level's NominalCL that can be borrowed by other priority levels. This value of this field must be between 0 and 100, inclusive, and it defaults to 0. The number of seats that other levels can borrow from this level, known as this level's LendableConcurrencyLimit (LendableCL), is defined as follows.\n\nLendableCL(i) = round( NominalCL(i) * lendablePercent(i)/100.0 )",
Type: []string{"integer"},
Format: "int32",
},
},
},
},
},
}
}
func schema_k8sio_api_flowcontrol_v1beta2_FlowDistinguisherMethod(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -34475,6 +34574,12 @@ func schema_k8sio_api_flowcontrol_v1beta2_PriorityLevelConfigurationSpec(ref com
Ref: ref("k8s.io/api/flowcontrol/v1beta2.LimitedPriorityLevelConfiguration"),
},
},
"exempt": {
SchemaProps: spec.SchemaProps{
Description: "`exempt` specifies how requests are handled for an exempt priority level. This field MUST be empty if `type` is `\"Limited\"`. This field MAY be non-empty if `type` is `\"Exempt\"`. If empty and `type` is `\"Exempt\"` then the default values for `ExemptPriorityLevelConfiguration` apply.",
Ref: ref("k8s.io/api/flowcontrol/v1beta2.ExemptPriorityLevelConfiguration"),
},
},
},
Required: []string{"type"},
},
@@ -34484,6 +34589,7 @@ func schema_k8sio_api_flowcontrol_v1beta2_PriorityLevelConfigurationSpec(ref com
map[string]interface{}{
"discriminator": "type",
"fields-to-discriminateBy": map[string]interface{}{
"exempt": "Exempt",
"limited": "Limited",
},
},
@@ -34492,7 +34598,7 @@ func schema_k8sio_api_flowcontrol_v1beta2_PriorityLevelConfigurationSpec(ref com
},
},
Dependencies: []string{
"k8s.io/api/flowcontrol/v1beta2.LimitedPriorityLevelConfiguration"},
"k8s.io/api/flowcontrol/v1beta2.ExemptPriorityLevelConfiguration", "k8s.io/api/flowcontrol/v1beta2.LimitedPriorityLevelConfiguration"},
}
}
@@ -34779,6 +34885,33 @@ func schema_k8sio_api_flowcontrol_v1beta2_UserSubject(ref common.ReferenceCallba
}
}
func schema_k8sio_api_flowcontrol_v1beta3_ExemptPriorityLevelConfiguration(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "ExemptPriorityLevelConfiguration describes the configurable aspects of the handling of exempt requests. In the mandatory exempt configuration object the values in the fields here can be modified by authorized users, unlike the rest of the `spec`.",
Type: []string{"object"},
Properties: map[string]spec.Schema{
"nominalConcurrencyShares": {
SchemaProps: spec.SchemaProps{
Description: "`nominalConcurrencyShares` (NCS) contributes to the computation of the NominalConcurrencyLimit (NominalCL) of this level. This is the number of execution seats nominally reserved for this priority level. This DOES NOT limit the dispatching from this priority level but affects the other priority levels through the borrowing mechanism. The server's concurrency limit (ServerCL) is divided among all the priority levels in proportion to their NCS values:\n\nNominalCL(i) = ceil( ServerCL * NCS(i) / sum_ncs ) sum_ncs = sum[priority level k] NCS(k)\n\nBigger numbers mean a larger nominal concurrency limit, at the expense of every other priority level. This field has a default value of zero.",
Type: []string{"integer"},
Format: "int32",
},
},
"lendablePercent": {
SchemaProps: spec.SchemaProps{
Description: "`lendablePercent` prescribes the fraction of the level's NominalCL that can be borrowed by other priority levels. This value of this field must be between 0 and 100, inclusive, and it defaults to 0. The number of seats that other levels can borrow from this level, known as this level's LendableConcurrencyLimit (LendableCL), is defined as follows.\n\nLendableCL(i) = round( NominalCL(i) * lendablePercent(i)/100.0 )",
Type: []string{"integer"},
Format: "int32",
},
},
},
},
},
}
}
func schema_k8sio_api_flowcontrol_v1beta3_FlowDistinguisherMethod(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -35120,7 +35253,7 @@ func schema_k8sio_api_flowcontrol_v1beta3_LimitedPriorityLevelConfiguration(ref
Properties: map[string]spec.Schema{
"nominalConcurrencyShares": {
SchemaProps: spec.SchemaProps{
Description: "`nominalConcurrencyShares` (NCS) contributes to the computation of the NominalConcurrencyLimit (NominalCL) of this level. This is the number of execution seats available at this priority level. This is used both for requests dispatched from this priority level as well as requests dispatched from other priority levels borrowing seats from this level. The server's concurrency limit (ServerCL) is divided among the Limited priority levels in proportion to their NCS values:\n\nNominalCL(i) = ceil( ServerCL * NCS(i) / sum_ncs ) sum_ncs = sum[limited priority level k] NCS(k)\n\nBigger numbers mean a larger nominal concurrency limit, at the expense of every other Limited priority level. This field has a default value of 30.",
Description: "`nominalConcurrencyShares` (NCS) contributes to the computation of the NominalConcurrencyLimit (NominalCL) of this level. This is the number of execution seats available at this priority level. This is used both for requests dispatched from this priority level as well as requests dispatched from other priority levels borrowing seats from this level. The server's concurrency limit (ServerCL) is divided among the Limited priority levels in proportion to their NCS values:\n\nNominalCL(i) = ceil( ServerCL * NCS(i) / sum_ncs ) sum_ncs = sum[priority level k] NCS(k)\n\nBigger numbers mean a larger nominal concurrency limit, at the expense of every other priority level. This field has a default value of 30.",
Default: 0,
Type: []string{"integer"},
Format: "int32",
@@ -35476,6 +35609,12 @@ func schema_k8sio_api_flowcontrol_v1beta3_PriorityLevelConfigurationSpec(ref com
Ref: ref("k8s.io/api/flowcontrol/v1beta3.LimitedPriorityLevelConfiguration"),
},
},
"exempt": {
SchemaProps: spec.SchemaProps{
Description: "`exempt` specifies how requests are handled for an exempt priority level. This field MUST be empty if `type` is `\"Limited\"`. This field MAY be non-empty if `type` is `\"Exempt\"`. If empty and `type` is `\"Exempt\"` then the default values for `ExemptPriorityLevelConfiguration` apply.",
Ref: ref("k8s.io/api/flowcontrol/v1beta3.ExemptPriorityLevelConfiguration"),
},
},
},
Required: []string{"type"},
},
@@ -35485,6 +35624,7 @@ func schema_k8sio_api_flowcontrol_v1beta3_PriorityLevelConfigurationSpec(ref com
map[string]interface{}{
"discriminator": "type",
"fields-to-discriminateBy": map[string]interface{}{
"exempt": "Exempt",
"limited": "Limited",
},
},
@@ -35493,7 +35633,7 @@ func schema_k8sio_api_flowcontrol_v1beta3_PriorityLevelConfigurationSpec(ref com
},
},
Dependencies: []string{
"k8s.io/api/flowcontrol/v1beta3.LimitedPriorityLevelConfiguration"},
"k8s.io/api/flowcontrol/v1beta3.ExemptPriorityLevelConfiguration", "k8s.io/api/flowcontrol/v1beta3.LimitedPriorityLevelConfiguration"},
}
}

View File

@@ -26,7 +26,7 @@ import (
func NewPriorityLevelConfigurationOps(client flowcontrolclient.PriorityLevelConfigurationInterface, lister flowcontrollisters.PriorityLevelConfigurationLister) ObjectOps[*flowcontrolv1beta3.PriorityLevelConfiguration] {
return NewObjectOps[*flowcontrolv1beta3.PriorityLevelConfiguration](client, lister, (*flowcontrolv1beta3.PriorityLevelConfiguration).DeepCopy,
plcReplaceSpec, plcSpecEqual)
plcReplaceSpec, plcSpecEqualish)
}
func plcReplaceSpec(into, from *flowcontrolv1beta3.PriorityLevelConfiguration) *flowcontrolv1beta3.PriorityLevelConfiguration {
@@ -35,8 +35,15 @@ func plcReplaceSpec(into, from *flowcontrolv1beta3.PriorityLevelConfiguration) *
return copy
}
func plcSpecEqual(expected, actual *flowcontrolv1beta3.PriorityLevelConfiguration) bool {
func plcSpecEqualish(expected, actual *flowcontrolv1beta3.PriorityLevelConfiguration) bool {
copiedExpected := expected.DeepCopy()
flowcontrolapisv1beta3.SetObjectDefaults_PriorityLevelConfiguration(copiedExpected)
if expected.Name == flowcontrolv1beta3.PriorityLevelConfigurationNameExempt {
if actual.Spec.Exempt == nil {
return false
}
copiedExpected.Spec.Exempt.NominalConcurrencyShares = actual.Spec.Exempt.NominalConcurrencyShares
copiedExpected.Spec.Exempt.LendablePercent = actual.Spec.Exempt.LendablePercent
}
return equality.Semantic.DeepEqual(copiedExpected.Spec, actual.Spec)
}

View File

@@ -35,6 +35,14 @@ import (
)
func TestEnsurePriorityLevel(t *testing.T) {
validExemptPL := func() *flowcontrolv1beta3.PriorityLevelConfiguration {
copy := bootstrap.MandatoryPriorityLevelConfigurationExempt.DeepCopy()
copy.Annotations[flowcontrolv1beta3.AutoUpdateAnnotationKey] = "true"
copy.Spec.Exempt.NominalConcurrencyShares = pointer.Int32(10)
copy.Spec.Exempt.LendablePercent = pointer.Int32(50)
return copy
}()
tests := []struct {
name string
strategy func() EnsureStrategy[*flowcontrolv1beta3.PriorityLevelConfiguration]
@@ -87,6 +95,15 @@ func TestEnsurePriorityLevel(t *testing.T) {
current: newPLConfiguration("pl1").WithAutoUpdateAnnotation("false").WithLimited(10).Object(),
expected: newPLConfiguration("pl1").WithAutoUpdateAnnotation("true").WithLimited(20).Object(),
},
{
name: "admin changes the Exempt field of the exempt priority level configuration",
strategy: NewMandatoryEnsureStrategy[*flowcontrolv1beta3.PriorityLevelConfiguration],
bootstrap: func() *flowcontrolv1beta3.PriorityLevelConfiguration {
return bootstrap.MandatoryPriorityLevelConfigurationExempt
}(),
current: validExemptPL,
expected: validExemptPL,
},
}
for _, test := range tests {
@@ -264,6 +281,41 @@ func TestPriorityLevelSpecChanged(t *testing.T) {
},
},
}
ple1 := &flowcontrolv1beta3.PriorityLevelConfiguration{
ObjectMeta: metav1.ObjectMeta{Name: "exempt"},
Spec: flowcontrolv1beta3.PriorityLevelConfigurationSpec{
Type: flowcontrolv1beta3.PriorityLevelEnablementExempt,
Exempt: &flowcontrolv1beta3.ExemptPriorityLevelConfiguration{
NominalConcurrencyShares: pointer.Int32(42),
LendablePercent: pointer.Int32(33),
},
},
}
ple2 := &flowcontrolv1beta3.PriorityLevelConfiguration{
ObjectMeta: metav1.ObjectMeta{Name: "exempt"},
Spec: flowcontrolv1beta3.PriorityLevelConfigurationSpec{
Type: flowcontrolv1beta3.PriorityLevelEnablementExempt,
Exempt: &flowcontrolv1beta3.ExemptPriorityLevelConfiguration{
NominalConcurrencyShares: pointer.Int32(24),
LendablePercent: pointer.Int32(86),
},
},
}
pleWrong := &flowcontrolv1beta3.PriorityLevelConfiguration{
ObjectMeta: metav1.ObjectMeta{Name: "exempt"},
Spec: flowcontrolv1beta3.PriorityLevelConfigurationSpec{
Type: flowcontrolv1beta3.PriorityLevelEnablementLimited,
Limited: &flowcontrolv1beta3.LimitedPriorityLevelConfiguration{
NominalConcurrencyShares: 1,
},
},
}
pleInvalid := &flowcontrolv1beta3.PriorityLevelConfiguration{
ObjectMeta: metav1.ObjectMeta{Name: "exempt"},
Spec: flowcontrolv1beta3.PriorityLevelConfigurationSpec{
Type: "widget",
},
}
testCases := []struct {
name string
expected *flowcontrolv1beta3.PriorityLevelConfiguration
@@ -288,10 +340,28 @@ func TestPriorityLevelSpecChanged(t *testing.T) {
actual: pl2,
specChanged: true,
},
{
name: "tweaked exempt config",
expected: ple1,
actual: ple2,
specChanged: false,
},
{
name: "exempt with wrong tag",
expected: ple1,
actual: pleWrong,
specChanged: true,
},
{
name: "exempt with invalid tag",
expected: ple1,
actual: pleInvalid,
specChanged: true,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
w := !plcSpecEqual(testCase.expected, testCase.actual)
w := !plcSpecEqualish(testCase.expected, testCase.actual)
if testCase.specChanged != w {
t.Errorf("Expected priorityLevelSpecChanged to return %t, but got: %t - diff: %s", testCase.specChanged, w,
cmp.Diff(testCase.expected, testCase.actual))

View File

@@ -69,8 +69,10 @@ type objectLocalOps[ObjectType configurationObject] interface {
// replaceSpec returns a deep copy of `into` except that the spec is a deep copy of `from`
ReplaceSpec(into, from ObjectType) ObjectType
// specEqual says whether applying defaulting to `expected` makes its spec equal that of `actual`
SpecEqual(expected, actual ObjectType) bool
// SpecEqualish says whether applying defaulting to `expected`
// makes its spec more or less equal (as appropriate for the
// object at hand) that of `actual`.
SpecEqualish(expected, actual ObjectType) bool
}
// ObjectOps is the needed operations, both as a receiver from a server and server-independent, on configurationObjects
@@ -109,21 +111,21 @@ type configurationObjectType interface {
type objectOps[ObjectType configurationObjectType] struct {
client[ObjectType]
cache[ObjectType]
deepCopy func(ObjectType) ObjectType
replaceSpec func(ObjectType, ObjectType) ObjectType
specEqual func(expected, actual ObjectType) bool
deepCopy func(ObjectType) ObjectType
replaceSpec func(ObjectType, ObjectType) ObjectType
specEqualish func(expected, actual ObjectType) bool
}
func NewObjectOps[ObjectType configurationObjectType](client client[ObjectType], cache cache[ObjectType],
deepCopy func(ObjectType) ObjectType,
replaceSpec func(ObjectType, ObjectType) ObjectType,
specEqual func(expected, actual ObjectType) bool,
specEqualish func(expected, actual ObjectType) bool,
) ObjectOps[ObjectType] {
return objectOps[ObjectType]{client: client,
cache: cache,
deepCopy: deepCopy,
replaceSpec: replaceSpec,
specEqual: specEqual}
cache: cache,
deepCopy: deepCopy,
replaceSpec: replaceSpec,
specEqualish: specEqualish}
}
func (oo objectOps[ObjectType]) DeepCopy(obj ObjectType) ObjectType { return oo.deepCopy(obj) }
@@ -132,34 +134,30 @@ func (oo objectOps[ObjectType]) ReplaceSpec(into, from ObjectType) ObjectType {
return oo.replaceSpec(into, from)
}
func (oo objectOps[ObjectType]) SpecEqual(expected, actual ObjectType) bool {
return oo.specEqual(expected, actual)
func (oo objectOps[ObjectType]) SpecEqualish(expected, actual ObjectType) bool {
return oo.specEqualish(expected, actual)
}
// NewSuggestedEnsureStrategy returns an EnsureStrategy for suggested config objects
func NewSuggestedEnsureStrategy[ObjectType configurationObjectType]() EnsureStrategy[ObjectType] {
return &strategy[ObjectType]{
alwaysAutoUpdateSpecFn: func(want, have ObjectType) bool {
return false
},
name: "suggested",
alwaysAutoUpdateSpec: false,
name: "suggested",
}
}
// NewMandatoryEnsureStrategy returns an EnsureStrategy for mandatory config objects
func NewMandatoryEnsureStrategy[ObjectType configurationObjectType]() EnsureStrategy[ObjectType] {
return &strategy[ObjectType]{
alwaysAutoUpdateSpecFn: func(want, have ObjectType) bool {
return true
},
name: "mandatory",
alwaysAutoUpdateSpec: true,
name: "mandatory",
}
}
// auto-update strategy for the configuration objects
type strategy[ObjectType configurationObjectType] struct {
alwaysAutoUpdateSpecFn func(want, have ObjectType) bool
name string
alwaysAutoUpdateSpec bool
name string
}
func (s *strategy[ObjectType]) Name() string {
@@ -172,14 +170,13 @@ func (s *strategy[ObjectType]) ReviseIfNeeded(objectOps objectLocalOps[ObjectTyp
return zero, false, nil
}
autoUpdateSpec := s.alwaysAutoUpdateSpecFn(bootstrap, current)
autoUpdateSpec := s.alwaysAutoUpdateSpec
if !autoUpdateSpec {
autoUpdateSpec = shouldUpdateSpec(current)
}
updateAnnotation := shouldUpdateAnnotation(current, autoUpdateSpec)
// specChanged := autoUpdateSpec && wah.specsDiffer()
specChanged := autoUpdateSpec && !objectOps.SpecEqual(bootstrap, current)
specChanged := autoUpdateSpec && !objectOps.SpecEqualish(bootstrap, current)
if !(updateAnnotation || specChanged) {
// the annotation key is up to date and the spec has not changed, no update is necessary