mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-20 09:33:52 +00:00
Graduate IngressClassNamespacedParams to GA
This commit is contained in:
@@ -339,15 +339,12 @@ type IngressClassParametersReference struct {
|
||||
Name string
|
||||
// Scope represents if this refers to a cluster or namespace scoped resource.
|
||||
// This may be set to "Cluster" (default) or "Namespace".
|
||||
// Field can be enabled with IngressClassNamespacedParams feature gate.
|
||||
// +optional
|
||||
// +featureGate=IngressClassNamespacedParams
|
||||
Scope *string
|
||||
// Namespace is the namespace of the resource being referenced. This field is
|
||||
// required when scope is set to "Namespace" and must be unset when scope is set to
|
||||
// "Cluster".
|
||||
// +optional
|
||||
// +featureGate=IngressClassNamespacedParams
|
||||
Namespace *string
|
||||
}
|
||||
|
||||
|
@@ -20,8 +20,6 @@ import (
|
||||
"k8s.io/api/core/v1"
|
||||
networkingv1 "k8s.io/api/networking/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
utilpointer "k8s.io/utils/pointer"
|
||||
)
|
||||
|
||||
@@ -48,9 +46,6 @@ func SetDefaults_NetworkPolicy(obj *networkingv1.NetworkPolicy) {
|
||||
}
|
||||
|
||||
func SetDefaults_IngressClass(obj *networkingv1.IngressClass) {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.IngressClassNamespacedParams) {
|
||||
return
|
||||
}
|
||||
if obj.Spec.Parameters != nil && obj.Spec.Parameters.Scope == nil {
|
||||
obj.Spec.Parameters.Scope = utilpointer.StringPtr(networkingv1.IngressClassParametersReferenceScopeCluster)
|
||||
}
|
||||
|
@@ -24,13 +24,10 @@ import (
|
||||
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
_ "k8s.io/kubernetes/pkg/apis/core/install"
|
||||
_ "k8s.io/kubernetes/pkg/apis/networking/install"
|
||||
. "k8s.io/kubernetes/pkg/apis/networking/v1"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
utilpointer "k8s.io/utils/pointer"
|
||||
)
|
||||
|
||||
@@ -240,13 +237,12 @@ func TestSetDefaultNetworkPolicy(t *testing.T) {
|
||||
|
||||
func TestSetDefaultsForIngressClassParametersReference(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
original *networkingv1.IngressClass
|
||||
expected *networkingv1.IngressClass
|
||||
enableNamespaceScopedParamsGate bool
|
||||
name string
|
||||
original *networkingv1.IngressClass
|
||||
expected *networkingv1.IngressClass
|
||||
}{
|
||||
{
|
||||
name: "populated parameters sets the default Scope when feature is enabled",
|
||||
name: "populated parameters sets the default Scope",
|
||||
original: &networkingv1.IngressClass{
|
||||
Spec: networkingv1.IngressClassSpec{
|
||||
Controller: "controller",
|
||||
@@ -266,10 +262,9 @@ func TestSetDefaultsForIngressClassParametersReference(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
enableNamespaceScopedParamsGate: true,
|
||||
},
|
||||
{
|
||||
name: "existing scope is not overridden when feature is enabled",
|
||||
name: "existing scope is not overridden",
|
||||
original: &networkingv1.IngressClass{
|
||||
Spec: networkingv1.IngressClassSpec{
|
||||
Controller: "controller",
|
||||
@@ -292,10 +287,9 @@ func TestSetDefaultsForIngressClassParametersReference(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
enableNamespaceScopedParamsGate: true,
|
||||
},
|
||||
{
|
||||
name: "empty Parameters does not set the default Scope when feature is enabled",
|
||||
name: "empty Parameters does not set the default Scope",
|
||||
original: &networkingv1.IngressClass{
|
||||
Spec: networkingv1.IngressClassSpec{
|
||||
Controller: "controller",
|
||||
@@ -306,43 +300,6 @@ func TestSetDefaultsForIngressClassParametersReference(t *testing.T) {
|
||||
Controller: "controller",
|
||||
},
|
||||
},
|
||||
enableNamespaceScopedParamsGate: true,
|
||||
},
|
||||
{
|
||||
name: "populated parameters does not set the default Scope when feature is disabled",
|
||||
original: &networkingv1.IngressClass{
|
||||
Spec: networkingv1.IngressClassSpec{
|
||||
Controller: "controller",
|
||||
Parameters: &networkingv1.IngressClassParametersReference{
|
||||
Kind: "k",
|
||||
Name: "n",
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: &networkingv1.IngressClass{
|
||||
Spec: networkingv1.IngressClassSpec{
|
||||
Controller: "controller",
|
||||
Parameters: &networkingv1.IngressClassParametersReference{
|
||||
Kind: "k",
|
||||
Name: "n",
|
||||
},
|
||||
},
|
||||
},
|
||||
enableNamespaceScopedParamsGate: false,
|
||||
},
|
||||
{
|
||||
name: "empty Parameters does not set the default Scope when feature is disabled",
|
||||
original: &networkingv1.IngressClass{
|
||||
Spec: networkingv1.IngressClassSpec{
|
||||
Controller: "controller",
|
||||
},
|
||||
},
|
||||
expected: &networkingv1.IngressClass{
|
||||
Spec: networkingv1.IngressClassSpec{
|
||||
Controller: "controller",
|
||||
},
|
||||
},
|
||||
enableNamespaceScopedParamsGate: false,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -350,7 +307,6 @@ func TestSetDefaultsForIngressClassParametersReference(t *testing.T) {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
original := test.original
|
||||
expected := test.expected
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.IngressClassNamespacedParams, test.enableNamespaceScopedParamsGate)()
|
||||
obj2 := roundTrip(t, runtime.Object(original))
|
||||
got, ok := obj2.(*networkingv1.IngressClass)
|
||||
if !ok {
|
||||
|
@@ -27,11 +27,9 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
|
||||
"k8s.io/kubernetes/pkg/apis/networking"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
netutils "k8s.io/utils/net"
|
||||
utilpointer "k8s.io/utils/pointer"
|
||||
)
|
||||
@@ -537,7 +535,7 @@ func validateIngressClassParametersReference(params *networking.IngressClassPara
|
||||
Name: params.Name,
|
||||
}, fldPath)...)
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.IngressClassNamespacedParams) && params.Scope == nil {
|
||||
if params.Scope == nil {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("scope"), ""))
|
||||
return allErrs
|
||||
}
|
||||
|
@@ -25,11 +25,8 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/networking"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
utilpointer "k8s.io/utils/pointer"
|
||||
)
|
||||
|
||||
@@ -1444,9 +1441,8 @@ func TestValidateIngressClass(t *testing.T) {
|
||||
}
|
||||
|
||||
testCases := map[string]struct {
|
||||
ingressClass *networking.IngressClass
|
||||
expectedErrs field.ErrorList
|
||||
enableNamespaceScopedParamsGate bool
|
||||
ingressClass *networking.IngressClass
|
||||
expectedErrs field.ErrorList
|
||||
}{
|
||||
"valid name, valid controller": {
|
||||
ingressClass: makeValidIngressClass("test123", "foo.co/bar"),
|
||||
@@ -1470,25 +1466,25 @@ func TestValidateIngressClass(t *testing.T) {
|
||||
},
|
||||
"valid name, valid controller, valid params": {
|
||||
ingressClass: makeValidIngressClass("test123", "foo.co/bar",
|
||||
setParams(makeIngressClassParams(utilpointer.StringPtr("example.com"), "foo", "bar", nil, nil)),
|
||||
setParams(makeIngressClassParams(utilpointer.StringPtr("example.com"), "foo", "bar", utilpointer.StringPtr("Cluster"), nil)),
|
||||
),
|
||||
expectedErrs: field.ErrorList{},
|
||||
},
|
||||
"valid name, valid controller, invalid params (no kind)": {
|
||||
ingressClass: makeValidIngressClass("test123", "foo.co/bar",
|
||||
setParams(makeIngressClassParams(utilpointer.StringPtr("example.com"), "", "bar", nil, nil)),
|
||||
setParams(makeIngressClassParams(utilpointer.StringPtr("example.com"), "", "bar", utilpointer.StringPtr("Cluster"), nil)),
|
||||
),
|
||||
expectedErrs: field.ErrorList{field.Required(field.NewPath("spec.parameters.kind"), "kind is required")},
|
||||
},
|
||||
"valid name, valid controller, invalid params (no name)": {
|
||||
ingressClass: makeValidIngressClass("test123", "foo.co/bar",
|
||||
setParams(makeIngressClassParams(utilpointer.StringPtr("example.com"), "foo", "", nil, nil)),
|
||||
setParams(makeIngressClassParams(utilpointer.StringPtr("example.com"), "foo", "", utilpointer.StringPtr("Cluster"), nil)),
|
||||
),
|
||||
expectedErrs: field.ErrorList{field.Required(field.NewPath("spec.parameters.name"), "name is required")},
|
||||
},
|
||||
"valid name, valid controller, invalid params (bad kind)": {
|
||||
ingressClass: makeValidIngressClass("test123", "foo.co/bar",
|
||||
setParams(makeIngressClassParams(nil, "foo/", "bar", nil, nil)),
|
||||
setParams(makeIngressClassParams(nil, "foo/", "bar", utilpointer.StringPtr("Cluster"), nil)),
|
||||
),
|
||||
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec.parameters.kind"), "foo/", "may not contain '/'")},
|
||||
},
|
||||
@@ -1496,7 +1492,6 @@ func TestValidateIngressClass(t *testing.T) {
|
||||
ingressClass: makeValidIngressClass("test123", "foo.co/bar",
|
||||
setParams(makeIngressClassParams(nil, "foo", "bar", utilpointer.StringPtr("bad-scope"), nil)),
|
||||
),
|
||||
enableNamespaceScopedParamsGate: true,
|
||||
expectedErrs: field.ErrorList{field.NotSupported(field.NewPath("spec.parameters.scope"),
|
||||
"bad-scope", []string{"Cluster", "Namespace"})},
|
||||
},
|
||||
@@ -1504,14 +1499,12 @@ func TestValidateIngressClass(t *testing.T) {
|
||||
ingressClass: makeValidIngressClass("test123", "foo.co/bar",
|
||||
setParams(makeIngressClassParams(nil, "foo", "bar", utilpointer.StringPtr("Namespace"), utilpointer.StringPtr("foo-ns"))),
|
||||
),
|
||||
enableNamespaceScopedParamsGate: true,
|
||||
expectedErrs: field.ErrorList{},
|
||||
expectedErrs: field.ErrorList{},
|
||||
},
|
||||
"valid name, valid controller, valid scope, invalid namespace": {
|
||||
ingressClass: makeValidIngressClass("test123", "foo.co/bar",
|
||||
setParams(makeIngressClassParams(nil, "foo", "bar", utilpointer.StringPtr("Namespace"), utilpointer.StringPtr("foo_ns"))),
|
||||
),
|
||||
enableNamespaceScopedParamsGate: true,
|
||||
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec.parameters.namespace"), "foo_ns",
|
||||
"a lowercase RFC 1123 label must consist of lower case alphanumeric characters or '-',"+
|
||||
" and must start and end with an alphanumeric character (e.g. 'my-name', or '123-abc', "+
|
||||
@@ -1521,14 +1514,12 @@ func TestValidateIngressClass(t *testing.T) {
|
||||
ingressClass: makeValidIngressClass("test123", "foo.co/bar",
|
||||
setParams(makeIngressClassParams(nil, "foo", "bar", utilpointer.StringPtr("Cluster"), nil)),
|
||||
),
|
||||
enableNamespaceScopedParamsGate: true,
|
||||
expectedErrs: field.ErrorList{},
|
||||
expectedErrs: field.ErrorList{},
|
||||
},
|
||||
"namespace not set when scope is Namespace": {
|
||||
ingressClass: makeValidIngressClass("test123", "foo.co/bar",
|
||||
setParams(makeIngressClassParams(nil, "foo", "bar", utilpointer.StringPtr("Namespace"), nil)),
|
||||
),
|
||||
enableNamespaceScopedParamsGate: true,
|
||||
expectedErrs: field.ErrorList{field.Required(field.NewPath("spec.parameters.namespace"),
|
||||
"`parameters.scope` is set to 'Namespace'")},
|
||||
},
|
||||
@@ -1536,7 +1527,6 @@ func TestValidateIngressClass(t *testing.T) {
|
||||
ingressClass: makeValidIngressClass("test123", "foo.co/bar",
|
||||
setParams(makeIngressClassParams(nil, "foo", "bar", utilpointer.StringPtr("Cluster"), utilpointer.StringPtr("foo-ns"))),
|
||||
),
|
||||
enableNamespaceScopedParamsGate: true,
|
||||
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec.parameters.namespace"),
|
||||
"`parameters.scope` is set to 'Cluster'")},
|
||||
},
|
||||
@@ -1544,38 +1534,13 @@ func TestValidateIngressClass(t *testing.T) {
|
||||
ingressClass: makeValidIngressClass("test123", "foo.co/bar",
|
||||
setParams(makeIngressClassParams(nil, "foo", "bar", utilpointer.StringPtr("Cluster"), utilpointer.StringPtr(""))),
|
||||
),
|
||||
enableNamespaceScopedParamsGate: true,
|
||||
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec.parameters.namespace"),
|
||||
"`parameters.scope` is set to 'Cluster'")},
|
||||
},
|
||||
"validation is performed when feature gate is disabled and scope is not empty": {
|
||||
ingressClass: makeValidIngressClass("test123", "foo.co/bar",
|
||||
setParams(makeIngressClassParams(nil, "foo", "bar", utilpointer.StringPtr("bad-scope"), nil)),
|
||||
),
|
||||
enableNamespaceScopedParamsGate: false,
|
||||
expectedErrs: field.ErrorList{field.NotSupported(field.NewPath("spec.parameters.scope"),
|
||||
"bad-scope", []string{"Cluster", "Namespace"})},
|
||||
},
|
||||
"validation fails when feature gate is enabled and scope is not set": {
|
||||
ingressClass: makeValidIngressClass("test123", "foo.co/bar",
|
||||
setParams(makeIngressClassParams(nil, "foo", "bar", nil, nil)),
|
||||
),
|
||||
enableNamespaceScopedParamsGate: true,
|
||||
expectedErrs: field.ErrorList{field.Required(field.NewPath("spec.parameters.scope"), "")},
|
||||
},
|
||||
"validation is performed when feature gate is disabled and namespace is not empty": {
|
||||
ingressClass: makeValidIngressClass("test123", "foo.co/bar",
|
||||
setParams(makeIngressClassParams(nil, "foo", "bar", nil, utilpointer.StringPtr("foo-ns"))),
|
||||
),
|
||||
enableNamespaceScopedParamsGate: false,
|
||||
expectedErrs: field.ErrorList{field.NotSupported(field.NewPath("spec.parameters.scope"),
|
||||
"", []string{"Cluster", "Namespace"})},
|
||||
},
|
||||
}
|
||||
|
||||
for name, testCase := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.IngressClassNamespacedParams, testCase.enableNamespaceScopedParamsGate)()
|
||||
errs := ValidateIngressClass(testCase.ingressClass)
|
||||
|
||||
if len(errs) != len(testCase.expectedErrs) {
|
||||
|
Reference in New Issue
Block a user