Change:
An ingress resource with both annotation and set cannot be created. Ingress resources can be updated to include both the annotation and the without issue. Kubernetes response: The ingress should be deployed with both annotation and set, as it is supported by updating an existing ingress. Apply this resource: The code causing this issue is here: <details</details<details</details<detailsLinux, Mac, mulitple OSs with the same issue. It's caused by code as linked above </details<details</details<details</details<details</details
/sig network
that code referenced is only used on Create update has a different path is this based on an observation of the code or are you hitting this problem?
, correct. This only happens on create. Our work around now is to create an ingress resource with the annotation, and then update the resource, adding the . This involves 2 MRs and approval processes We are hitting this problem regularly as we scale out the number of kubernetes clusters we operate, and create new ingress resources. It's quite painful as we're starting to use , but cannot drop the ingressClass annotation yet as some third party services have not ported over to use the .
but why do you create it with the annotaiton?
Sorry, I don't understand your question. I need to be able to create an ingress resource with both the ingressClass annotation () and both set
yeah, that is my question, if you are creating the ingress with v1 you don't need the annotation, it was deprecated by the field, the annotation has to be there for the people that upgrades from v1beta1 to v1
As far as I know, External DNS still requires the annotation. We use external DNS, and thus cannot drop the annotation yet
I think what you're doing as a workaround is a valid approach . A better fix would be for the ingress controller you're using to migrate to properly use the v1 API for Ingress and IngressClass. Please consider filing a bug against that ingress controller or other component. We could also return a header when someone sets the annotation on an Ingress that already has set, to make it clear that this is not recommended.
It seems that PR got stuck , but is not a kubernets bug
IMO we should probably not hard-fail if these are both set, but a warning would be appropriate.
, i'd completely agree. Kubernetes is happy to have both set side by side, but the logic linked in the first comment blocks it. Seemingly needlessly.
Discussed at sig-net. We don't object to loosening this rule - an API warning seems sufficient. PRs welcome /triage accepted
Hi , I'm willing to help with this issue. I'm not familiar with , I read the relevant code and I think it seems that to add an API warning, I just need to implement for in . Am I right? And in the same time, don't check these two fields in validation?
Pretty much! See how Service works (though you probably don't need to put it into a different package, not sure why we did that..) kidddddddddddddddddddddd <
/assign

Discussion:
} allErrs = append(allErrs, validateIngress(ingress, opts)...) annotationVal, annotationIsSet := ingress.Annotations[annotationIngressClass] <del> if annotationIsSet && ingress.Spec.IngressClassName != nil { </del> <ins> if annotationIsSet && ingress.Spec.IngressClassName != nil && annotationVal != *ingress.Spec.IngressClassName { </ins> annotationPath := field.NewPath("annotations").Child(annotationIngressClass) <del> allErrs = append(allErrs, field.Invalid(annotationPath, annotationVal, "can not be set when the class field is also set")) </del> <ins> allErrs = append(allErrs, field.Invalid(annotationPath, annotationVal, "must match `ingressClassName` when both are specified")) </ins> } return allErrs }

}, expectedErrs: field.ErrorList{}, }, <del> "class field and annotation set": { </del> <ins> "class field and annotation set with same value": { tweakIngress: func(ingress *networking.Ingress) { ingress.Spec.IngressClassName = utilpointer.String("foo") ingress.Annotations = map[string]string{annotationIngressClass: "foo"} }, expectedErrs: field.ErrorList{}, }, "class field and annotation set with different value": { </ins> tweakIngress: func(ingress *networking.Ingress) { ingress.Spec.IngressClassName = utilpointer.String("bar") ingress.Annotations = map[string]string{annotationIngressClass: "foo"} }, <del> expectedErrs: field.ErrorList{field.Invalid(field.NewPath("annotations").Child(annotationIngressClass), "foo", "can not be set when the class field is also set")}, </del> <ins> expectedErrs: field.ErrorList{field.Invalid(field.NewPath("annotations").Child(annotationIngressClass), "foo", "must match `ingressClassName` when both are specified")}, </ins> }, "valid regex path": { tweakIngress: func(ingress *networking.Ingress) {

import ( "context" <ins> "fmt" </ins> apiequality "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/runtime"

"sigs.k8s.io/structured-merge-diff/v4/fieldpath" ) <ins> const ( annotationIngressClass = "kubernetes.io/ingress.class" ) </ins> // ingressStrategy implements verification logic for Replication Ingress. type ingressStrategy struct { runtime.ObjectTyper

} // WarningsOnCreate returns warnings for the creation of the given object. <del> func (ingressStrategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string { return nil } </del> <ins> func (ingressStrategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string { var warnings []string ingress := obj.(*networking.Ingress) _, annotationIsSet := ingress.Annotations[annotationIngressClass] if annotationIsSet && ingress.Spec.IngressClassName == nil { warnings = append(warnings, fmt.Sprintf("annotation %q is deprecated, please use 'spec.ingressClassName' instead", annotationIngressClass)) } return warnings } </ins> // Canonicalize normalizes the object after validation. func (ingressStrategy) Canonicalize(obj runtime.Object) {