Adding IngressClass to networking/v1beta1
Co-authored-by: Christopher M. Luciano <cmluciano@us.ibm.com>
This commit is contained in:
@@ -17,11 +17,14 @@ go_test(
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/networking:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/validation:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
|
||||
"//vendor/k8s.io/utils/pointer:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -38,6 +41,7 @@ go_library(
|
||||
"//pkg/apis/networking:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/validation:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/validation/path:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1/validation:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
|
@@ -22,6 +22,7 @@ import (
|
||||
"strings"
|
||||
|
||||
apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation"
|
||||
pathvalidation "k8s.io/apimachinery/pkg/api/validation/path"
|
||||
unversionedvalidation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
@@ -32,6 +33,11 @@ import (
|
||||
"k8s.io/kubernetes/pkg/apis/networking"
|
||||
)
|
||||
|
||||
const (
|
||||
annotationIngressClass = "kubernetes.io/ingress.class"
|
||||
maxLenIngressClassController = 250
|
||||
)
|
||||
|
||||
// ValidateNetworkPolicyName can be used to check whether the given networkpolicy
|
||||
// name is valid.
|
||||
func ValidateNetworkPolicyName(name string, prefix bool) []string {
|
||||
@@ -174,15 +180,35 @@ func ValidateIPBlock(ipb *networking.IPBlock, fldPath *field.Path) field.ErrorLi
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateIngress tests if required fields in the Ingress are set.
|
||||
// ValidateIngressName validates that the given name can be used as an Ingress
|
||||
// name.
|
||||
var ValidateIngressName = apimachineryvalidation.NameIsDNSSubdomain
|
||||
|
||||
// ValidateIngress validates Ingresses on create and update.
|
||||
func ValidateIngress(ingress *networking.Ingress) field.ErrorList {
|
||||
allErrs := apivalidation.ValidateObjectMeta(&ingress.ObjectMeta, true, ValidateIngressName, field.NewPath("metadata"))
|
||||
allErrs = append(allErrs, ValidateIngressSpec(&ingress.Spec, field.NewPath("spec"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateIngressName validates that the given name can be used as an Ingress name.
|
||||
var ValidateIngressName = apimachineryvalidation.NameIsDNSSubdomain
|
||||
// ValidateIngressCreate validates Ingresses on create.
|
||||
func ValidateIngressCreate(ingress *networking.Ingress) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
allErrs = append(allErrs, ValidateIngress(ingress)...)
|
||||
annotationVal, annotationIsSet := ingress.Annotations[annotationIngressClass]
|
||||
if annotationIsSet && ingress.Spec.IngressClassName != nil {
|
||||
annotationPath := field.NewPath("annotations").Child(annotationIngressClass)
|
||||
allErrs = append(allErrs, field.Invalid(annotationPath, annotationVal, "can not be set when the class field is also set"))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateIngressUpdate validates ingresses on update.
|
||||
func ValidateIngressUpdate(ingress, oldIngress *networking.Ingress) field.ErrorList {
|
||||
allErrs := apivalidation.ValidateObjectMetaUpdate(&ingress.ObjectMeta, &oldIngress.ObjectMeta, field.NewPath("metadata"))
|
||||
allErrs = append(allErrs, ValidateIngress(ingress)...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateIngressTLS(spec *networking.IngressSpec, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
@@ -220,13 +246,11 @@ func ValidateIngressSpec(spec *networking.IngressSpec, fldPath *field.Path) fiel
|
||||
if len(spec.TLS) > 0 {
|
||||
allErrs = append(allErrs, validateIngressTLS(spec, fldPath.Child("tls"))...)
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateIngressUpdate tests if required fields in the Ingress are set.
|
||||
func ValidateIngressUpdate(ingress, oldIngress *networking.Ingress) field.ErrorList {
|
||||
allErrs := apivalidation.ValidateObjectMetaUpdate(&ingress.ObjectMeta, &oldIngress.ObjectMeta, field.NewPath("metadata"))
|
||||
allErrs = append(allErrs, ValidateIngressSpec(&ingress.Spec, field.NewPath("spec"))...)
|
||||
if spec.IngressClassName != nil {
|
||||
for _, msg := range ValidateIngressClassName(*spec.IngressClassName, false) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("ingressClassName"), *spec.IngressClassName, msg))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
@@ -315,3 +339,72 @@ func validateIngressBackend(backend *networking.IngressBackend, fldPath *field.P
|
||||
allErrs = append(allErrs, apivalidation.ValidatePortNumOrName(backend.ServicePort, fldPath.Child("servicePort"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateIngressClassName validates that the given name can be used as an
|
||||
// IngressClass name.
|
||||
var ValidateIngressClassName = apimachineryvalidation.NameIsDNSSubdomain
|
||||
|
||||
// ValidateIngressClass ensures that IngressClass resources are valid.
|
||||
func ValidateIngressClass(ingressClass *networking.IngressClass) field.ErrorList {
|
||||
allErrs := apivalidation.ValidateObjectMeta(&ingressClass.ObjectMeta, false, ValidateIngressClassName, field.NewPath("metadata"))
|
||||
allErrs = append(allErrs, validateIngressClassSpec(&ingressClass.Spec, field.NewPath("spec"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateIngressClassUpdate ensures that IngressClass updates are valid.
|
||||
func ValidateIngressClassUpdate(newIngressClass, oldIngressClass *networking.IngressClass) field.ErrorList {
|
||||
allErrs := apivalidation.ValidateObjectMetaUpdate(&newIngressClass.ObjectMeta, &oldIngressClass.ObjectMeta, field.NewPath("metadata"))
|
||||
allErrs = append(allErrs, validateIngressClassSpecUpdate(&newIngressClass.Spec, &oldIngressClass.Spec, field.NewPath("spec"))...)
|
||||
allErrs = append(allErrs, ValidateIngressClass(newIngressClass)...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// validateIngressClassSpec ensures that IngressClassSpec fields are valid.
|
||||
func validateIngressClassSpec(spec *networking.IngressClassSpec, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(spec.Controller) > maxLenIngressClassController {
|
||||
allErrs = append(allErrs, field.TooLong(fldPath.Child("controller"), spec.Controller, maxLenIngressClassController))
|
||||
}
|
||||
allErrs = append(allErrs, validation.IsDomainPrefixedPath(fldPath.Child("controller"), spec.Controller)...)
|
||||
allErrs = append(allErrs, validateIngressClassParameters(spec.Parameters, fldPath.Child("parameters"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// validateIngressClassSpecUpdate ensures that IngressClassSpec updates are
|
||||
// valid.
|
||||
func validateIngressClassSpecUpdate(newSpec, oldSpec *networking.IngressClassSpec, fldPath *field.Path) field.ErrorList {
|
||||
return apivalidation.ValidateImmutableField(newSpec.Controller, oldSpec.Controller, fldPath.Child("controller"))
|
||||
}
|
||||
|
||||
// validateIngressClassParameters ensures that Parameters fields are valid.
|
||||
func validateIngressClassParameters(params *api.TypedLocalObjectReference, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if params == nil {
|
||||
return allErrs
|
||||
}
|
||||
|
||||
if params.APIGroup != nil {
|
||||
for _, msg := range validation.IsDNS1123Subdomain(*params.APIGroup) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("apiGroup"), *params.APIGroup, msg))
|
||||
}
|
||||
}
|
||||
|
||||
if params.Kind == "" {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("kind"), "kind is required"))
|
||||
} else {
|
||||
for _, msg := range pathvalidation.IsValidPathSegmentName(params.Kind) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("kind"), params.Kind, msg))
|
||||
}
|
||||
}
|
||||
|
||||
if params.Name == "" {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("name"), "name is required"))
|
||||
} else {
|
||||
for _, msg := range pathvalidation.IsValidPathSegmentName(params.Name) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), params.Name, msg))
|
||||
}
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
@@ -18,6 +18,9 @@ package validation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
utilpointer "k8s.io/utils/pointer"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -993,6 +996,313 @@ func TestValidateIngress(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateIngressCreate(t *testing.T) {
|
||||
baseIngress := networking.Ingress{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test123",
|
||||
Namespace: "test123",
|
||||
ResourceVersion: "1234",
|
||||
},
|
||||
Spec: networking.IngressSpec{
|
||||
Backend: &networking.IngressBackend{
|
||||
ServiceName: "default-backend",
|
||||
ServicePort: intstr.FromInt(80),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
testCases := map[string]struct {
|
||||
tweakIngress func(ingress *networking.Ingress)
|
||||
expectedErrs field.ErrorList
|
||||
}{
|
||||
"class field set": {
|
||||
tweakIngress: func(ingress *networking.Ingress) {
|
||||
ingress.Spec.IngressClassName = utilpointer.StringPtr("bar")
|
||||
},
|
||||
expectedErrs: field.ErrorList{},
|
||||
},
|
||||
"class annotation set": {
|
||||
tweakIngress: func(ingress *networking.Ingress) {
|
||||
ingress.Annotations = map[string]string{annotationIngressClass: "foo"}
|
||||
},
|
||||
expectedErrs: field.ErrorList{},
|
||||
},
|
||||
"class field and annotation set": {
|
||||
tweakIngress: func(ingress *networking.Ingress) {
|
||||
ingress.Spec.IngressClassName = utilpointer.StringPtr("bar")
|
||||
ingress.Annotations = map[string]string{annotationIngressClass: "foo"}
|
||||
},
|
||||
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("annotations").Child(annotationIngressClass), "foo", "can not be set when the class field is also set")},
|
||||
},
|
||||
}
|
||||
|
||||
for name, testCase := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
newIngress := baseIngress.DeepCopy()
|
||||
testCase.tweakIngress(newIngress)
|
||||
|
||||
errs := ValidateIngressCreate(newIngress)
|
||||
if len(errs) != len(testCase.expectedErrs) {
|
||||
t.Fatalf("Expected %d errors, got %d (%+v)", len(testCase.expectedErrs), len(errs), errs)
|
||||
}
|
||||
|
||||
for i, err := range errs {
|
||||
if err.Error() != testCase.expectedErrs[i].Error() {
|
||||
t.Fatalf("Expected error: %v, got %v", testCase.expectedErrs[i].Error(), err.Error())
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateIngressUpdate(t *testing.T) {
|
||||
baseIngress := networking.Ingress{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test123",
|
||||
Namespace: "test123",
|
||||
ResourceVersion: "1234",
|
||||
},
|
||||
Spec: networking.IngressSpec{
|
||||
Backend: &networking.IngressBackend{
|
||||
ServiceName: "default-backend",
|
||||
ServicePort: intstr.FromInt(80),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
testCases := map[string]struct {
|
||||
tweakIngresses func(newIngress, oldIngress *networking.Ingress)
|
||||
expectedErrs field.ErrorList
|
||||
}{
|
||||
"class field set": {
|
||||
tweakIngresses: func(newIngress, oldIngress *networking.Ingress) {
|
||||
newIngress.Spec.IngressClassName = utilpointer.StringPtr("bar")
|
||||
},
|
||||
expectedErrs: field.ErrorList{},
|
||||
},
|
||||
"class annotation set": {
|
||||
tweakIngresses: func(newIngress, oldIngress *networking.Ingress) {
|
||||
newIngress.Annotations = map[string]string{annotationIngressClass: "foo"}
|
||||
},
|
||||
expectedErrs: field.ErrorList{},
|
||||
},
|
||||
"class field and annotation set": {
|
||||
tweakIngresses: func(newIngress, oldIngress *networking.Ingress) {
|
||||
newIngress.Spec.IngressClassName = utilpointer.StringPtr("bar")
|
||||
newIngress.Annotations = map[string]string{annotationIngressClass: "foo"}
|
||||
},
|
||||
expectedErrs: field.ErrorList{},
|
||||
},
|
||||
}
|
||||
|
||||
for name, testCase := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
newIngress := baseIngress.DeepCopy()
|
||||
oldIngress := baseIngress.DeepCopy()
|
||||
testCase.tweakIngresses(newIngress, oldIngress)
|
||||
|
||||
errs := ValidateIngressUpdate(newIngress, oldIngress)
|
||||
|
||||
if len(errs) != len(testCase.expectedErrs) {
|
||||
t.Fatalf("Expected %d errors, got %d (%+v)", len(testCase.expectedErrs), len(errs), errs)
|
||||
}
|
||||
|
||||
for i, err := range errs {
|
||||
if err.Error() != testCase.expectedErrs[i].Error() {
|
||||
t.Fatalf("Expected error: %v, got %v", testCase.expectedErrs[i].Error(), err.Error())
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateIngressClass(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
ingressClass networking.IngressClass
|
||||
expectedErrs field.ErrorList
|
||||
}{
|
||||
"valid name, valid controller": {
|
||||
ingressClass: networking.IngressClass{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test123"},
|
||||
Spec: networking.IngressClassSpec{
|
||||
Controller: "foo.co/bar",
|
||||
},
|
||||
},
|
||||
expectedErrs: field.ErrorList{},
|
||||
},
|
||||
"invalid name, valid controller": {
|
||||
ingressClass: networking.IngressClass{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test*123"},
|
||||
Spec: networking.IngressClassSpec{
|
||||
Controller: "foo.co/bar",
|
||||
},
|
||||
},
|
||||
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("metadata.name"), "test*123", "a DNS-1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*')")},
|
||||
},
|
||||
"valid name, empty controller": {
|
||||
ingressClass: networking.IngressClass{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test123"},
|
||||
Spec: networking.IngressClassSpec{
|
||||
Controller: "",
|
||||
},
|
||||
},
|
||||
expectedErrs: field.ErrorList{field.Required(field.NewPath("spec.controller"), "")},
|
||||
},
|
||||
"valid name, controller max length": {
|
||||
ingressClass: networking.IngressClass{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test123"},
|
||||
Spec: networking.IngressClassSpec{
|
||||
Controller: "foo.co/" + strings.Repeat("a", 243),
|
||||
},
|
||||
},
|
||||
expectedErrs: field.ErrorList{},
|
||||
},
|
||||
"valid name, controller too long": {
|
||||
ingressClass: networking.IngressClass{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test123"},
|
||||
Spec: networking.IngressClassSpec{
|
||||
Controller: "foo.co/" + strings.Repeat("a", 244),
|
||||
},
|
||||
},
|
||||
expectedErrs: field.ErrorList{field.TooLong(field.NewPath("spec.controller"), "", 250)},
|
||||
},
|
||||
"valid name, valid controller, valid params": {
|
||||
ingressClass: networking.IngressClass{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test123"},
|
||||
Spec: networking.IngressClassSpec{
|
||||
Controller: "foo.co/bar",
|
||||
Parameters: &api.TypedLocalObjectReference{
|
||||
APIGroup: utilpointer.StringPtr("example.com"),
|
||||
Kind: "foo",
|
||||
Name: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErrs: field.ErrorList{},
|
||||
},
|
||||
"valid name, valid controller, invalid params (no kind)": {
|
||||
ingressClass: networking.IngressClass{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test123"},
|
||||
Spec: networking.IngressClassSpec{
|
||||
Controller: "foo.co/bar",
|
||||
Parameters: &api.TypedLocalObjectReference{
|
||||
APIGroup: utilpointer.StringPtr("example.com"),
|
||||
Name: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErrs: field.ErrorList{field.Required(field.NewPath("spec.parameters.kind"), "kind is required")},
|
||||
},
|
||||
"valid name, valid controller, invalid params (no name)": {
|
||||
ingressClass: networking.IngressClass{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test123"},
|
||||
Spec: networking.IngressClassSpec{
|
||||
Controller: "foo.co/bar",
|
||||
Parameters: &api.TypedLocalObjectReference{
|
||||
Kind: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErrs: field.ErrorList{field.Required(field.NewPath("spec.parameters.name"), "name is required")},
|
||||
},
|
||||
"valid name, valid controller, invalid params (bad kind)": {
|
||||
ingressClass: networking.IngressClass{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test123"},
|
||||
Spec: networking.IngressClassSpec{
|
||||
Controller: "foo.co/bar",
|
||||
Parameters: &api.TypedLocalObjectReference{
|
||||
Kind: "foo/",
|
||||
Name: "bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec.parameters.kind"), "foo/", "may not contain '/'")},
|
||||
},
|
||||
}
|
||||
|
||||
for name, testCase := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
errs := ValidateIngressClass(&testCase.ingressClass)
|
||||
|
||||
if len(errs) != len(testCase.expectedErrs) {
|
||||
t.Fatalf("Expected %d errors, got %d (%+v)", len(testCase.expectedErrs), len(errs), errs)
|
||||
}
|
||||
|
||||
for i, err := range errs {
|
||||
if err.Error() != testCase.expectedErrs[i].Error() {
|
||||
t.Fatalf("Expected error: %v, got %v", testCase.expectedErrs[i].Error(), err.Error())
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateIngressClassUpdate(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
newIngressClass networking.IngressClass
|
||||
oldIngressClass networking.IngressClass
|
||||
expectedErrs field.ErrorList
|
||||
}{
|
||||
"name change": {
|
||||
newIngressClass: networking.IngressClass{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test123",
|
||||
ResourceVersion: "2",
|
||||
},
|
||||
Spec: networking.IngressClassSpec{
|
||||
Controller: "foo.co/bar",
|
||||
},
|
||||
},
|
||||
oldIngressClass: networking.IngressClass{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test123"},
|
||||
Spec: networking.IngressClassSpec{
|
||||
Controller: "foo.co/different",
|
||||
},
|
||||
},
|
||||
expectedErrs: field.ErrorList{field.Invalid(field.NewPath("spec").Child("controller"), "foo.co/bar", apimachineryvalidation.FieldImmutableErrorMsg)},
|
||||
},
|
||||
"parameters change": {
|
||||
newIngressClass: networking.IngressClass{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "test123",
|
||||
ResourceVersion: "2",
|
||||
},
|
||||
Spec: networking.IngressClassSpec{
|
||||
Controller: "foo.co/bar",
|
||||
Parameters: &api.TypedLocalObjectReference{
|
||||
APIGroup: utilpointer.StringPtr("v1"),
|
||||
Kind: "ConfigMap",
|
||||
Name: "foo",
|
||||
},
|
||||
},
|
||||
},
|
||||
oldIngressClass: networking.IngressClass{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "test123"},
|
||||
Spec: networking.IngressClassSpec{
|
||||
Controller: "foo.co/bar",
|
||||
},
|
||||
},
|
||||
expectedErrs: field.ErrorList{},
|
||||
},
|
||||
}
|
||||
|
||||
for name, testCase := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
errs := ValidateIngressClassUpdate(&testCase.newIngressClass, &testCase.oldIngressClass)
|
||||
|
||||
if len(errs) != len(testCase.expectedErrs) {
|
||||
t.Fatalf("Expected %d errors, got %d (%+v)", len(testCase.expectedErrs), len(errs), errs)
|
||||
}
|
||||
|
||||
for i, err := range errs {
|
||||
if err.Error() != testCase.expectedErrs[i].Error() {
|
||||
t.Fatalf("Expected error: %v, got %v", testCase.expectedErrs[i].Error(), err.Error())
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateIngressTLS(t *testing.T) {
|
||||
defaultBackend := networking.IngressBackend{
|
||||
ServiceName: "default-backend",
|
||||
|
Reference in New Issue
Block a user