diff --git a/internal/BUILD.bazel b/internal/BUILD.bazel index 581a8086b..7237b60f9 100644 --- a/internal/BUILD.bazel +++ b/internal/BUILD.bazel @@ -20,7 +20,6 @@ filegroup( "//internal/controller/feature:all-srcs", "//internal/controller/issuers:all-srcs", "//internal/controller/orders:all-srcs", - "//internal/ingress:all-srcs", "//internal/plugin:all-srcs", "//internal/test/paths:all-srcs", "//internal/vault:all-srcs", diff --git a/internal/ingress/BUILD.bazel b/internal/ingress/BUILD.bazel deleted file mode 100644 index 2d9dbdb2f..000000000 --- a/internal/ingress/BUILD.bazel +++ /dev/null @@ -1,66 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = [ - "convert.go", - "ingress.go", - "v1.go", - "v1beta1.go", - ], - importpath = "github.com/cert-manager/cert-manager/internal/ingress", - visibility = ["//visibility:public"], - deps = [ - "//pkg/controller:go_default_library", - "@io_k8s_api//core/v1:go_default_library", - "@io_k8s_api//networking/v1:go_default_library", - "@io_k8s_api//networking/v1beta1:go_default_library", - "@io_k8s_apimachinery//pkg/apis/meta/v1:go_default_library", - "@io_k8s_apimachinery//pkg/conversion:go_default_library", - "@io_k8s_apimachinery//pkg/labels:go_default_library", - "@io_k8s_apimachinery//pkg/util/intstr:go_default_library", - "@io_k8s_client_go//discovery:go_default_library", - "@io_k8s_client_go//kubernetes:go_default_library", - "@io_k8s_client_go//listers/networking/v1:go_default_library", - "@io_k8s_client_go//listers/networking/v1beta1:go_default_library", - "@io_k8s_client_go//tools/cache:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = [ - "convert_test.go", - "ingress_test.go", - ], - embed = [":go_default_library"], - deps = [ - "//pkg/controller:go_default_library", - "//test/unit/discovery:go_default_library", - "@com_github_google_gofuzz//:go_default_library", - "@com_github_stretchr_testify//assert:go_default_library", - "@io_k8s_api//networking/v1:go_default_library", - "@io_k8s_api//networking/v1beta1:go_default_library", - "@io_k8s_apimachinery//pkg/apis/meta/v1:go_default_library", - "@io_k8s_apimachinery//pkg/labels:go_default_library", - "@io_k8s_apimachinery//pkg/runtime/schema:go_default_library", - "@io_k8s_apimachinery//pkg/util/intstr:go_default_library", - "@io_k8s_client_go//informers:go_default_library", - "@io_k8s_client_go//kubernetes/fake:go_default_library", - "@io_k8s_utils//pointer:go_default_library", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], - visibility = ["//visibility:public"], -) diff --git a/internal/ingress/convert.go b/internal/ingress/convert.go deleted file mode 100644 index de175b632..000000000 --- a/internal/ingress/convert.go +++ /dev/null @@ -1,372 +0,0 @@ -/* -Copyright 2021 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package ingress - -import ( - "unsafe" - - corev1 "k8s.io/api/core/v1" - networkingv1 "k8s.io/api/networking/v1" - networkingv1beta1 "k8s.io/api/networking/v1beta1" - "k8s.io/apimachinery/pkg/conversion" - "k8s.io/apimachinery/pkg/util/intstr" -) - -/* -This file contains copies of functions from k8s.io/kubernetes, -as we definitely don't want to import the entire of k8s. The code -is released under the following LICENSE: -*/ - -/* -Copyright The Kubernetes Authors. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Convert_networking_Ingress_To_v1beta1_Ingress uses unsafe pointer manipulation to manipulate a -// *networkingv1beta1.Ingress into pointing at the same underlying data as the input *networkingv1.Ingress. -// Both the `in` and `out` Object's data will be manipulated by this function. -// -// Recommended usage: -// // as in and out will point to the same data, make sure any manipulation doesn't affect the original Ingress -// in := myIngress.DeepCopy() -// out := new(networkingv1beta1.Ingress) -// err := Convert_networking_Ingress_To_v1beta1_Ingress(in, out, nil) -func Convert_networking_Ingress_To_v1beta1_Ingress(in *networkingv1.Ingress, out *networkingv1beta1.Ingress, s conversion.Scope) error { - err := autoConvert_networking_Ingress_To_v1beta1_Ingress(in, out, s) - if err != nil { - return err - } - // v1beta1 Ingresses should not have IngressClassName set but instead use the deprecated annotation. - // Move the ingress class to the annotations and then zero the IngressClassName field - if out.Spec.IngressClassName != nil { - if out.Annotations == nil { - out.Annotations = make(map[string]string) - } - out.Annotations["kubernetes.io/ingress.class"] = *out.Spec.IngressClassName - out.Spec.IngressClassName = nil - } - return nil -} - -func autoConvert_networking_Ingress_To_v1beta1_Ingress(in *networkingv1.Ingress, out *networkingv1beta1.Ingress, s conversion.Scope) error { - out.ObjectMeta = in.ObjectMeta - if err := Convert_networking_IngressSpec_To_v1beta1_IngressSpec(&in.Spec, &out.Spec, s); err != nil { - return err - } - if err := Convert_networking_IngressStatus_To_v1beta1_IngressStatus(&in.Status, &out.Status, s); err != nil { - return err - } - return nil -} - -func Convert_networking_IngressSpec_To_v1beta1_IngressSpec(in *networkingv1.IngressSpec, out *networkingv1beta1.IngressSpec, s conversion.Scope) error { - if err := autoConvert_networking_IngressSpec_To_v1beta1_IngressSpec(in, out, s); err != nil { - return nil - } - if in.DefaultBackend != nil { - out.Backend = &networkingv1beta1.IngressBackend{} - if err := Convert_networking_IngressBackend_To_v1beta1_IngressBackend(in.DefaultBackend, out.Backend, s); err != nil { - return err - } - } - return nil -} - -func autoConvert_networking_IngressSpec_To_v1beta1_IngressSpec(in *networkingv1.IngressSpec, out *networkingv1beta1.IngressSpec, s conversion.Scope) error { - out.IngressClassName = (*string)(unsafe.Pointer(in.IngressClassName)) - // WARNING: in.DefaultBackend requires manual conversion: does not exist in peer-type - out.TLS = *(*[]networkingv1beta1.IngressTLS)(unsafe.Pointer(&in.TLS)) - if in.Rules != nil { - in, out := &in.Rules, &out.Rules - *out = make([]networkingv1beta1.IngressRule, len(*in)) - for i := range *in { - if err := Convert_networking_IngressRule_To_v1beta1_IngressRule(&(*in)[i], &(*out)[i], s); err != nil { - return err - } - } - } else { - out.Rules = nil - } - return nil -} - -func Convert_networking_IngressStatus_To_v1beta1_IngressStatus(in *networkingv1.IngressStatus, out *networkingv1beta1.IngressStatus, s conversion.Scope) error { - return autoConvert_networking_IngressStatus_To_v1beta1_IngressStatus(in, out, s) -} - -func autoConvert_networking_IngressStatus_To_v1beta1_IngressStatus(in *networkingv1.IngressStatus, out *networkingv1beta1.IngressStatus, s conversion.Scope) error { - if err := Convert_core_LoadBalancerStatus_To_v1_LoadBalancerStatus(&in.LoadBalancer, &out.LoadBalancer, s); err != nil { - return err - } - return nil -} - -func Convert_core_LoadBalancerStatus_To_v1_LoadBalancerStatus(in *corev1.LoadBalancerStatus, out *corev1.LoadBalancerStatus, s conversion.Scope) error { - return autoConvert_core_LoadBalancerStatus_To_v1_LoadBalancerStatus(in, out, s) -} - -func autoConvert_core_LoadBalancerStatus_To_v1_LoadBalancerStatus(in *corev1.LoadBalancerStatus, out *corev1.LoadBalancerStatus, s conversion.Scope) error { - out.Ingress = *(*[]corev1.LoadBalancerIngress)(unsafe.Pointer(&in.Ingress)) - return nil -} - -func Convert_networking_IngressRule_To_v1beta1_IngressRule(in *networkingv1.IngressRule, out *networkingv1beta1.IngressRule, s conversion.Scope) error { - return autoConvert_networking_IngressRule_To_v1beta1_IngressRule(in, out, s) -} - -func autoConvert_networking_IngressRule_To_v1beta1_IngressRule(in *networkingv1.IngressRule, out *networkingv1beta1.IngressRule, s conversion.Scope) error { - out.Host = in.Host - if err := Convert_networking_IngressRuleValue_To_v1beta1_IngressRuleValue(&in.IngressRuleValue, &out.IngressRuleValue, s); err != nil { - return err - } - return nil -} - -func Convert_networking_IngressRuleValue_To_v1beta1_IngressRuleValue(in *networkingv1.IngressRuleValue, out *networkingv1beta1.IngressRuleValue, s conversion.Scope) error { - return autoConvert_networking_IngressRuleValue_To_v1beta1_IngressRuleValue(in, out, s) -} - -func autoConvert_networking_IngressRuleValue_To_v1beta1_IngressRuleValue(in *networkingv1.IngressRuleValue, out *networkingv1beta1.IngressRuleValue, s conversion.Scope) error { - if in.HTTP != nil { - in, out := &in.HTTP, &out.HTTP - *out = new(networkingv1beta1.HTTPIngressRuleValue) - if err := Convert_networking_HTTPIngressRuleValue_To_v1beta1_HTTPIngressRuleValue(*in, *out, s); err != nil { - return err - } - } else { - out.HTTP = nil - } - return nil -} - -func Convert_networking_HTTPIngressRuleValue_To_v1beta1_HTTPIngressRuleValue(in *networkingv1.HTTPIngressRuleValue, out *networkingv1beta1.HTTPIngressRuleValue, s conversion.Scope) error { - return autoConvert_networking_HTTPIngressRuleValue_To_v1beta1_HTTPIngressRuleValue(in, out, s) -} - -func autoConvert_networking_HTTPIngressRuleValue_To_v1beta1_HTTPIngressRuleValue(in *networkingv1.HTTPIngressRuleValue, out *networkingv1beta1.HTTPIngressRuleValue, s conversion.Scope) error { - if in.Paths != nil { - in, out := &in.Paths, &out.Paths - *out = make([]networkingv1beta1.HTTPIngressPath, len(*in)) - for i := range *in { - if err := Convert_networking_HTTPIngressPath_To_v1beta1_HTTPIngressPath(&(*in)[i], &(*out)[i], s); err != nil { - return err - } - } - } else { - out.Paths = nil - } - return nil -} - -func Convert_networking_HTTPIngressPath_To_v1beta1_HTTPIngressPath(in *networkingv1.HTTPIngressPath, out *networkingv1beta1.HTTPIngressPath, s conversion.Scope) error { - return autoConvert_networking_HTTPIngressPath_To_v1beta1_HTTPIngressPath(in, out, s) -} - -func autoConvert_networking_HTTPIngressPath_To_v1beta1_HTTPIngressPath(in *networkingv1.HTTPIngressPath, out *networkingv1beta1.HTTPIngressPath, s conversion.Scope) error { - out.Path = in.Path - out.PathType = (*networkingv1beta1.PathType)(unsafe.Pointer(in.PathType)) - if err := Convert_networking_IngressBackend_To_v1beta1_IngressBackend(&in.Backend, &out.Backend, s); err != nil { - return err - } - return nil -} - -func Convert_networking_IngressBackend_To_v1beta1_IngressBackend(in *networkingv1.IngressBackend, out *networkingv1beta1.IngressBackend, s conversion.Scope) error { - if err := autoConvert_networking_IngressBackend_To_v1beta1_IngressBackend(in, out, s); err != nil { - return err - } - if in.Service != nil { - out.ServiceName = in.Service.Name - if len(in.Service.Port.Name) > 0 { - out.ServicePort = intstr.FromString(in.Service.Port.Name) - } else { - out.ServicePort = intstr.FromInt(int(in.Service.Port.Number)) - } - } - return nil -} - -func autoConvert_networking_IngressBackend_To_v1beta1_IngressBackend(in *networkingv1.IngressBackend, out *networkingv1beta1.IngressBackend, s conversion.Scope) error { - // WARNING: in.Service requires manual conversion: does not exist in peer-type - out.Resource = (*corev1.TypedLocalObjectReference)(unsafe.Pointer(in.Resource)) - return nil -} - -// Convert_v1beta1_Ingress_To_networking_Ingress uses unsafe pointer manipulation to manipulate a -// *networkingv1.Ingress into pointing at the same underlying data as the input *networkingv1beta1.Ingress. -// Both the `in` and `out` Object's data will be manipulated by this function. -// -// Recommended usage: -// // as in and out will point to the same data, make sure any manipulation doesn't affect the original Ingress -// in := myIngress.DeepCopy() -// out := new(networkingv1.Ingress) -// err := Convert_v1beta1_Ingress_To_networking_Ingress(in, out, nil) -func Convert_v1beta1_Ingress_To_networking_Ingress(in *networkingv1beta1.Ingress, out *networkingv1.Ingress, s conversion.Scope) error { - return autoConvert_v1beta1_Ingress_To_networking_Ingress(in, out, s) -} - -func autoConvert_v1beta1_Ingress_To_networking_Ingress(in *networkingv1beta1.Ingress, out *networkingv1.Ingress, s conversion.Scope) error { - out.ObjectMeta = in.ObjectMeta - if err := Convert_v1beta1_IngressSpec_To_networking_IngressSpec(&in.Spec, &out.Spec, s); err != nil { - return err - } - if err := Convert_v1beta1_IngressStatus_To_networking_IngressStatus(&in.Status, &out.Status, s); err != nil { - return err - } - return nil -} - -func Convert_v1beta1_IngressSpec_To_networking_IngressSpec(in *networkingv1beta1.IngressSpec, out *networkingv1.IngressSpec, s conversion.Scope) error { - if err := autoConvert_v1beta1_IngressSpec_To_networking_IngressSpec(in, out, s); err != nil { - return nil - } - if in.Backend != nil { - out.DefaultBackend = &networkingv1.IngressBackend{} - if err := Convert_v1beta1_IngressBackend_To_networking_IngressBackend(in.Backend, out.DefaultBackend, s); err != nil { - return err - } - } - return nil -} - -func autoConvert_v1beta1_IngressSpec_To_networking_IngressSpec(in *networkingv1beta1.IngressSpec, out *networkingv1.IngressSpec, s conversion.Scope) error { - out.IngressClassName = (*string)(unsafe.Pointer(in.IngressClassName)) - // WARNING: in.Backend requires manual conversion: does not exist in peer-type - out.TLS = *(*[]networkingv1.IngressTLS)(unsafe.Pointer(&in.TLS)) - if in.Rules != nil { - in, out := &in.Rules, &out.Rules - *out = make([]networkingv1.IngressRule, len(*in)) - for i := range *in { - if err := Convert_v1beta1_IngressRule_To_networking_IngressRule(&(*in)[i], &(*out)[i], s); err != nil { - return err - } - } - } else { - out.Rules = nil - } - return nil -} - -func Convert_v1beta1_IngressStatus_To_networking_IngressStatus(in *networkingv1beta1.IngressStatus, out *networkingv1.IngressStatus, s conversion.Scope) error { - return autoConvert_v1beta1_IngressStatus_To_networking_IngressStatus(in, out, s) -} - -func autoConvert_v1beta1_IngressStatus_To_networking_IngressStatus(in *networkingv1beta1.IngressStatus, out *networkingv1.IngressStatus, s conversion.Scope) error { - if err := Convert_v1_LoadBalancerStatus_To_core_LoadBalancerStatus(&in.LoadBalancer, &out.LoadBalancer, s); err != nil { - return err - } - return nil -} - -func Convert_v1_LoadBalancerStatus_To_core_LoadBalancerStatus(in *corev1.LoadBalancerStatus, out *corev1.LoadBalancerStatus, s conversion.Scope) error { - return autoConvert_v1_LoadBalancerStatus_To_core_LoadBalancerStatus(in, out, s) -} - -func autoConvert_v1_LoadBalancerStatus_To_core_LoadBalancerStatus(in *corev1.LoadBalancerStatus, out *corev1.LoadBalancerStatus, s conversion.Scope) error { - out.Ingress = *(*[]corev1.LoadBalancerIngress)(unsafe.Pointer(&in.Ingress)) - return nil -} - -func Convert_v1beta1_IngressRule_To_networking_IngressRule(in *networkingv1beta1.IngressRule, out *networkingv1.IngressRule, s conversion.Scope) error { - return autoConvert_v1beta1_IngressRule_To_networking_IngressRule(in, out, s) -} - -func autoConvert_v1beta1_IngressRule_To_networking_IngressRule(in *networkingv1beta1.IngressRule, out *networkingv1.IngressRule, s conversion.Scope) error { - out.Host = in.Host - if err := Convert_v1beta1_IngressRuleValue_To_networking_IngressRuleValue(&in.IngressRuleValue, &out.IngressRuleValue, s); err != nil { - return err - } - return nil -} - -func Convert_v1beta1_IngressRuleValue_To_networking_IngressRuleValue(in *networkingv1beta1.IngressRuleValue, out *networkingv1.IngressRuleValue, s conversion.Scope) error { - return autoConvert_v1beta1_IngressRuleValue_To_networking_IngressRuleValue(in, out, s) -} - -func autoConvert_v1beta1_IngressRuleValue_To_networking_IngressRuleValue(in *networkingv1beta1.IngressRuleValue, out *networkingv1.IngressRuleValue, s conversion.Scope) error { - if in.HTTP != nil { - in, out := &in.HTTP, &out.HTTP - *out = new(networkingv1.HTTPIngressRuleValue) - if err := Convert_v1beta1_HTTPIngressRuleValue_To_networking_HTTPIngressRuleValue(*in, *out, s); err != nil { - return err - } - } else { - out.HTTP = nil - } - return nil -} - -func Convert_v1beta1_HTTPIngressRuleValue_To_networking_HTTPIngressRuleValue(in *networkingv1beta1.HTTPIngressRuleValue, out *networkingv1.HTTPIngressRuleValue, s conversion.Scope) error { - return autoConvert_v1beta1_HTTPIngressRuleValue_To_networking_HTTPIngressRuleValue(in, out, s) -} - -func autoConvert_v1beta1_HTTPIngressRuleValue_To_networking_HTTPIngressRuleValue(in *networkingv1beta1.HTTPIngressRuleValue, out *networkingv1.HTTPIngressRuleValue, s conversion.Scope) error { - if in.Paths != nil { - in, out := &in.Paths, &out.Paths - *out = make([]networkingv1.HTTPIngressPath, len(*in)) - for i := range *in { - if err := Convert_v1beta1_HTTPIngressPath_To_networking_HTTPIngressPath(&(*in)[i], &(*out)[i], s); err != nil { - return err - } - } - } else { - out.Paths = nil - } - return nil -} - -func Convert_v1beta1_HTTPIngressPath_To_networking_HTTPIngressPath(in *networkingv1beta1.HTTPIngressPath, out *networkingv1.HTTPIngressPath, s conversion.Scope) error { - return autoConvert_v1beta1_HTTPIngressPath_To_networking_HTTPIngressPath(in, out, s) -} - -func autoConvert_v1beta1_HTTPIngressPath_To_networking_HTTPIngressPath(in *networkingv1beta1.HTTPIngressPath, out *networkingv1.HTTPIngressPath, s conversion.Scope) error { - out.Path = in.Path - out.PathType = (*networkingv1.PathType)(unsafe.Pointer(in.PathType)) - if err := Convert_v1beta1_IngressBackend_To_networking_IngressBackend(&in.Backend, &out.Backend, s); err != nil { - return err - } - return nil -} - -func Convert_v1beta1_IngressBackend_To_networking_IngressBackend(in *networkingv1beta1.IngressBackend, out *networkingv1.IngressBackend, s conversion.Scope) error { - if err := autoConvert_v1beta1_IngressBackend_To_networking_IngressBackend(in, out, s); err != nil { - return err - } - if len(in.ServiceName) > 0 || in.ServicePort.IntVal != 0 || in.ServicePort.StrVal != "" || in.ServicePort.Type == intstr.String { - out.Service = &networkingv1.IngressServiceBackend{} - out.Service.Name = in.ServiceName - out.Service.Port.Name = in.ServicePort.StrVal - out.Service.Port.Number = in.ServicePort.IntVal - } - return nil -} - -func autoConvert_v1beta1_IngressBackend_To_networking_IngressBackend(in *networkingv1beta1.IngressBackend, out *networkingv1.IngressBackend, s conversion.Scope) error { - // WARNING: in.ServiceName requires manual conversion: does not exist in peer-type - // WARNING: in.ServicePort requires manual conversion: does not exist in peer-type - out.Resource = (*corev1.TypedLocalObjectReference)(unsafe.Pointer(in.Resource)) - return nil -} diff --git a/internal/ingress/convert_test.go b/internal/ingress/convert_test.go deleted file mode 100644 index 48490aaaf..000000000 --- a/internal/ingress/convert_test.go +++ /dev/null @@ -1,261 +0,0 @@ -/* -Copyright 2021 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package ingress - -import ( - "regexp" - "testing" - - fuzz "github.com/google/gofuzz" - "github.com/stretchr/testify/assert" - networkingv1 "k8s.io/api/networking/v1" - networkingv1beta1 "k8s.io/api/networking/v1beta1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/intstr" - "k8s.io/utils/pointer" -) - -var v1TestIngress = &networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-networkingv1-ingress", - Namespace: "test-networkingv1-namespace", - Annotations: map[string]string{ - "test.key": "test.value", - "kubernetes.io/ingress.class": "bogus-ingress-class", - }, - Labels: map[string]string{ - "labelkey": "labelvalue", - }, - }, - Spec: networkingv1.IngressSpec{ - // As discussed in https://github.com/cert-manager/cert-manager/issues/4537 - // the IngressClassName field is not directly equivalent to the - // kubernetes.io/ingress.class annotation. According to the Ingress graduation KEP: - // https://github.com/kubernetes/enhancements/blob/master/keps/sig-network/758-ingress-api-group/README.md - // the annotation, if present, overrides this field. - // - // As the goal of cert-manager is to be as widely compatible as possible, we can only use the - // annotation to describe an ingress class. - IngressClassName: nil, - DefaultBackend: &networkingv1.IngressBackend{ - Service: &networkingv1.IngressServiceBackend{ - Name: "default-backend-svc", - Port: networkingv1.ServiceBackendPort{ - Number: 1234, - }, - }, - }, - TLS: []networkingv1.IngressTLS{ - { - Hosts: []string{"aaa.", "bbb.", "ccc.ddd"}, - SecretName: "test-secret-1", - }, - { - Hosts: []string{"eee"}, - SecretName: "test-secret-2", - }, - }, - Rules: []networkingv1.IngressRule{ - { - Host: "aaa", - IngressRuleValue: networkingv1.IngressRuleValue{ - HTTP: &networkingv1.HTTPIngressRuleValue{ - Paths: []networkingv1.HTTPIngressPath{ - { - Path: "/.well-known/acme-challenge", - PathType: func() *networkingv1.PathType { p := networkingv1.PathTypeImplementationSpecific; return &p }(), - Backend: networkingv1.IngressBackend{ - Service: &networkingv1.IngressServiceBackend{ - Name: "test-solver-backend", - Port: networkingv1.ServiceBackendPort{Number: 80}, - }, - }, - }, - }, - }, - }, - }, - }, - }, -} - -var v1beta1TestIngress = &networkingv1beta1.Ingress{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-networkingv1-ingress", - Namespace: "test-networkingv1-namespace", - Annotations: map[string]string{ - "test.key": "test.value", - "kubernetes.io/ingress.class": "bogus-ingress-class", - }, - Labels: map[string]string{ - "labelkey": "labelvalue", - }, - }, - Spec: networkingv1beta1.IngressSpec{ - Backend: &networkingv1beta1.IngressBackend{ - ServiceName: "default-backend-svc", - ServicePort: intstr.IntOrString{ - Type: intstr.Int, - IntVal: 1234, - }, - }, - Rules: []networkingv1beta1.IngressRule{ - { - Host: "aaa", - IngressRuleValue: networkingv1beta1.IngressRuleValue{ - HTTP: &networkingv1beta1.HTTPIngressRuleValue{ - Paths: []networkingv1beta1.HTTPIngressPath{ - { - Path: "/.well-known/acme-challenge", - PathType: func() *networkingv1beta1.PathType { p := networkingv1beta1.PathTypeImplementationSpecific; return &p }(), - Backend: networkingv1beta1.IngressBackend{ - ServiceName: "test-solver-backend", - ServicePort: intstr.IntOrString{ - Type: intstr.Int, - IntVal: 80, - }, - }, - }, - }, - }, - }, - }, - }, - TLS: []networkingv1beta1.IngressTLS{ - { - Hosts: []string{"aaa.", "bbb.", "ccc.ddd"}, - SecretName: "test-secret-1", - }, - { - Hosts: []string{"eee"}, - SecretName: "test-secret-2", - }, - }, - }, - Status: networkingv1beta1.IngressStatus{}, -} - -func TestConvert_networking_Ingress_To_v1beta1_Ingress(t *testing.T) { - tests := map[string]func(t *testing.T){ - "convert networkingv1 Ingresss to networkingv1beta1 Ingress": func(t *testing.T) { - in := v1TestIngress.DeepCopy() - out := new(networkingv1beta1.Ingress) - err := Convert_networking_Ingress_To_v1beta1_Ingress(in, out, nil) - assert.NoError(t, err, "conversion should not fail") - expected := v1beta1TestIngress.DeepCopy() - assert.Equal(t, expected, out, "conversion was not as expected") - }, - "mutation side effects": func(t *testing.T) { - in := v1TestIngress.DeepCopy() - out := &networkingv1beta1.Ingress{} - err := Convert_networking_Ingress_To_v1beta1_Ingress(in, out, nil) - assert.NoError(t, err, "conversion should not fail") - expected := v1beta1TestIngress.DeepCopy() - assert.Equal(t, expected, out, "conversion was not as expected") - // as the convert functions use unsafe.Pointer to make out point to the same - // underlying data as in, in should end up mutated. This test ensures if - // a future maintainer touches this code they understand the side effects - assert.Equal(t, in.Annotations, out.Annotations, "conversion did not have expected side effects: annotations differ") - }, - "ingress without annotations ends up with annotations": func(t *testing.T) { - in := &networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{ - Name: "name", - Namespace: "namespaces", - }, - Spec: networkingv1.IngressSpec{ - IngressClassName: pointer.String("some-class"), - }, - } - out := new(networkingv1beta1.Ingress) - err := Convert_networking_Ingress_To_v1beta1_Ingress(in, out, nil) - assert.NoError(t, err, "conversion should not fail") - expected := &networkingv1beta1.Ingress{ - ObjectMeta: metav1.ObjectMeta{ - Name: "name", - Namespace: "namespaces", - Annotations: map[string]string{ - "kubernetes.io/ingress.class": "some-class", - }, - }, - } - assert.Equal(t, expected, out, "conversion was not as expected") - }, - "v1 -> v1beta1 -> v1 round trip preserves fields": func(t *testing.T) { - // Something mentioned in a previous code review is we should make sure we do not - // remove fields during conversion. There may be a better way of doing this, but this - // test will fill every field with a fuzzer and perform a conversion round trip. - - base := new(networkingv1.Ingress) - f := fuzz.New(). - // Filling both the port name and port number is invalid so skip the number for now - // (the fuzzer will put some negative ports in as well). - SkipFieldsWithPattern(regexp.MustCompile("Number")). - // The IngressClassNameLogic is tested below - SkipFieldsWithPattern(regexp.MustCompile("IngressClassName")) - f.Fuzz(base) - - in := base.DeepCopy() - expected := in.DeepCopy() - intermediate := new(networkingv1beta1.Ingress) - out := new(networkingv1.Ingress) - - err := Convert_networking_Ingress_To_v1beta1_Ingress(in, intermediate, nil) - assert.NoError(t, err, "conversion from v1 to v1beta1 should not fail") - err = Convert_v1beta1_Ingress_To_networking_Ingress(intermediate.DeepCopy(), out, nil) - assert.NoError(t, err, "conversion from v1beta1 to v1 should not fail") - assert.Equal(t, expected.Spec, out.Spec, "output Spec was not equal to input Spec after round trip") - }, - } - for name, test := range tests { - t.Run(name, test) - } -} - -func TestConvert_v1beta1_Ingress_To_networking_Ingress(t *testing.T) { - tests := map[string]func(t *testing.T){ - "convert networkingv1beta1 Ingresss to networkingv1 Ingress": func(t *testing.T) { - in := v1beta1TestIngress.DeepCopy() - out := new(networkingv1.Ingress) - err := Convert_v1beta1_Ingress_To_networking_Ingress(in, out, nil) - assert.NoError(t, err, "conversion should not fail") - expected := v1TestIngress.DeepCopy() - assert.Equal(t, expected, out, "conversion was not as expected") - }, - "conversion with no ingress class annotation works": func(t *testing.T) { - in := v1beta1TestIngress.DeepCopy() - out := new(networkingv1.Ingress) - delete(in.Annotations, "kubernetes.io/ingress.class") - err := Convert_v1beta1_Ingress_To_networking_Ingress(in, out, nil) - assert.NoError(t, err, "conversion should not fail") - assert.Nil(t, out.Spec.IngressClassName, "ingress class should not be set on output") - }, - "mutation side effects": func(t *testing.T) { - // as the convert functions use unsafe.Pointer to make out point to the same - // underlying data as in, in should end up mutated. This test ensures if - // a future maintainer touches this code they understand the side effects - in := v1beta1TestIngress.DeepCopy() - out := new(networkingv1.Ingress) - err := Convert_v1beta1_Ingress_To_networking_Ingress(in, out, nil) - assert.NoError(t, err, "conversion should not fail") - assert.Equal(t, in.Annotations, out.Annotations, "conversion did not have expected side effects: annotations differ") - }, - } - for name, test := range tests { - t.Run(name, test) - } -} diff --git a/internal/ingress/ingress.go b/internal/ingress/ingress.go deleted file mode 100644 index c193805bd..000000000 --- a/internal/ingress/ingress.go +++ /dev/null @@ -1,157 +0,0 @@ -/* -Copyright 2021 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Package ingress lets us use an internal type for supporting multiple kinds of ingresses. -// -// This package's sole reason for existence is for compatibility with Kubernetes API servers -// below v1.18. However, our client-go library is already beyond the supported version skew -// (https://kubernetes.io/releases/version-skew-policy/) so it is not guaranteed to continue -// working in the future, and will definitely be removed once cert-manager no longer supports -// Kubernetes 1.17. -package ingress - -import ( - "context" - "fmt" - "sync" - "sync/atomic" - - networkingv1 "k8s.io/api/networking/v1" - networkingv1beta1 "k8s.io/api/networking/v1beta1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/discovery" - "k8s.io/client-go/tools/cache" - - "github.com/cert-manager/cert-manager/pkg/controller" -) - -// keep an internal cache of known API types so calls to the discovery API are kept to a minimum -// https://pkg.go.dev/sync/atomic#example-Value-ReadMostly -var ( - knownAPIVersionCache atomic.Value - cacheLock sync.Mutex -) - -// InternalIngressCreateUpdater mimics a client-go networking/v1 or -// networking/v1beta1 Interface. -type InternalIngressCreateUpdater interface { - Ingresses(namespace string) InternalIngressInterface -} - -// InternalIngressInterface mimics a client-go networking/v1/IngressInterface -// It always returns a *networkingv1.Ingress, so when implementing this you must convert any type of -// Ingress into a v1.Ingress. -type InternalIngressInterface interface { - Create(ctx context.Context, ingress *networkingv1.Ingress, opts metav1.CreateOptions) (*networkingv1.Ingress, error) - Update(ctx context.Context, ingress *networkingv1.Ingress, opts metav1.UpdateOptions) (*networkingv1.Ingress, error) - Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error - Get(ctx context.Context, name string, opts metav1.GetOptions) (*networkingv1.Ingress, error) -} - -// InternalIngressLister mimics a client-go networking/v1/IngressLister. -type InternalIngressLister interface { - List(selector labels.Selector) (ret []*networkingv1.Ingress, err error) - Ingresses(namespace string) InternalIngressNamespaceLister -} - -// InternalIngressNamespaceLister mimics a client-go networking/v1/IngressNamespaceLister -type InternalIngressNamespaceLister interface { - List(selector labels.Selector) (ret []*networkingv1.Ingress, err error) - Get(name string) (*networkingv1.Ingress, error) -} - -// NewListerInformer returns an InternalIngressLister configured for v1 or v1beta1 ingresses depending on the -// API Versions available in the discovery client. -func NewListerInformer(ctx *controller.Context) (InternalIngressLister, cache.SharedIndexInformer, error) { - switch { - case hasVersion(ctx.DiscoveryClient, networkingv1.SchemeGroupVersion.String()): - return &v1Lister{ - lister: ctx.KubeSharedInformerFactory.Networking().V1().Ingresses().Lister(), - }, - ctx.KubeSharedInformerFactory.Networking().V1().Ingresses().Informer(), - nil - case hasVersion(ctx.DiscoveryClient, networkingv1beta1.SchemeGroupVersion.String()): - return &v1beta1Lister{ - lister: ctx.KubeSharedInformerFactory.Networking().V1beta1().Ingresses().Lister(), - }, - ctx.KubeSharedInformerFactory.Networking().V1beta1().Ingresses().Informer(), - nil - default: - return nil, nil, fmt.Errorf("neither %s nor %s have any APIResources", networkingv1.SchemeGroupVersion, networkingv1beta1.SchemeGroupVersion) - } -} - -// NewCreateUpdater returns an InternalIngressCreateUpdater configured for v1 or v1beta1 ingresses depending on the -// versions available in the discovery client -func NewCreateUpdater(ctx *controller.Context) (InternalIngressCreateUpdater, error) { - if hasVersion(ctx.DiscoveryClient, networkingv1.SchemeGroupVersion.String()) { - return &v1CreaterUpdater{ - client: ctx.Client, - }, nil - } else if hasVersion(ctx.DiscoveryClient, networkingv1beta1.SchemeGroupVersion.String()) { - return &v1beta1CreaterUpdater{ - client: ctx.Client, - }, nil - } else { - return nil, fmt.Errorf("neither %s nor %s have any APIResources", networkingv1.SchemeGroupVersion, networkingv1beta1.SchemeGroupVersion) - } -} - -func hasVersion(d discovery.DiscoveryInterface, GroupVersion string) bool { - // check whether the GroupVersion is already known - knownVersions := knownAPIVersionCache.Load().(map[string]bool) - knownVersion, found := knownVersions[GroupVersion] - if found { - return knownVersion - } - - resourceList, err := d.ServerResourcesForGroupVersion(GroupVersion) - if err != nil { - return false - } - for _, r := range resourceList.APIResources { - if r.Kind == "Ingress" { - // Now we know the APIServer supports this GroupVersion, store the result atomically - // in the knownVersions cache. Lock, get the latest copy, atomically update. - cacheLock.Lock() - oldCache := knownAPIVersionCache.Load().(map[string]bool) - newCache := make(map[string]bool) - for k, v := range oldCache { - newCache[k] = v - } - newCache[GroupVersion] = true - knownAPIVersionCache.Store(newCache) - cacheLock.Unlock() - return true - } - } - // no networking error and no Ingresses found in networking.k8s.io/, cache negative result - cacheLock.Lock() - oldCache := knownAPIVersionCache.Load().(map[string]bool) - newCache := make(map[string]bool) - for k, v := range oldCache { - newCache[k] = v - } - newCache[GroupVersion] = false - knownAPIVersionCache.Store(newCache) - cacheLock.Unlock() - return false -} - -func init() { - knownAPIVersionCache.Store(make(map[string]bool)) -} diff --git a/internal/ingress/ingress_test.go b/internal/ingress/ingress_test.go deleted file mode 100644 index 77462c238..000000000 --- a/internal/ingress/ingress_test.go +++ /dev/null @@ -1,233 +0,0 @@ -/* -Copyright 2021 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package ingress - -import ( - "context" - "fmt" - "testing" - "time" - - "github.com/stretchr/testify/assert" - networkingv1 "k8s.io/api/networking/v1" - networkingv1beta1 "k8s.io/api/networking/v1beta1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/client-go/informers" - kubefake "k8s.io/client-go/kubernetes/fake" - "k8s.io/utils/pointer" - - "github.com/cert-manager/cert-manager/pkg/controller" - discoveryfake "github.com/cert-manager/cert-manager/test/unit/discovery" -) - -// Important: these tests cannot run in parallel as the cache holds internal state at the package level. - -func TestFunctionalityAgainstV1(t *testing.T) { - // wipe known versions cache - cacheLock.Lock() - knownAPIVersionCache.Store(make(map[string]bool)) - cacheLock.Unlock() - - fakeClient := kubefake.NewSimpleClientset() - v1ctx := &controller.Context{ - RootContext: context.TODO(), - Client: fakeClient, - DiscoveryClient: fakeDiscoveryFor(networkingv1.SchemeGroupVersion), - KubeSharedInformerFactory: informers.NewSharedInformerFactory(fakeClient, 10*time.Hour), - } - ch := make(chan struct{}) - v1ctx.KubeSharedInformerFactory.Start(ch) - errs := testFunctionality(t, v1ctx) - assert.Len(t, errs, 0, "InternalIngress should not fail on an API server that supports networking.k8s.io/v1") - close(ch) -} - -func TestFunctionalityAgainstV1Beta1(t *testing.T) { - cacheLock.Lock() - knownAPIVersionCache.Store(make(map[string]bool)) - cacheLock.Unlock() - - fakeClient := kubefake.NewSimpleClientset() - - v1beta1ctx := &controller.Context{ - RootContext: context.TODO(), - Client: fakeClient, - DiscoveryClient: fakeDiscoveryFor(networkingv1beta1.SchemeGroupVersion), - KubeSharedInformerFactory: informers.NewSharedInformerFactory(fakeClient, 10*time.Hour), - } - ch := make(chan struct{}) - v1beta1ctx.KubeSharedInformerFactory.Start(ch) - errs := testFunctionality(t, v1beta1ctx) - assert.Len(t, errs, 0, "InternalIngress should not fail on an API server that supports networking.k8s.io/v1beta1") - close(ch) -} - -func TestFunctionalityAgainstNone(t *testing.T) { - // wipe known versions cache - cacheLock.Lock() - knownAPIVersionCache.Store(make(map[string]bool)) - cacheLock.Unlock() - - fakeClient := kubefake.NewSimpleClientset() - noneCtx := &controller.Context{ - RootContext: context.TODO(), - Client: fakeClient, - DiscoveryClient: uselessDiscovery(), - KubeSharedInformerFactory: informers.NewSharedInformerFactory(fakeClient, 10*time.Hour), - } - _, _, err := NewListerInformer(noneCtx) - if assert.Error(t, err) { - assert.Equal( - t, - fmt.Errorf("neither %s nor %s have any APIResources", networkingv1.SchemeGroupVersion, networkingv1beta1.SchemeGroupVersion), - err, - ) - } -} - -func fakeDiscoveryFor(version schema.GroupVersion) *discoveryfake.Discovery { - return discoveryfake.NewDiscovery().WithServerResourcesForGroupVersion(func(groupVersion string) (*metav1.APIResourceList, error) { - if groupVersion == version.String() { - return &metav1.APIResourceList{ - TypeMeta: metav1.TypeMeta{}, - GroupVersion: version.String(), - APIResources: []metav1.APIResource{ - { - Name: "ingresses", - SingularName: "Ingress", - Namespaced: true, - Group: version.Group, - Version: version.Version, - Kind: version.WithKind("Ingress").Kind, - Verbs: metav1.Verbs{"get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"}, - ShortNames: []string{"ing"}, - Categories: []string{"all"}, - StorageVersionHash: "testing", - }, - }, - }, nil - } else { - return &metav1.APIResourceList{}, nil - } - }) -} - -func uselessDiscovery() *discoveryfake.Discovery { - return discoveryfake.NewDiscovery(). - WithServerResourcesForGroupVersion( - func(groupVersion string) (*metav1.APIResourceList, error) { - return &metav1.APIResourceList{}, nil - }, - ) -} - -func testFunctionality(t *testing.T, ctx *controller.Context) []error { - var ret []error - lister, _, err := NewListerInformer(ctx) - assert.NoError(t, err, "New ListerInformer should not fail") - if err != nil { - ret = append(ret, err) - } - createUpdater, err := NewCreateUpdater(ctx) - assert.NoError(t, err, "New CreateUpdater should not fail") - if err != nil { - ret = append(ret, err) - } - _, err = createUpdater.Ingresses("default").Create(context.TODO(), &networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test", - Namespace: "default", - }, - Spec: networkingv1.IngressSpec{ - IngressClassName: pointer.StringPtr("test1"), - Rules: []networkingv1.IngressRule{ - { - Host: "test", - IngressRuleValue: networkingv1.IngressRuleValue{ - HTTP: &networkingv1.HTTPIngressRuleValue{ - Paths: []networkingv1.HTTPIngressPath{ - { - Path: "/", - PathType: func() *networkingv1.PathType { s := networkingv1.PathTypePrefix; return &s }(), - Backend: networkingv1.IngressBackend{ - Service: &networkingv1.IngressServiceBackend{ - Name: "test", - Port: networkingv1.ServiceBackendPort{ - Number: 80, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, metav1.CreateOptions{}) - assert.NoError(t, err, "Create should not fail") - if err != nil { - ret = append(ret, err) - } - _, err = createUpdater.Ingresses("default").Update(context.TODO(), &networkingv1.Ingress{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test", - Namespace: "default", - }, - Spec: networkingv1.IngressSpec{ - IngressClassName: pointer.StringPtr("test1"), - Rules: []networkingv1.IngressRule{ - { - Host: "test", - IngressRuleValue: networkingv1.IngressRuleValue{ - HTTP: &networkingv1.HTTPIngressRuleValue{ - Paths: []networkingv1.HTTPIngressPath{ - { - Path: "/", - PathType: func() *networkingv1.PathType { s := networkingv1.PathTypePrefix; return &s }(), - Backend: networkingv1.IngressBackend{ - Service: &networkingv1.IngressServiceBackend{ - Name: "test", - Port: networkingv1.ServiceBackendPort{ - Number: 80, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, metav1.UpdateOptions{}) - assert.NoError(t, err, "Update should not fail") - if err != nil { - ret = append(ret, err) - } - _, err = lister.List(labels.Everything()) - assert.NoError(t, err, "List should not fail") - - err = createUpdater.Ingresses("default").Delete(context.TODO(), "test", metav1.DeleteOptions{}) - assert.NoError(t, err, "delete should not fail") - if err != nil { - ret = append(ret, err) - } - return ret -} diff --git a/internal/ingress/v1.go b/internal/ingress/v1.go deleted file mode 100644 index c86bb1453..000000000 --- a/internal/ingress/v1.go +++ /dev/null @@ -1,83 +0,0 @@ -/* -Copyright 2021 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package ingress - -import ( - "context" - - networkingv1 "k8s.io/api/networking/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/kubernetes" - listersv1 "k8s.io/client-go/listers/networking/v1" -) - -type v1Lister struct { - lister listersv1.IngressLister -} - -type v1NamespaceLister struct { - nsLister listersv1.IngressNamespaceLister -} - -func (l *v1Lister) List(selector labels.Selector) ([]*networkingv1.Ingress, error) { - return l.lister.List(selector) -} - -func (l *v1Lister) Ingresses(namespace string) InternalIngressNamespaceLister { - return &v1NamespaceLister{nsLister: l.lister.Ingresses(namespace)} -} - -func (nl *v1NamespaceLister) List(selector labels.Selector) ([]*networkingv1.Ingress, error) { - return nl.nsLister.List(selector) -} - -func (nl *v1NamespaceLister) Get(name string) (*networkingv1.Ingress, error) { - return nl.nsLister.Get(name) -} - -type v1CreaterUpdater struct { - client kubernetes.Interface -} - -func (v1 *v1CreaterUpdater) Ingresses(namespace string) InternalIngressInterface { - return &v1Interface{ - client: v1.client, - ns: namespace, - } -} - -type v1Interface struct { - client kubernetes.Interface - ns string -} - -func (v1 *v1Interface) Get(ctx context.Context, name string, opts metav1.GetOptions) (*networkingv1.Ingress, error) { - return v1.client.NetworkingV1().Ingresses(v1.ns).Get(ctx, name, opts) -} - -func (v1 *v1Interface) Create(ctx context.Context, ingress *networkingv1.Ingress, opts metav1.CreateOptions) (*networkingv1.Ingress, error) { - return v1.client.NetworkingV1().Ingresses(v1.ns).Create(ctx, ingress, opts) -} - -func (v1 *v1Interface) Update(ctx context.Context, ingress *networkingv1.Ingress, opts metav1.UpdateOptions) (*networkingv1.Ingress, error) { - return v1.client.NetworkingV1().Ingresses(v1.ns).Update(ctx, ingress, opts) -} - -func (v1 *v1Interface) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { - return v1.client.NetworkingV1().Ingresses(v1.ns).Delete(ctx, name, opts) -} diff --git a/internal/ingress/v1beta1.go b/internal/ingress/v1beta1.go deleted file mode 100644 index 224210274..000000000 --- a/internal/ingress/v1beta1.go +++ /dev/null @@ -1,182 +0,0 @@ -/* -Copyright 2021 The cert-manager Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package ingress - -import ( - "context" - "fmt" - - networkingv1 "k8s.io/api/networking/v1" - networkingv1beta1 "k8s.io/api/networking/v1beta1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/kubernetes" - listersv1beta1 "k8s.io/client-go/listers/networking/v1beta1" -) - -// ConvertedGVKAnnotation is the annotation key set by cert-manager on Ingress -// resources converted from networking.k8s.io/v1beta1 to networking.k8s.io/v1 -// -// On Kubernetes 1.16, 1.17, and 1.18, the `networking.k8s.io/v1` API did not exist yet. -// For these Kubernetes versions, cert-manager converts `networking.k8s.io/v1beta1` -// into `networking.k8s.io/v1`, which is the one version used across cert-manager. -// -// But this conversion means that we lose the "original" apiVersion, which is needed -// by the ingress-shim sync function to set the correct `ownerReference` on the -// Certificate it creates. -// -// This annotation is only set on Ingresses on Kubernetes 1.16, 1.17, and 1.18. -const ConvertedGVKAnnotation = `internal.cert-manager.io/converted-gvk` - -type v1beta1Lister struct { - lister listersv1beta1.IngressLister -} - -type v1beta1NamespaceLister struct { - nsLister listersv1beta1.IngressNamespaceLister -} - -func (l *v1beta1Lister) List(selector labels.Selector) ([]*networkingv1.Ingress, error) { - all, err := l.lister.List(selector) - if err != nil { - return nil, err - } - return convertV1Beta1ListToV1(all) -} - -func (l *v1beta1Lister) Ingresses(namespace string) InternalIngressNamespaceLister { - return &v1beta1NamespaceLister{ - nsLister: l.lister.Ingresses(namespace), - } -} - -func (nl *v1beta1NamespaceLister) List(selector labels.Selector) ([]*networkingv1.Ingress, error) { - all, err := nl.nsLister.List(selector) - if err != nil { - return nil, err - } - return convertV1Beta1ListToV1(all) -} - -func (nl *v1beta1NamespaceLister) Get(name string) (*networkingv1.Ingress, error) { - ing, err := nl.nsLister.Get(name) - if err != nil { - return nil, err - } - return convertV1Beta1ToV1(ing) -} - -func convertV1Beta1ListToV1(list []*networkingv1beta1.Ingress) ([]*networkingv1.Ingress, error) { - var ret []*networkingv1.Ingress - for _, in := range list { - out, err := convertV1Beta1ToV1(in) - if err != nil { - return nil, err - } - ret = append(ret, out) - } - return ret, nil -} - -func convertV1Beta1ToV1(in *networkingv1beta1.Ingress) (*networkingv1.Ingress, error) { - out := new(networkingv1.Ingress) - err := Convert_v1beta1_Ingress_To_networking_Ingress(in.DeepCopy(), out, nil) - - if err != nil { - return nil, fmt.Errorf( - "could not convert %s to %s when processing object %s/%s: %w", - networkingv1beta1.SchemeGroupVersion, - networkingv1.SchemeGroupVersion, - in.Namespace, - in.Name, - err, - ) - } - if out.Annotations == nil { - out.Annotations = make(map[string]string) - } - out.Annotations[ConvertedGVKAnnotation] = networkingv1beta1.SchemeGroupVersion.WithKind("Ingress").String() - return out, nil -} - -func convertV1ToV1Beta1(in *networkingv1.Ingress) (*networkingv1beta1.Ingress, error) { - out := new(networkingv1beta1.Ingress) - err := Convert_networking_Ingress_To_v1beta1_Ingress(in.DeepCopy(), out, nil) - if err != nil { - return nil, fmt.Errorf( - "could not convert %s to %s when processing object %s/%s: %w", - networkingv1.SchemeGroupVersion, - networkingv1beta1.SchemeGroupVersion, - in.Namespace, - in.Name, - err, - ) - } - return out, nil -} - -type v1beta1CreaterUpdater struct { - client kubernetes.Interface -} - -func (v *v1beta1CreaterUpdater) Ingresses(namespace string) InternalIngressInterface { - return &v1beta1Interface{ - client: v.client, - ns: namespace, - } -} - -type v1beta1Interface struct { - client kubernetes.Interface - ns string -} - -func (v *v1beta1Interface) Get(ctx context.Context, name string, opts metav1.GetOptions) (*networkingv1.Ingress, error) { - ing, err := v.client.NetworkingV1beta1().Ingresses(v.ns).Get(ctx, name, opts) - if err != nil { - return nil, err - } - return convertV1Beta1ToV1(ing) -} - -func (v *v1beta1Interface) Create(ctx context.Context, ingress *networkingv1.Ingress, opts metav1.CreateOptions) (*networkingv1.Ingress, error) { - ing, err := convertV1ToV1Beta1(ingress) - if err != nil { - return nil, err - } - newIng, err := v.client.NetworkingV1beta1().Ingresses(v.ns).Create(ctx, ing, opts) - if err != nil { - return nil, err - } - return convertV1Beta1ToV1(newIng) -} - -func (v *v1beta1Interface) Update(ctx context.Context, ingress *networkingv1.Ingress, opts metav1.UpdateOptions) (*networkingv1.Ingress, error) { - ing, err := convertV1ToV1Beta1(ingress) - if err != nil { - return nil, err - } - newIng, err := v.client.NetworkingV1beta1().Ingresses(v.ns).Update(ctx, ing, opts) - if err != nil { - return nil, err - } - return convertV1Beta1ToV1(newIng) -} - -func (v *v1beta1Interface) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { - return v.client.NetworkingV1beta1().Ingresses(v.ns).Delete(ctx, name, opts) -} diff --git a/pkg/controller/acmechallenges/BUILD.bazel b/pkg/controller/acmechallenges/BUILD.bazel index d5fffff66..f03aeed5d 100644 --- a/pkg/controller/acmechallenges/BUILD.bazel +++ b/pkg/controller/acmechallenges/BUILD.bazel @@ -14,7 +14,6 @@ go_library( deps = [ "//internal/controller/challenges:go_default_library", "//internal/controller/feature:go_default_library", - "//internal/ingress:go_default_library", "//pkg/acme:go_default_library", "//pkg/acme/accounts:go_default_library", "//pkg/acme/client:go_default_library", diff --git a/pkg/controller/acmechallenges/controller.go b/pkg/controller/acmechallenges/controller.go index 91dc22291..e556d8829 100644 --- a/pkg/controller/acmechallenges/controller.go +++ b/pkg/controller/acmechallenges/controller.go @@ -28,7 +28,6 @@ import ( "k8s.io/client-go/tools/record" "k8s.io/client-go/util/workqueue" - "github.com/cert-manager/cert-manager/internal/ingress" "github.com/cert-manager/cert-manager/pkg/acme/accounts" cmacmelisters "github.com/cert-manager/cert-manager/pkg/client/listers/acme/v1" cmlisters "github.com/cert-manager/cert-manager/pkg/client/listers/certmanager/v1" @@ -97,11 +96,7 @@ func (c *controller) Register(ctx *controllerpkg.Context) (workqueue.RateLimitin // cache when managing pod/service/ingress resources podInformer := ctx.KubeSharedInformerFactory.Core().V1().Pods() serviceInformer := ctx.KubeSharedInformerFactory.Core().V1().Services() - - _, ingressInformer, err := ingress.NewListerInformer(ctx) - if err != nil { - return nil, nil, err - } + ingressInformer := ctx.KubeSharedInformerFactory.Networking().V1().Ingresses() // build a list of InformerSynced functions that will be returned by the Register method. // the controller will only begin processing items once all of these informers have synced. @@ -111,7 +106,7 @@ func (c *controller) Register(ctx *controllerpkg.Context) (workqueue.RateLimitin secretInformer.Informer().HasSynced, podInformer.Informer().HasSynced, serviceInformer.Informer().HasSynced, - ingressInformer.HasSynced, + ingressInformer.Informer().HasSynced, } if ctx.GatewaySolverEnabled { @@ -140,6 +135,7 @@ func (c *controller) Register(ctx *controllerpkg.Context) (workqueue.RateLimitin c.recorder = ctx.Recorder c.accountRegistry = ctx.ACMEOptions.AccountRegistry + var err error c.httpSolver, err = http.NewSolver(ctx) if err != nil { return nil, nil, err diff --git a/pkg/controller/certificate-shim/BUILD.bazel b/pkg/controller/certificate-shim/BUILD.bazel index 220f76206..e14db4253 100644 --- a/pkg/controller/certificate-shim/BUILD.bazel +++ b/pkg/controller/certificate-shim/BUILD.bazel @@ -11,7 +11,6 @@ go_library( deps = [ "//internal/controller/certificates:go_default_library", "//internal/controller/feature:go_default_library", - "//internal/ingress:go_default_library", "//pkg/api/util:go_default_library", "//pkg/apis/acme/v1:go_default_library", "//pkg/apis/certmanager/v1:go_default_library", @@ -24,7 +23,6 @@ go_library( "@com_github_go_logr_logr//:go_default_library", "@io_k8s_api//core/v1:go_default_library", "@io_k8s_api//networking/v1:go_default_library", - "@io_k8s_api//networking/v1beta1:go_default_library", "@io_k8s_apimachinery//pkg/api/errors:go_default_library", "@io_k8s_apimachinery//pkg/apis/meta/v1:go_default_library", "@io_k8s_apimachinery//pkg/labels:go_default_library", diff --git a/pkg/controller/certificate-shim/ingresses/BUILD.bazel b/pkg/controller/certificate-shim/ingresses/BUILD.bazel index b881b9ca3..71220cdc7 100644 --- a/pkg/controller/certificate-shim/ingresses/BUILD.bazel +++ b/pkg/controller/certificate-shim/ingresses/BUILD.bazel @@ -6,7 +6,6 @@ go_library( importpath = "github.com/cert-manager/cert-manager/pkg/controller/certificate-shim/ingresses", visibility = ["//visibility:public"], deps = [ - "//internal/ingress:go_default_library", "//pkg/apis/certmanager/v1:go_default_library", "//pkg/controller:go_default_library", "//pkg/controller/certificate-shim:go_default_library", @@ -14,6 +13,7 @@ go_library( "@io_k8s_apimachinery//pkg/api/errors:go_default_library", "@io_k8s_apimachinery//pkg/apis/meta/v1:go_default_library", "@io_k8s_apimachinery//pkg/util/runtime:go_default_library", + "@io_k8s_client_go//listers/networking/v1:go_default_library", "@io_k8s_client_go//tools/cache:go_default_library", "@io_k8s_client_go//util/workqueue:go_default_library", ], diff --git a/pkg/controller/certificate-shim/ingresses/controller.go b/pkg/controller/certificate-shim/ingresses/controller.go index 53f287548..a479d0238 100644 --- a/pkg/controller/certificate-shim/ingresses/controller.go +++ b/pkg/controller/certificate-shim/ingresses/controller.go @@ -23,10 +23,10 @@ import ( k8sErrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/runtime" + networkingv1listers "k8s.io/client-go/listers/networking/v1" "k8s.io/client-go/tools/cache" "k8s.io/client-go/util/workqueue" - "github.com/cert-manager/cert-manager/internal/ingress" cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" controllerpkg "github.com/cert-manager/cert-manager/pkg/controller" shimhelper "github.com/cert-manager/cert-manager/pkg/controller/certificate-shim" @@ -38,19 +38,15 @@ const ( ) type controller struct { - ingressLister ingress.InternalIngressLister + ingressLister networkingv1listers.IngressLister sync shimhelper.SyncFn } func (c *controller) Register(ctx *controllerpkg.Context) (workqueue.RateLimitingInterface, []cache.InformerSynced, error) { cmShared := ctx.SharedInformerFactory - internalIngressLister, internalIngressInformer, err := ingress.NewListerInformer(ctx) - if err != nil { - return nil, nil, err - } - - c.ingressLister = internalIngressLister + ingressInformer := ctx.KubeSharedInformerFactory.Networking().V1().Ingresses() + c.ingressLister = ingressInformer.Lister() log := logf.FromContext(ctx.RootContext, ControllerName) c.sync = shimhelper.SyncFnFor(ctx.Recorder, log, ctx.CMClient, cmShared.Certmanager().V1().Certificates().Lister(), ctx.IngressShimOptions, ctx.FieldManager) @@ -58,7 +54,7 @@ func (c *controller) Register(ctx *controllerpkg.Context) (workqueue.RateLimitin queue := workqueue.NewNamedRateLimitingQueue(controllerpkg.DefaultItemBasedRateLimiter(), ControllerName) mustSync := []cache.InformerSynced{ - internalIngressInformer.HasSynced, + ingressInformer.Informer().HasSynced, cmShared.Certmanager().V1().Certificates().Informer().HasSynced, } @@ -68,7 +64,7 @@ func (c *controller) Register(ctx *controllerpkg.Context) (workqueue.RateLimitin // to do some cleanup, we would use a finalizer, and the cleanup logic would // be triggered by the "Updated" event when the object gets marked for // deletion. - internalIngressInformer.AddEventHandler(&controllerpkg.QueuingEventHandler{ + ingressInformer.Informer().AddEventHandler(&controllerpkg.QueuingEventHandler{ Queue: queue, }) @@ -139,9 +135,6 @@ func certificateHandler(queue workqueue.RateLimitingInterface) func(obj interfac return } - // We don't check the apiVersion e.g. "networking.k8s.io/v1beta1" - // because there is no chance that another object called "Ingress" be - // the controller of a Certificate. if ingress.Kind != "Ingress" { return } diff --git a/pkg/controller/certificate-shim/sync.go b/pkg/controller/certificate-shim/sync.go index 7fadb0512..ff02a4bde 100644 --- a/pkg/controller/certificate-shim/sync.go +++ b/pkg/controller/certificate-shim/sync.go @@ -27,7 +27,6 @@ import ( "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" networkingv1 "k8s.io/api/networking/v1" - networkingv1beta1 "k8s.io/api/networking/v1beta1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" @@ -39,7 +38,6 @@ import ( internalcertificates "github.com/cert-manager/cert-manager/internal/controller/certificates" "github.com/cert-manager/cert-manager/internal/controller/feature" - ingress "github.com/cert-manager/cert-manager/internal/ingress" cmacme "github.com/cert-manager/cert-manager/pkg/apis/acme/v1" cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" @@ -58,7 +56,6 @@ const ( ) var ingressV1GVK = networkingv1.SchemeGroupVersion.WithKind("Ingress") -var ingressV1Beta1GVK = networkingv1beta1.SchemeGroupVersion.WithKind("Ingress") var gatewayGVK = gwapi.SchemeGroupVersion.WithKind("Gateway") // SyncFn is the reconciliation function passed to a certificate-shim's @@ -351,11 +348,7 @@ func buildCertificates( var controllerGVK schema.GroupVersionKind switch ingLike.(type) { case *networkingv1.Ingress: - if _, found := ingLike.GetAnnotations()[ingress.ConvertedGVKAnnotation]; found { - controllerGVK = ingressV1Beta1GVK - } else { - controllerGVK = ingressV1GVK - } + controllerGVK = ingressV1GVK case *gwapi.Gateway: controllerGVK = gatewayGVK } diff --git a/pkg/issuer/acme/http/BUILD.bazel b/pkg/issuer/acme/http/BUILD.bazel index 6f82907a7..e70ccb17f 100644 --- a/pkg/issuer/acme/http/BUILD.bazel +++ b/pkg/issuer/acme/http/BUILD.bazel @@ -12,7 +12,6 @@ go_library( importpath = "github.com/cert-manager/cert-manager/pkg/issuer/acme/http", visibility = ["//visibility:public"], deps = [ - "//internal/ingress:go_default_library", "//pkg/apis/acme/v1:go_default_library", "//pkg/apis/certmanager/v1:go_default_library", "//pkg/controller:go_default_library", @@ -27,6 +26,7 @@ go_library( "@io_k8s_apimachinery//pkg/util/errors:go_default_library", "@io_k8s_apimachinery//pkg/util/intstr:go_default_library", "@io_k8s_client_go//listers/core/v1:go_default_library", + "@io_k8s_client_go//listers/networking/v1:go_default_library", "@io_k8s_client_go//util/retry:go_default_library", "@io_k8s_sigs_gateway_api//apis/v1alpha2:go_default_library", "@io_k8s_sigs_gateway_api//pkg/client/listers/gateway/apis/v1alpha2:go_default_library", diff --git a/pkg/issuer/acme/http/http.go b/pkg/issuer/acme/http/http.go index 99d958fe0..f47e2ae08 100644 --- a/pkg/issuer/acme/http/http.go +++ b/pkg/issuer/acme/http/http.go @@ -30,10 +30,10 @@ import ( corev1 "k8s.io/api/core/v1" utilerrors "k8s.io/apimachinery/pkg/util/errors" corev1listers "k8s.io/client-go/listers/core/v1" + networkingv1listers "k8s.io/client-go/listers/networking/v1" k8snet "k8s.io/utils/net" gwapilisters "sigs.k8s.io/gateway-api/pkg/client/listers/gateway/apis/v1alpha2" - "github.com/cert-manager/cert-manager/internal/ingress" cmacme "github.com/cert-manager/cert-manager/pkg/apis/acme/v1" v1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" "github.com/cert-manager/cert-manager/pkg/controller" @@ -59,11 +59,10 @@ var ( type Solver struct { *controller.Context - podLister corev1listers.PodLister - serviceLister corev1listers.ServiceLister - ingressLister ingress.InternalIngressLister - ingressCreateUpdater ingress.InternalIngressCreateUpdater - httpRouteLister gwapilisters.HTTPRouteLister + podLister corev1listers.PodLister + serviceLister corev1listers.ServiceLister + ingressLister networkingv1listers.IngressLister + httpRouteLister gwapilisters.HTTPRouteLister testReachability reachabilityTest requiredPasses int @@ -73,23 +72,14 @@ type reachabilityTest func(ctx context.Context, url *url.URL, key string, dnsSer // NewSolver returns a new ACME HTTP01 solver for the given *controller.Context. func NewSolver(ctx *controller.Context) (*Solver, error) { - ingressLister, _, err := ingress.NewListerInformer(ctx) - if err != nil { - return nil, err - } - ingressCreateUpdater, err := ingress.NewCreateUpdater(ctx) - if err != nil { - return nil, err - } return &Solver{ - Context: ctx, - podLister: ctx.KubeSharedInformerFactory.Core().V1().Pods().Lister(), - serviceLister: ctx.KubeSharedInformerFactory.Core().V1().Services().Lister(), - ingressLister: ingressLister, - ingressCreateUpdater: ingressCreateUpdater, - httpRouteLister: ctx.GWShared.Gateway().V1alpha2().HTTPRoutes().Lister(), - testReachability: testReachability, - requiredPasses: 5, + Context: ctx, + podLister: ctx.KubeSharedInformerFactory.Core().V1().Pods().Lister(), + serviceLister: ctx.KubeSharedInformerFactory.Core().V1().Services().Lister(), + ingressLister: ctx.KubeSharedInformerFactory.Networking().V1().Ingresses().Lister(), + httpRouteLister: ctx.GWShared.Gateway().V1alpha2().HTTPRoutes().Lister(), + testReachability: testReachability, + requiredPasses: 5, }, nil } diff --git a/pkg/issuer/acme/http/ingress.go b/pkg/issuer/acme/http/ingress.go index f754d4b6e..987e73049 100644 --- a/pkg/issuer/acme/http/ingress.go +++ b/pkg/issuer/acme/http/ingress.go @@ -138,7 +138,7 @@ func (s *Solver) createIngress(ctx context.Context, ch *cmacme.Challenge, svcNam ing = s.mergeIngressObjectMetaWithIngressResourceTemplate(ing, ch.Spec.Solver.HTTP01.Ingress.IngressTemplate) } - return s.ingressCreateUpdater.Ingresses(ch.Namespace).Create(ctx, ing, metav1.CreateOptions{}) + return s.Client.NetworkingV1().Ingresses(ch.Namespace).Create(ctx, ing, metav1.CreateOptions{}) } func buildIngressResource(ch *cmacme.Challenge, svcName string) (*networkingv1.Ingress, error) { @@ -256,11 +256,11 @@ func (s *Solver) addChallengePathToIngress(ctx context.Context, ch *cmacme.Chall return ing, nil } rule.HTTP.Paths[i] = ingPathToAdd - return s.ingressCreateUpdater.Ingresses(ing.Namespace).Update(ctx, ing, metav1.UpdateOptions{}) + return s.Client.NetworkingV1().Ingresses(ing.Namespace).Update(ctx, ing, metav1.UpdateOptions{}) } } rule.HTTP.Paths = append([]networkingv1.HTTPIngressPath{ingPathToAdd}, rule.HTTP.Paths...) - return s.ingressCreateUpdater.Ingresses(ing.Namespace).Update(ctx, ing, metav1.UpdateOptions{}) + return s.Client.NetworkingV1().Ingresses(ing.Namespace).Update(ctx, ing, metav1.UpdateOptions{}) } } @@ -273,7 +273,7 @@ func (s *Solver) addChallengePathToIngress(ctx context.Context, ch *cmacme.Chall }, }, }) - return s.ingressCreateUpdater.Ingresses(ing.Namespace).Update(ctx, ing, metav1.UpdateOptions{}) + return s.Client.NetworkingV1().Ingresses(ing.Namespace).Update(ctx, ing, metav1.UpdateOptions{}) } // cleanupIngresses will remove the rules added by cert-manager to an existing @@ -304,7 +304,7 @@ func (s *Solver) cleanupIngresses(ctx context.Context, ch *cmacme.Challenge) err log := logf.WithRelatedResource(log, ingress).V(logf.DebugLevel) log.V(logf.DebugLevel).Info("deleting ingress resource") - err := s.ingressCreateUpdater.Ingresses(ingress.Namespace).Delete(ctx, ingress.Name, metav1.DeleteOptions{}) + err := s.Client.NetworkingV1().Ingresses(ingress.Namespace).Delete(ctx, ingress.Name, metav1.DeleteOptions{}) if err != nil { log.V(logf.WarnLevel).Info("failed to delete ingress resource", "error", err) errs = append(errs, err) @@ -316,7 +316,7 @@ func (s *Solver) cleanupIngresses(ctx context.Context, ch *cmacme.Challenge) err } // otherwise, we need to remove any cert-manager added rules from the ingress resource - ing, err := s.ingressCreateUpdater.Ingresses(ch.Namespace).Get(ctx, existingIngressName, metav1.GetOptions{}) + ing, err := s.Client.NetworkingV1().Ingresses(ch.Namespace).Get(ctx, existingIngressName, metav1.GetOptions{}) if k8sErrors.IsNotFound(err) { log.Error(err, "named ingress resource not found, skipping cleanup") return nil @@ -359,7 +359,7 @@ func (s *Solver) cleanupIngresses(ctx context.Context, ch *cmacme.Challenge) err ing.Spec.Rules = ingRules - _, err = s.ingressCreateUpdater.Ingresses(ing.Namespace).Update(ctx, ing, metav1.UpdateOptions{}) + _, err = s.Client.NetworkingV1().Ingresses(ing.Namespace).Update(ctx, ing, metav1.UpdateOptions{}) if err != nil { return err }