Merge pull request #118782 from MikeSpreitzer/exempt-borrowing-impl
Exempt borrowing implementation
This commit is contained in:
@@ -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
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 ||
|
||||
|
||||
@@ -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",
|
||||
|
||||
31
pkg/apis/flowcontrol/zz_generated.deepcopy.go
generated
31
pkg/apis/flowcontrol/zz_generated.deepcopy.go
generated
@@ -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
|
||||
}
|
||||
|
||||
|
||||
150
pkg/generated/openapi/zz_generated.openapi.go
generated
150
pkg/generated/openapi/zz_generated.openapi.go
generated
@@ -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"},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user