mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-28 05:57:25 +00:00
Allow resource backends in Ingress
This commit is contained in:
parent
8f7b8105a1
commit
1758d17689
@ -197,7 +197,6 @@ var ValidateIngressName = apimachineryvalidation.NameIsDNSSubdomain
|
|||||||
|
|
||||||
// IngressValidationOptions cover beta to GA transitions for HTTP PathType
|
// IngressValidationOptions cover beta to GA transitions for HTTP PathType
|
||||||
type IngressValidationOptions struct {
|
type IngressValidationOptions struct {
|
||||||
allowResourceBackend bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateIngress validates Ingresses on create and update.
|
// ValidateIngress validates Ingresses on create and update.
|
||||||
@ -211,10 +210,7 @@ func validateIngress(ingress *networking.Ingress, opts IngressValidationOptions,
|
|||||||
func ValidateIngressCreate(ingress *networking.Ingress, requestGV schema.GroupVersion) field.ErrorList {
|
func ValidateIngressCreate(ingress *networking.Ingress, requestGV schema.GroupVersion) field.ErrorList {
|
||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
var opts IngressValidationOptions
|
var opts IngressValidationOptions
|
||||||
opts = IngressValidationOptions{
|
opts = IngressValidationOptions{}
|
||||||
// TODO(cmluciano): Allow resource backend for 1.19.
|
|
||||||
allowResourceBackend: false,
|
|
||||||
}
|
|
||||||
allErrs = append(allErrs, validateIngress(ingress, opts, requestGV)...)
|
allErrs = append(allErrs, validateIngress(ingress, opts, requestGV)...)
|
||||||
annotationVal, annotationIsSet := ingress.Annotations[annotationIngressClass]
|
annotationVal, annotationIsSet := ingress.Annotations[annotationIngressClass]
|
||||||
if annotationIsSet && ingress.Spec.IngressClassName != nil {
|
if annotationIsSet && ingress.Spec.IngressClassName != nil {
|
||||||
@ -228,9 +224,7 @@ func ValidateIngressCreate(ingress *networking.Ingress, requestGV schema.GroupVe
|
|||||||
func ValidateIngressUpdate(ingress, oldIngress *networking.Ingress, requestGV schema.GroupVersion) field.ErrorList {
|
func ValidateIngressUpdate(ingress, oldIngress *networking.Ingress, requestGV schema.GroupVersion) field.ErrorList {
|
||||||
allErrs := apivalidation.ValidateObjectMetaUpdate(&ingress.ObjectMeta, &oldIngress.ObjectMeta, field.NewPath("metadata"))
|
allErrs := apivalidation.ValidateObjectMetaUpdate(&ingress.ObjectMeta, &oldIngress.ObjectMeta, field.NewPath("metadata"))
|
||||||
var opts IngressValidationOptions
|
var opts IngressValidationOptions
|
||||||
opts = IngressValidationOptions{
|
opts = IngressValidationOptions{}
|
||||||
allowResourceBackend: resourceBackendPresent(oldIngress),
|
|
||||||
}
|
|
||||||
|
|
||||||
allErrs = append(allErrs, validateIngress(ingress, opts, requestGV)...)
|
allErrs = append(allErrs, validateIngress(ingress, opts, requestGV)...)
|
||||||
return allErrs
|
return allErrs
|
||||||
@ -383,8 +377,6 @@ func validateIngressBackend(backend *networking.IngressBackend, fldPath *field.P
|
|||||||
switch {
|
switch {
|
||||||
case hasResourceBackend && hasServiceBackend:
|
case hasResourceBackend && hasServiceBackend:
|
||||||
return append(allErrs, field.Invalid(fldPath, "", "cannot set both resource and service backends"))
|
return append(allErrs, field.Invalid(fldPath, "", "cannot set both resource and service backends"))
|
||||||
case hasResourceBackend && !opts.allowResourceBackend:
|
|
||||||
return append(allErrs, field.Forbidden(fldPath.Child("resource"), "not supported; only service backends are supported in this version"))
|
|
||||||
case hasResourceBackend:
|
case hasResourceBackend:
|
||||||
allErrs = append(allErrs, validateIngressTypedLocalObjectReference(backend.Resource, fldPath.Child("resource"))...)
|
allErrs = append(allErrs, validateIngressTypedLocalObjectReference(backend.Resource, fldPath.Child("resource"))...)
|
||||||
default:
|
default:
|
||||||
@ -468,20 +460,3 @@ func validateIngressTypedLocalObjectReference(params *api.TypedLocalObjectRefere
|
|||||||
|
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
func resourceBackendPresent(ingress *networking.Ingress) bool {
|
|
||||||
if ingress.Spec.Backend != nil && ingress.Spec.Backend.Resource != nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
for _, rule := range ingress.Spec.Rules {
|
|
||||||
if rule.HTTP == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, path := range rule.HTTP.Paths {
|
|
||||||
if path.Backend.Resource != nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
@ -1336,14 +1336,14 @@ func TestValidateIngressCreate(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expectedErrs: field.ErrorList{},
|
expectedErrs: field.ErrorList{},
|
||||||
},
|
},
|
||||||
"Spec.Backend.Resource field not allowed on create": {
|
"Spec.Backend.Resource field allowed on create": {
|
||||||
tweakIngress: func(ingress *networking.Ingress) {
|
tweakIngress: func(ingress *networking.Ingress) {
|
||||||
ingress.Spec.Backend = &networking.IngressBackend{
|
ingress.Spec.Backend = &networking.IngressBackend{
|
||||||
Resource: resourceBackend}
|
Resource: resourceBackend}
|
||||||
},
|
},
|
||||||
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec.backend.resource"), "not supported; only service backends are supported in this version")},
|
expectedErrs: field.ErrorList{},
|
||||||
},
|
},
|
||||||
"Paths.Backend.Resource field not allowed on create": {
|
"Paths.Backend.Resource field allowed on create": {
|
||||||
tweakIngress: func(ingress *networking.Ingress) {
|
tweakIngress: func(ingress *networking.Ingress) {
|
||||||
ingress.Spec.Rules = []networking.IngressRule{{
|
ingress.Spec.Rules = []networking.IngressRule{{
|
||||||
Host: "foo.bar.com",
|
Host: "foo.bar.com",
|
||||||
@ -1359,7 +1359,7 @@ func TestValidateIngressCreate(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
},
|
},
|
||||||
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec.rules[0].http.paths[0].backend.resource"), "not supported; only service backends are supported in this version")},
|
expectedErrs: field.ErrorList{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1543,13 +1543,13 @@ func TestValidateIngressUpdate(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expectedErrs: field.ErrorList{},
|
expectedErrs: field.ErrorList{},
|
||||||
},
|
},
|
||||||
"new Backend.Resource not allowed on update": {
|
"new Backend.Resource allowed on update": {
|
||||||
tweakIngresses: func(newIngress, oldIngress *networking.Ingress) {
|
tweakIngresses: func(newIngress, oldIngress *networking.Ingress) {
|
||||||
oldIngress.Spec.Backend = &defaultBackend
|
oldIngress.Spec.Backend = &defaultBackend
|
||||||
newIngress.Spec.Backend = &networking.IngressBackend{
|
newIngress.Spec.Backend = &networking.IngressBackend{
|
||||||
Resource: resourceBackend}
|
Resource: resourceBackend}
|
||||||
},
|
},
|
||||||
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec.backend.resource"), "not supported; only service backends are supported in this version")},
|
expectedErrs: field.ErrorList{},
|
||||||
},
|
},
|
||||||
"old Backend.Resource allowed on update": {
|
"old Backend.Resource allowed on update": {
|
||||||
tweakIngresses: func(newIngress, oldIngress *networking.Ingress) {
|
tweakIngresses: func(newIngress, oldIngress *networking.Ingress) {
|
||||||
@ -1686,7 +1686,7 @@ func TestValidateIngressUpdate(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
},
|
},
|
||||||
expectedErrs: field.ErrorList{field.Forbidden(field.NewPath("spec.rules[0].http.paths[0].backend.resource"), "not supported; only service backends are supported in this version")},
|
expectedErrs: field.ErrorList{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2077,151 +2077,3 @@ func TestValidateIngressStatusUpdate(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateResourceBackendPresent(t *testing.T) {
|
|
||||||
implementationPathType := networking.PathTypeImplementationSpecific
|
|
||||||
defaultBackend := networking.IngressBackend{
|
|
||||||
ServiceName: "default-backend",
|
|
||||||
ServicePort: intstr.FromInt(80),
|
|
||||||
}
|
|
||||||
resourceBackend := &api.TypedLocalObjectReference{
|
|
||||||
APIGroup: utilpointer.StringPtr("example.com"),
|
|
||||||
Kind: "foo",
|
|
||||||
Name: "bar",
|
|
||||||
}
|
|
||||||
baseIngress := networking.Ingress{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "foo",
|
|
||||||
Namespace: metav1.NamespaceDefault,
|
|
||||||
},
|
|
||||||
Spec: networking.IngressSpec{
|
|
||||||
Backend: &networking.IngressBackend{
|
|
||||||
ServiceName: "default-backend",
|
|
||||||
ServicePort: intstr.FromInt(80),
|
|
||||||
},
|
|
||||||
Rules: []networking.IngressRule{
|
|
||||||
{
|
|
||||||
Host: "foo.bar.com",
|
|
||||||
IngressRuleValue: networking.IngressRuleValue{
|
|
||||||
HTTP: &networking.HTTPIngressRuleValue{
|
|
||||||
Paths: []networking.HTTPIngressPath{
|
|
||||||
{
|
|
||||||
Path: "/foo",
|
|
||||||
PathType: &implementationPathType,
|
|
||||||
Backend: defaultBackend,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Status: networking.IngressStatus{
|
|
||||||
LoadBalancer: api.LoadBalancerStatus{
|
|
||||||
Ingress: []api.LoadBalancerIngress{
|
|
||||||
{IP: "127.0.0.1"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
testCases := map[string]struct {
|
|
||||||
groupVersion *schema.GroupVersion
|
|
||||||
tweakIngress func(ing *networking.Ingress)
|
|
||||||
expectResourceBackend bool
|
|
||||||
}{
|
|
||||||
"nil spec.Backend and no paths": {
|
|
||||||
tweakIngress: func(ing *networking.Ingress) {
|
|
||||||
ing.Spec.Backend = nil
|
|
||||||
ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path = ""
|
|
||||||
},
|
|
||||||
expectResourceBackend: false,
|
|
||||||
},
|
|
||||||
"nil spec.Backend.Resource and no paths": {
|
|
||||||
tweakIngress: func(ing *networking.Ingress) {
|
|
||||||
ing.Spec.Backend = nil
|
|
||||||
ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths = []networking.HTTPIngressPath{}
|
|
||||||
},
|
|
||||||
expectResourceBackend: false,
|
|
||||||
},
|
|
||||||
"non-nil spec.Backend.Resource and no paths": {
|
|
||||||
tweakIngress: func(ing *networking.Ingress) {
|
|
||||||
ing.Spec.Backend = &networking.IngressBackend{
|
|
||||||
Resource: resourceBackend,
|
|
||||||
}
|
|
||||||
ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Path = ""
|
|
||||||
},
|
|
||||||
expectResourceBackend: true,
|
|
||||||
},
|
|
||||||
"nil spec.Backend, one rule with nil HTTP ": {
|
|
||||||
tweakIngress: func(ing *networking.Ingress) {
|
|
||||||
ing.Spec.Backend = nil
|
|
||||||
ing.Spec.Rules[0].IngressRuleValue.HTTP = nil
|
|
||||||
},
|
|
||||||
expectResourceBackend: false,
|
|
||||||
},
|
|
||||||
"nil spec.Backend, one rule with non-nil HTTP, no paths": {
|
|
||||||
tweakIngress: func(ing *networking.Ingress) {
|
|
||||||
ing.Spec.Backend = nil
|
|
||||||
ing.Spec.Rules[0].IngressRuleValue = networking.IngressRuleValue{
|
|
||||||
HTTP: &networking.HTTPIngressRuleValue{
|
|
||||||
Paths: []networking.HTTPIngressPath{},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
expectResourceBackend: false,
|
|
||||||
},
|
|
||||||
"nil spec.Backend, one rule with non-nil HTTP, one path with nil Backend.Resource": {
|
|
||||||
tweakIngress: func(ing *networking.Ingress) {
|
|
||||||
ing.Spec.Backend = nil
|
|
||||||
ing.Spec.Rules[0].IngressRuleValue = networking.IngressRuleValue{
|
|
||||||
HTTP: &networking.HTTPIngressRuleValue{
|
|
||||||
Paths: []networking.HTTPIngressPath{
|
|
||||||
{
|
|
||||||
Path: "/foo",
|
|
||||||
PathType: &implementationPathType,
|
|
||||||
Backend: networking.IngressBackend{
|
|
||||||
Resource: nil,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
expectResourceBackend: false,
|
|
||||||
},
|
|
||||||
"nil spec.Backend, one rule with non-nil HTTP, one path with non-nil Backend.Resource": {
|
|
||||||
tweakIngress: func(ing *networking.Ingress) {
|
|
||||||
ing.Spec.Backend = nil
|
|
||||||
ing.Spec.Rules[0].IngressRuleValue = networking.IngressRuleValue{
|
|
||||||
HTTP: &networking.HTTPIngressRuleValue{
|
|
||||||
Paths: []networking.HTTPIngressPath{
|
|
||||||
{
|
|
||||||
Path: "/foo",
|
|
||||||
PathType: &implementationPathType,
|
|
||||||
Backend: networking.IngressBackend{
|
|
||||||
Resource: resourceBackend,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
expectResourceBackend: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for name, testCase := range testCases {
|
|
||||||
t.Run(name, func(t *testing.T) {
|
|
||||||
ingress := baseIngress.DeepCopy()
|
|
||||||
testCase.tweakIngress(ingress)
|
|
||||||
gv := testCase.groupVersion
|
|
||||||
if gv == nil {
|
|
||||||
gv = &networkingv1.SchemeGroupVersion
|
|
||||||
}
|
|
||||||
isBackendAllowed := resourceBackendPresent(ingress)
|
|
||||||
if isBackendAllowed != testCase.expectResourceBackend {
|
|
||||||
t.Errorf("Expected resourceBackendPresent to return: %v, got: %v", testCase.expectResourceBackend, isBackendAllowed)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user