diff --git a/pkg/apis/core/validation/validation.go b/pkg/apis/core/validation/validation.go index 9f6f8da5b42..b15eef0207d 100644 --- a/pkg/apis/core/validation/validation.go +++ b/pkg/apis/core/validation/validation.go @@ -7491,7 +7491,7 @@ var ( func ValidateLoadBalancerStatus(status *core.LoadBalancerStatus, fldPath *field.Path, spec *core.ServiceSpec) field.ErrorList { allErrs := field.ErrorList{} ingrPath := fldPath.Child("ingress") - if spec.Type != core.ServiceTypeLoadBalancer && len(status.Ingress) != 0 { + if !utilfeature.DefaultFeatureGate.Enabled(features.AllowServiceLBStatusOnNonLB) && spec.Type != core.ServiceTypeLoadBalancer && len(status.Ingress) != 0 { allErrs = append(allErrs, field.Forbidden(ingrPath, "may only be used when `spec.type` is 'LoadBalancer'")) } else { for i, ingress := range status.Ingress { diff --git a/pkg/apis/core/validation/validation_test.go b/pkg/apis/core/validation/validation_test.go index e7eb7804d96..72dbcff461f 100644 --- a/pkg/apis/core/validation/validation_test.go +++ b/pkg/apis/core/validation/validation_test.go @@ -24044,12 +24044,14 @@ func TestValidateLoadBalancerStatus(t *testing.T) { testCases := []struct { name string ipModeEnabled bool + nonLBAllowed bool tweakLBStatus func(s *core.LoadBalancerStatus) tweakSvcSpec func(s *core.ServiceSpec) numErrs int }{ { - name: "type is not LB", + name: "type is not LB", + nonLBAllowed: false, tweakSvcSpec: func(s *core.ServiceSpec) { s.Type = core.ServiceTypeClusterIP }, @@ -24059,6 +24061,18 @@ func TestValidateLoadBalancerStatus(t *testing.T) { }} }, numErrs: 1, + }, { + name: "type is not LB. back-compat", + nonLBAllowed: true, + tweakSvcSpec: func(s *core.ServiceSpec) { + s.Type = core.ServiceTypeClusterIP + }, + tweakLBStatus: func(s *core.LoadBalancerStatus) { + s.Ingress = []core.LoadBalancerIngress{{ + IP: "1.2.3.4", + }} + }, + numErrs: 0, }, { name: "valid vip ipMode", ipModeEnabled: true, @@ -24124,6 +24138,7 @@ func TestValidateLoadBalancerStatus(t *testing.T) { featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.31")) } featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.LoadBalancerIPMode, tc.ipModeEnabled) + featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.AllowServiceLBStatusOnNonLB, tc.nonLBAllowed) status := core.LoadBalancerStatus{} tc.tweakLBStatus(&status) spec := core.ServiceSpec{Type: core.ServiceTypeLoadBalancer} diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index d7fd604e1dd..6aab6555664 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -48,6 +48,13 @@ const ( // Allow spec.terminationGracePeriodSeconds to be overridden by MaxPodGracePeriodSeconds in soft evictions. AllowOverwriteTerminationGracePeriodSeconds featuregate.Feature = "AllowOverwriteTerminationGracePeriodSeconds" + // owner: @thockin + // deprecated: v1.29 + // + // Enables Service.status.ingress.loadBanace to be set on + // services of types other than LoadBalancer. + AllowServiceLBStatusOnNonLB featuregate.Feature = "AllowServiceLBStatusOnNonLB" + // owner: @bswartz // // Enables usage of any object for volume data source in PVCs