Merge pull request #4225 from jakexks/ingressv1

Feature: Support both v1 and v1beta1 ingresses.
This commit is contained in:
jetstack-bot
2021-07-27 20:11:37 +01:00
committed by GitHub
36 changed files with 1630 additions and 302 deletions
+1
View File
@@ -93,6 +93,7 @@ filegroup(
"//test/integration:all-srcs",
"//test/internal/apiserver:all-srcs",
"//test/unit/coreclients:all-srcs",
"//test/unit/discovery:all-srcs",
"//test/unit/gen:all-srcs",
"//test/unit/listers:all-srcs",
"//tools/cobra:all-srcs",
+1
View File
@@ -243,6 +243,7 @@ func buildControllerContext(ctx context.Context, stopCh <-chan struct{}, opts *o
Client: cl,
CMClient: intcl,
GWClient: gwcl,
DiscoveryClient: cl.Discovery(),
Recorder: recorder,
KubeSharedInformerFactory: kubeSharedInformerFactory,
SharedInformerFactory: sharedInformerFactory,
+1
View File
@@ -26,6 +26,7 @@ go_library(
"@io_k8s_apimachinery//pkg/util/runtime:go_default_library",
"@io_k8s_apimachinery//pkg/util/wait:go_default_library",
"@io_k8s_apiserver//pkg/registry/generic/registry:go_default_library",
"@io_k8s_client_go//discovery:go_default_library",
"@io_k8s_client_go//informers:go_default_library",
"@io_k8s_client_go//kubernetes:go_default_library",
"@io_k8s_client_go//rest:go_default_library",
@@ -21,6 +21,7 @@ go_library(
"//pkg/controller:go_default_library",
"//pkg/controller/acmechallenges/scheduler:go_default_library",
"//pkg/feature:go_default_library",
"//pkg/internal/ingress:go_default_library",
"//pkg/issuer:go_default_library",
"//pkg/issuer/acme/dns:go_default_library",
"//pkg/issuer/acme/dns/util:go_default_library",
+12 -4
View File
@@ -35,6 +35,7 @@ import (
cmlisters "github.com/jetstack/cert-manager/pkg/client/listers/certmanager/v1"
controllerpkg "github.com/jetstack/cert-manager/pkg/controller"
"github.com/jetstack/cert-manager/pkg/controller/acmechallenges/scheduler"
"github.com/jetstack/cert-manager/pkg/internal/ingress"
"github.com/jetstack/cert-manager/pkg/issuer"
"github.com/jetstack/cert-manager/pkg/issuer/acme/dns"
"github.com/jetstack/cert-manager/pkg/issuer/acme/http"
@@ -96,7 +97,12 @@ 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 := ctx.KubeSharedInformerFactory.Networking().V1beta1().Ingresses()
_, ingressInformer, err := ingress.NewListerInformer(ctx)
if err != nil {
return nil, nil, err
}
// 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.
mustSync := []cache.InformerSynced{
@@ -105,7 +111,7 @@ func (c *controller) Register(ctx *controllerpkg.Context) (workqueue.RateLimitin
secretInformer.Informer().HasSynced,
podInformer.Informer().HasSynced,
serviceInformer.Informer().HasSynced,
ingressInformer.Informer().HasSynced,
ingressInformer.HasSynced,
}
// set all the references to the listers for used by the Sync function
@@ -128,10 +134,12 @@ func (c *controller) Register(ctx *controllerpkg.Context) (workqueue.RateLimitin
c.scheduler = scheduler.New(logf.NewContext(ctx.RootContext, c.log), c.challengeLister, ctx.SchedulerOptions.MaxConcurrentChallenges)
c.recorder = ctx.Recorder
c.cmClient = ctx.CMClient
c.httpSolver = http.NewSolver(ctx)
c.accountRegistry = ctx.ACMEOptions.AccountRegistry
var err error
c.httpSolver, err = http.NewSolver(ctx)
if err != nil {
return nil, nil, err
}
c.dnsSolver, err = dns.NewSolver(ctx)
if err != nil {
return nil, nil, err
+3 -1
View File
@@ -16,9 +16,11 @@ go_library(
"//pkg/client/clientset/versioned:go_default_library",
"//pkg/client/listers/certmanager/v1:go_default_library",
"//pkg/controller:go_default_library",
"//pkg/internal/ingress:go_default_library",
"//pkg/logs:go_default_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",
@@ -47,7 +49,7 @@ go_test(
"//test/unit/gen:go_default_library",
"@com_github_go_logr_logr//:go_default_library",
"@com_github_stretchr_testify//assert:go_default_library",
"@io_k8s_api//networking/v1beta1:go_default_library",
"@io_k8s_api//networking/v1:go_default_library",
"@io_k8s_apimachinery//pkg/apis/meta/v1:go_default_library",
"@io_k8s_apimachinery//pkg/runtime:go_default_library",
"@io_k8s_apimachinery//pkg/types:go_default_library",
@@ -9,11 +9,11 @@ go_library(
"//pkg/apis/certmanager/v1:go_default_library",
"//pkg/controller:go_default_library",
"//pkg/controller/certificate-shim:go_default_library",
"//pkg/internal/ingress:go_default_library",
"//pkg/logs: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/util/runtime:go_default_library",
"@io_k8s_client_go//listers/networking/v1beta1:go_default_library",
"@io_k8s_client_go//tools/cache:go_default_library",
"@io_k8s_client_go//util/workqueue:go_default_library",
],
@@ -29,7 +29,7 @@ go_test(
"//pkg/controller/test:go_default_library",
"@com_github_stretchr_testify//assert:go_default_library",
"@com_github_stretchr_testify//require:go_default_library",
"@io_k8s_api//networking/v1beta1:go_default_library",
"@io_k8s_api//networking/v1:go_default_library",
"@io_k8s_apimachinery//pkg/apis/meta/v1:go_default_library",
"@io_k8s_apimachinery//pkg/runtime:go_default_library",
"@io_k8s_client_go//kubernetes:go_default_library",
@@ -23,13 +23,13 @@ import (
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/runtime"
networkinglisters "k8s.io/client-go/listers/networking/v1beta1"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/util/workqueue"
cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1"
controllerpkg "github.com/jetstack/cert-manager/pkg/controller"
shimhelper "github.com/jetstack/cert-manager/pkg/controller/certificate-shim"
"github.com/jetstack/cert-manager/pkg/internal/ingress"
logf "github.com/jetstack/cert-manager/pkg/logs"
)
@@ -38,15 +38,19 @@ const (
)
type controller struct {
ingressLister networkinglisters.IngressLister
ingressLister ingress.InternalIngressLister
sync shimhelper.SyncFn
}
func (c *controller) Register(ctx *controllerpkg.Context) (workqueue.RateLimitingInterface, []cache.InformerSynced, error) {
kShared := ctx.KubeSharedInformerFactory
cmShared := ctx.SharedInformerFactory
c.ingressLister = kShared.Networking().V1beta1().Ingresses().Lister()
internalIngressLister, internalIngressInformer, err := ingress.NewListerInformer(ctx)
if err != nil {
return nil, nil, err
}
c.ingressLister = internalIngressLister
log := logf.FromContext(ctx.RootContext, ControllerName)
c.sync = shimhelper.SyncFnFor(ctx.Recorder, log, ctx.CMClient, cmShared.Certmanager().V1().Certificates().Lister(), ctx.IngressShimOptions)
@@ -54,7 +58,7 @@ func (c *controller) Register(ctx *controllerpkg.Context) (workqueue.RateLimitin
queue := workqueue.NewNamedRateLimitingQueue(controllerpkg.DefaultItemBasedRateLimiter(), ControllerName)
mustSync := []cache.InformerSynced{
kShared.Networking().V1beta1().Ingresses().Informer().HasSynced,
internalIngressInformer.HasSynced,
cmShared.Certmanager().V1().Certificates().Informer().HasSynced,
}
@@ -64,7 +68,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.
kShared.Networking().V1beta1().Ingresses().Informer().AddEventHandler(&controllerpkg.QueuingEventHandler{
internalIngressInformer.AddEventHandler(&controllerpkg.QueuingEventHandler{
Queue: queue,
})
@@ -24,7 +24,7 @@ import (
testpkg "github.com/jetstack/cert-manager/pkg/controller/test"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
networkingv1beta1 "k8s.io/api/networking/v1beta1"
networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
kclient "k8s.io/client-go/kubernetes"
@@ -33,7 +33,7 @@ import (
cmclient "github.com/jetstack/cert-manager/pkg/client/clientset/versioned"
)
var ingressGVK = networkingv1beta1.SchemeGroupVersion.WithKind("Ingress")
var ingressGVK = networkingv1.SchemeGroupVersion.WithKind("Ingress")
func Test_controller_Register(t *testing.T) {
tests := []struct {
@@ -46,7 +46,7 @@ func Test_controller_Register(t *testing.T) {
{
name: "ingress is re-queued when an 'Added' event is received for this ingress",
givenCall: func(t *testing.T, _ cmclient.Interface, c kclient.Interface) {
_, err := c.NetworkingV1beta1().Ingresses("namespace-1").Create(context.Background(), &networkingv1beta1.Ingress{ObjectMeta: metav1.ObjectMeta{
_, err := c.NetworkingV1().Ingresses("namespace-1").Create(context.Background(), &networkingv1.Ingress{ObjectMeta: metav1.ObjectMeta{
Namespace: "namespace-1", Name: "ingress-1",
}}, metav1.CreateOptions{})
require.NoError(t, err)
@@ -55,11 +55,11 @@ func Test_controller_Register(t *testing.T) {
},
{
name: "ingress is re-queued when an 'Updated' event is received for this ingress",
existingKObjects: []runtime.Object{&networkingv1beta1.Ingress{ObjectMeta: metav1.ObjectMeta{
existingKObjects: []runtime.Object{&networkingv1.Ingress{ObjectMeta: metav1.ObjectMeta{
Namespace: "namespace-1", Name: "ingress-1",
}}},
givenCall: func(t *testing.T, _ cmclient.Interface, c kclient.Interface) {
_, err := c.NetworkingV1beta1().Ingresses("namespace-1").Update(context.Background(), &networkingv1beta1.Ingress{ObjectMeta: metav1.ObjectMeta{
_, err := c.NetworkingV1().Ingresses("namespace-1").Update(context.Background(), &networkingv1.Ingress{ObjectMeta: metav1.ObjectMeta{
Namespace: "namespace-1", Name: "ingress-1",
}}, metav1.UpdateOptions{})
require.NoError(t, err)
@@ -68,11 +68,11 @@ func Test_controller_Register(t *testing.T) {
},
{
name: "ingress is re-queued when a 'Deleted' event is received for this ingress",
existingKObjects: []runtime.Object{&networkingv1beta1.Ingress{ObjectMeta: metav1.ObjectMeta{
existingKObjects: []runtime.Object{&networkingv1.Ingress{ObjectMeta: metav1.ObjectMeta{
Namespace: "namespace-1", Name: "ingress-1",
}}},
givenCall: func(t *testing.T, _ cmclient.Interface, c kclient.Interface) {
err := c.NetworkingV1beta1().Ingresses("namespace-1").Delete(context.Background(), "ingress-1", metav1.DeleteOptions{})
err := c.NetworkingV1().Ingresses("namespace-1").Delete(context.Background(), "ingress-1", metav1.DeleteOptions{})
require.NoError(t, err)
},
expectRequeueKey: "namespace-1/ingress-1",
@@ -82,7 +82,7 @@ func Test_controller_Register(t *testing.T) {
givenCall: func(t *testing.T, c cmclient.Interface, _ kclient.Interface) {
_, err := c.CertmanagerV1().Certificates("namespace-1").Create(context.Background(), &cmapi.Certificate{ObjectMeta: metav1.ObjectMeta{
Namespace: "namespace-1", Name: "cert-1",
OwnerReferences: []metav1.OwnerReference{*metav1.NewControllerRef(&networkingv1beta1.Ingress{ObjectMeta: metav1.ObjectMeta{
OwnerReferences: []metav1.OwnerReference{*metav1.NewControllerRef(&networkingv1.Ingress{ObjectMeta: metav1.ObjectMeta{
Namespace: "namespace-1", Name: "ingress-2",
}}, ingressGVK)},
}}, metav1.CreateOptions{})
@@ -94,14 +94,14 @@ func Test_controller_Register(t *testing.T) {
name: "ingress is re-queued when an 'Updated' event is received for its child Certificate",
existingCMObjects: []runtime.Object{&cmapi.Certificate{ObjectMeta: metav1.ObjectMeta{
Namespace: "namespace-1", Name: "cert-1",
OwnerReferences: []metav1.OwnerReference{*metav1.NewControllerRef(&networkingv1beta1.Ingress{ObjectMeta: metav1.ObjectMeta{
OwnerReferences: []metav1.OwnerReference{*metav1.NewControllerRef(&networkingv1.Ingress{ObjectMeta: metav1.ObjectMeta{
Namespace: "namespace-1", Name: "ingress-2",
}}, ingressGVK)},
}}},
givenCall: func(t *testing.T, c cmclient.Interface, _ kclient.Interface) {
_, err := c.CertmanagerV1().Certificates("namespace-1").Update(context.Background(), &cmapi.Certificate{ObjectMeta: metav1.ObjectMeta{
Namespace: "namespace-1", Name: "cert-1",
OwnerReferences: []metav1.OwnerReference{*metav1.NewControllerRef(&networkingv1beta1.Ingress{ObjectMeta: metav1.ObjectMeta{
OwnerReferences: []metav1.OwnerReference{*metav1.NewControllerRef(&networkingv1.Ingress{ObjectMeta: metav1.ObjectMeta{
Namespace: "namespace-1", Name: "ingress-2",
}}, ingressGVK)},
}}, metav1.UpdateOptions{})
@@ -113,7 +113,7 @@ func Test_controller_Register(t *testing.T) {
name: "ingress is re-queued when a 'Deleted' event is received for its child Certificate",
existingCMObjects: []runtime.Object{&cmapi.Certificate{ObjectMeta: metav1.ObjectMeta{
Namespace: "namespace-1", Name: "cert-1",
OwnerReferences: []metav1.OwnerReference{*metav1.NewControllerRef(&networkingv1beta1.Ingress{ObjectMeta: metav1.ObjectMeta{
OwnerReferences: []metav1.OwnerReference{*metav1.NewControllerRef(&networkingv1.Ingress{ObjectMeta: metav1.ObjectMeta{
Namespace: "namespace-1", Name: "ingress-2",
}}, ingressGVK)},
}}},
+17 -10
View File
@@ -25,6 +25,7 @@ import (
"strings"
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"
@@ -40,6 +41,7 @@ import (
clientset "github.com/jetstack/cert-manager/pkg/client/clientset/versioned"
cmlisters "github.com/jetstack/cert-manager/pkg/client/listers/certmanager/v1"
"github.com/jetstack/cert-manager/pkg/controller"
ingress "github.com/jetstack/cert-manager/pkg/internal/ingress"
logf "github.com/jetstack/cert-manager/pkg/logs"
"k8s.io/apimachinery/pkg/util/validation/field"
gwapi "sigs.k8s.io/gateway-api/apis/v1alpha1"
@@ -52,7 +54,8 @@ const (
reasonDeleteCertificate = "DeleteCertificate"
)
var ingressGVK = networkingv1beta1.SchemeGroupVersion.WithKind("Ingress")
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
@@ -88,7 +91,7 @@ func SyncFnFor(
// resource.
var autoAnnotations []string
switch ingLike.(type) {
case *networkingv1beta1.Ingress:
case *networkingv1.Ingress:
autoAnnotations = defaults.DefaultAutoCertificateAnnotations
}
@@ -152,7 +155,7 @@ func SyncFnFor(
func validateIngressLike(ingLike metav1.Object) field.ErrorList {
switch o := ingLike.(type) {
case *networkingv1beta1.Ingress:
case *networkingv1.Ingress:
return checkForDuplicateSecretNames(field.NewPath("spec", "tls"), o.Spec.TLS)
case *gwapi.Gateway:
return nil
@@ -161,7 +164,7 @@ func validateIngressLike(ingLike metav1.Object) field.ErrorList {
}
}
func checkForDuplicateSecretNames(path *field.Path, tlsBlocks []networkingv1beta1.IngressTLS) field.ErrorList {
func checkForDuplicateSecretNames(path *field.Path, tlsBlocks []networkingv1.IngressTLS) field.ErrorList {
var errs field.ErrorList
// We can't let two TLS blocks share the same secretName because we decided
// to create one Certificate for each TLS block. For example:
@@ -202,7 +205,7 @@ func checkForDuplicateSecretNames(path *field.Path, tlsBlocks []networkingv1beta
return errs
}
func validateIngressTLSBlock(path *field.Path, tlsBlock networkingv1beta1.IngressTLS) field.ErrorList {
func validateIngressTLSBlock(path *field.Path, tlsBlock networkingv1.IngressTLS) field.ErrorList {
var errs field.ErrorList
if len(tlsBlock.Hosts) == 0 {
@@ -273,7 +276,7 @@ func buildCertificates(
tlsHosts := make(map[corev1.ObjectReference][]string)
switch ingLike := ingLike.(type) {
case *networkingv1beta1.Ingress:
case *networkingv1.Ingress:
for i, tls := range ingLike.Spec.TLS {
path := field.NewPath("spec", "tls").Index(i)
err := validateIngressTLSBlock(path, tls).ToAggregate()
@@ -314,8 +317,12 @@ func buildCertificates(
var controllerGVK schema.GroupVersionKind
switch ingLike.(type) {
case *networkingv1beta1.Ingress:
controllerGVK = ingressGVK
case *networkingv1.Ingress:
if _, found := ingLike.GetAnnotations()[ingress.ConvertedGVKAnnotation]; found {
controllerGVK = ingressV1Beta1GVK
} else {
controllerGVK = ingressV1GVK
}
case *gwapi.Gateway:
controllerGVK = gatewayGVK
}
@@ -340,7 +347,7 @@ func buildCertificates(
}
switch o := ingLike.(type) {
case *networkingv1beta1.Ingress:
case *networkingv1.Ingress:
ingLike = o.DeepCopy()
case *gwapi.Gateway:
ingLike = o.DeepCopy()
@@ -410,7 +417,7 @@ func isUnrequiredCertificate(crt *cmapi.Certificate, ingLike metav1.Object) bool
}
switch o := ingLike.(type) {
case *networkingv1beta1.Ingress:
case *networkingv1.Ingress:
for _, tls := range o.Spec.TLS {
if crt.Spec.SecretName == tls.SecretName {
return false
+67 -67
View File
@@ -24,7 +24,7 @@ import (
"github.com/go-logr/logr"
"github.com/stretchr/testify/assert"
networkingv1beta1 "k8s.io/api/networking/v1beta1"
networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
@@ -97,7 +97,7 @@ func TestSync(t *testing.T) {
{
Name: "return a single Certificate for an ingress with a single valid TLS entry and common-name annotation",
Issuer: acmeClusterIssuer,
IngressLike: &networkingv1beta1.Ingress{
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
@@ -110,8 +110,8 @@ func TestSync(t *testing.T) {
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1beta1.IngressSpec{
TLS: []networkingv1beta1.IngressTLS{
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{"example.com", "www.example.com"},
SecretName: "example-com-tls",
@@ -147,7 +147,7 @@ func TestSync(t *testing.T) {
{
Name: "return a single HTTP01 Certificate for an ingress with a single valid TLS entry and HTTP01 annotations using edit-in-place",
Issuer: acmeClusterIssuer,
IngressLike: &networkingv1beta1.Ingress{
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
@@ -160,8 +160,8 @@ func TestSync(t *testing.T) {
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1beta1.IngressSpec{
TLS: []networkingv1beta1.IngressTLS{
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{"example.com", "www.example.com"},
SecretName: "example-com-tls",
@@ -200,7 +200,7 @@ func TestSync(t *testing.T) {
{
Name: "create a Certificate with the HTTP01 name override if the given ingress uses http01 annotations",
Issuer: gen.Issuer(acmeIssuer.Name),
IngressLike: &networkingv1beta1.Ingress{
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
@@ -213,8 +213,8 @@ func TestSync(t *testing.T) {
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1beta1.IngressSpec{
TLS: []networkingv1beta1.IngressTLS{
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{"example.com", "www.example.com"},
SecretName: "example-com-tls",
@@ -253,7 +253,7 @@ func TestSync(t *testing.T) {
{
Name: "return a single HTTP01 Certificate for an ingress with a single valid TLS entry and HTTP01 annotations with no ingress class set",
Issuer: acmeClusterIssuer,
IngressLike: &networkingv1beta1.Ingress{
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
@@ -262,8 +262,8 @@ func TestSync(t *testing.T) {
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1beta1.IngressSpec{
TLS: []networkingv1beta1.IngressTLS{
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{"example.com", "www.example.com"},
SecretName: "example-com-tls",
@@ -295,7 +295,7 @@ func TestSync(t *testing.T) {
{
Name: "return a single HTTP01 Certificate for an ingress with a single valid TLS entry and HTTP01 annotations with a custom ingress class",
Issuer: acmeClusterIssuer,
IngressLike: &networkingv1beta1.Ingress{
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
@@ -305,8 +305,8 @@ func TestSync(t *testing.T) {
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1beta1.IngressSpec{
TLS: []networkingv1beta1.IngressTLS{
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{"example.com", "www.example.com"},
SecretName: "example-com-tls",
@@ -338,7 +338,7 @@ func TestSync(t *testing.T) {
{
Name: "return a single HTTP01 Certificate for an ingress with a single valid TLS entry and HTTP01 annotations with a certificate ingress class",
Issuer: acmeClusterIssuer,
IngressLike: &networkingv1beta1.Ingress{
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
@@ -349,8 +349,8 @@ func TestSync(t *testing.T) {
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1beta1.IngressSpec{
TLS: []networkingv1beta1.IngressTLS{
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{"example.com", "www.example.com"},
SecretName: "example-com-tls",
@@ -385,7 +385,7 @@ func TestSync(t *testing.T) {
{
Name: "edit-in-place set to false should not trigger editing the ingress in-place",
Issuer: acmeClusterIssuer,
IngressLike: &networkingv1beta1.Ingress{
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
@@ -396,8 +396,8 @@ func TestSync(t *testing.T) {
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1beta1.IngressSpec{
TLS: []networkingv1beta1.IngressTLS{
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{"example.com", "www.example.com"},
SecretName: "example-com-tls",
@@ -429,7 +429,7 @@ func TestSync(t *testing.T) {
{
Name: "return a single DNS01 Certificate for an ingress with a single valid TLS entry",
Issuer: acmeClusterIssuer,
IngressLike: &networkingv1beta1.Ingress{
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
@@ -438,8 +438,8 @@ func TestSync(t *testing.T) {
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1beta1.IngressSpec{
TLS: []networkingv1beta1.IngressTLS{
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{"example.com", "www.example.com"},
SecretName: "example-com-tls",
@@ -475,7 +475,7 @@ func TestSync(t *testing.T) {
DefaultIssuerKind: "ClusterIssuer",
DefaultIssuerGroup: "cert-manager.io",
ClusterIssuerLister: []runtime.Object{clusterIssuer},
IngressLike: &networkingv1beta1.Ingress{
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
@@ -484,8 +484,8 @@ func TestSync(t *testing.T) {
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1beta1.IngressSpec{
TLS: []networkingv1beta1.IngressTLS{
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{"example.com", "www.example.com"},
SecretName: "example-com-tls",
@@ -522,7 +522,7 @@ func TestSync(t *testing.T) {
`Warning BadConfig Skipped a TLS block: spec.tls[0].hosts: Required value`,
`Normal CreateCertificate Successfully created Certificate "example-com-tls"`,
},
IngressLike: &networkingv1beta1.Ingress{
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
@@ -531,8 +531,8 @@ func TestSync(t *testing.T) {
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1beta1.IngressSpec{
TLS: []networkingv1beta1.IngressTLS{
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
SecretName: "example-com-tls-invalid",
},
@@ -571,7 +571,7 @@ func TestSync(t *testing.T) {
`Warning BadConfig Skipped a TLS block: spec.tls[0].secretName: Required value`,
`Normal CreateCertificate Successfully created Certificate "example-com-tls"`,
},
IngressLike: &networkingv1beta1.Ingress{
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
@@ -580,8 +580,8 @@ func TestSync(t *testing.T) {
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1beta1.IngressSpec{
TLS: []networkingv1beta1.IngressTLS{
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{"example.com"},
},
@@ -613,7 +613,7 @@ func TestSync(t *testing.T) {
},
{
Name: "should error if the specified issuer is not found",
IngressLike: &networkingv1beta1.Ingress{
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
@@ -628,7 +628,7 @@ func TestSync(t *testing.T) {
Name: "should not return any certificates if a correct Certificate already exists",
Issuer: acmeIssuer,
IssuerLister: []runtime.Object{acmeIssuer},
IngressLike: &networkingv1beta1.Ingress{
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
@@ -637,8 +637,8 @@ func TestSync(t *testing.T) {
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1beta1.IngressSpec{
TLS: []networkingv1beta1.IngressTLS{
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{"example.com"},
SecretName: "existing-crt",
@@ -672,7 +672,7 @@ func TestSync(t *testing.T) {
Name: "should update a certificate if an incorrect Certificate exists",
Issuer: acmeIssuer,
IssuerLister: []runtime.Object{acmeIssuer},
IngressLike: &networkingv1beta1.Ingress{
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
@@ -681,8 +681,8 @@ func TestSync(t *testing.T) {
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1beta1.IngressSpec{
TLS: []networkingv1beta1.IngressTLS{
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{"example.com"},
SecretName: "existing-crt",
@@ -721,7 +721,7 @@ func TestSync(t *testing.T) {
Name: "should update an existing Certificate resource with new labels if they do not match those specified on the IngressLike",
Issuer: acmeIssuer,
IssuerLister: []runtime.Object{acmeIssuerNewFormat},
IngressLike: &networkingv1beta1.Ingress{
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
@@ -733,8 +733,8 @@ func TestSync(t *testing.T) {
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1beta1.IngressSpec{
TLS: []networkingv1beta1.IngressTLS{
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{"example.com"},
SecretName: "cert-secret-name",
@@ -791,7 +791,7 @@ func TestSync(t *testing.T) {
Name: "should not update certificate if it does not belong to any ingress",
Issuer: acmeIssuer,
IssuerLister: []runtime.Object{acmeIssuer},
IngressLike: &networkingv1beta1.Ingress{
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
@@ -801,8 +801,8 @@ func TestSync(t *testing.T) {
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1beta1.IngressSpec{
TLS: []networkingv1beta1.IngressTLS{
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{"example.com"},
SecretName: "existing-crt",
@@ -833,7 +833,7 @@ func TestSync(t *testing.T) {
Name: "should not update certificate if it does not belong to the ingress",
Issuer: acmeIssuer,
IssuerLister: []runtime.Object{acmeIssuer},
IngressLike: &networkingv1beta1.Ingress{
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
@@ -843,8 +843,8 @@ func TestSync(t *testing.T) {
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1beta1.IngressSpec{
TLS: []networkingv1beta1.IngressTLS{
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{"example.com"},
SecretName: "existing-crt",
@@ -875,7 +875,7 @@ func TestSync(t *testing.T) {
Name: "should delete a Certificate if its SecretName is not present in the ingress",
Issuer: acmeIssuer,
IssuerLister: []runtime.Object{acmeIssuer},
IngressLike: &networkingv1beta1.Ingress{
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
@@ -926,7 +926,7 @@ func TestSync(t *testing.T) {
Name: "should update a Certificate if is contains a Common Name that is not defined on the ingress annotations",
Issuer: acmeIssuer,
IssuerLister: []runtime.Object{acmeIssuer},
IngressLike: &networkingv1beta1.Ingress{
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
@@ -937,8 +937,8 @@ func TestSync(t *testing.T) {
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1beta1.IngressSpec{
TLS: []networkingv1beta1.IngressTLS{
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{"example.com"},
SecretName: "example-com-tls",
@@ -994,7 +994,7 @@ func TestSync(t *testing.T) {
ExpectedEvents: []string{
`Warning BadConfig spec.tls[0].secretName: Invalid value: "example-com-tls": this secret name must only appear in a single TLS entry but is also used in spec.tls[1].secretName`,
},
IngressLike: &networkingv1beta1.Ingress{
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
@@ -1005,8 +1005,8 @@ func TestSync(t *testing.T) {
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1beta1.IngressSpec{
TLS: []networkingv1beta1.IngressTLS{
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{"example.com"},
SecretName: "example-com-tls",
@@ -1022,7 +1022,7 @@ func TestSync(t *testing.T) {
{
Name: "Failure to translateIngressAnnotations",
Issuer: acmeIssuer,
IngressLike: &networkingv1beta1.Ingress{
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
@@ -1034,8 +1034,8 @@ func TestSync(t *testing.T) {
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1beta1.IngressSpec{
TLS: []networkingv1beta1.IngressTLS{
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{"example.com"},
SecretName: "example-com-tls",
@@ -1048,7 +1048,7 @@ func TestSync(t *testing.T) {
{
Name: "return a single Certificate for an ingress with a single valid TLS entry with common-name and keyusage annotation",
Issuer: acmeClusterIssuer,
IngressLike: &networkingv1beta1.Ingress{
IngressLike: &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "ingress-name",
Namespace: gen.DefaultTestNamespace,
@@ -1062,8 +1062,8 @@ func TestSync(t *testing.T) {
},
UID: types.UID("ingress-name"),
},
Spec: networkingv1beta1.IngressSpec{
TLS: []networkingv1beta1.IngressTLS{
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{"example.com", "www.example.com"},
SecretName: "example-com-tls",
@@ -2484,7 +2484,7 @@ func (f *fakeHelper) GetGenericIssuer(ref cmmeta.ObjectReference, ns string) (cm
func TestIssuerForIngress(t *testing.T) {
type testT struct {
Ingress *networkingv1beta1.Ingress
Ingress *networkingv1.Ingress
DefaultName string
DefaultKind string
DefaultGroup string
@@ -2583,8 +2583,8 @@ func buildCertificate(name, namespace string, ownerReferences []metav1.OwnerRefe
}
}
func buildIngress(name, namespace string, annotations map[string]string) *networkingv1beta1.Ingress {
return &networkingv1beta1.Ingress{
func buildIngress(name, namespace string, annotations map[string]string) *networkingv1.Ingress {
return &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
@@ -2606,7 +2606,7 @@ func buildGateway(name, namespace string, annotations map[string]string) *gwapi.
func buildIngressOwnerReferences(name, namespace string) []metav1.OwnerReference {
return []metav1.OwnerReference{
*metav1.NewControllerRef(buildIngress(name, namespace, nil), ingressGVK),
*metav1.NewControllerRef(buildIngress(name, namespace, nil), ingressV1GVK),
}
}
+3
View File
@@ -21,6 +21,7 @@ import (
"time"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/client-go/discovery"
kubeinformers "k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
@@ -54,6 +55,8 @@ type Context struct {
CMClient clientset.Interface
// GWClient is a GatewayAPI clientset.
GWClient gwclient.Interface
// DiscoveryClient is a discovery interface. Usually set to Client.Discovery unless a fake client is in use.
DiscoveryClient discovery.DiscoveryInterface
// Recorder to record events to
Recorder record.EventRecorder
+2
View File
@@ -20,7 +20,9 @@ go_library(
"//pkg/logs:go_default_library",
"//pkg/metrics:go_default_library",
"//pkg/util:go_default_library",
"//test/unit/discovery:go_default_library",
"@com_github_kr_pretty//:go_default_library",
"@io_k8s_api//networking/v1:go_default_library",
"@io_k8s_apimachinery//pkg/apis/meta/v1:go_default_library",
"@io_k8s_apimachinery//pkg/runtime:go_default_library",
"@io_k8s_apimachinery//pkg/util/errors:go_default_library",
+25
View File
@@ -24,6 +24,7 @@ import (
"testing"
"time"
networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
@@ -43,6 +44,7 @@ import (
"github.com/jetstack/cert-manager/pkg/logs"
"github.com/jetstack/cert-manager/pkg/metrics"
"github.com/jetstack/cert-manager/pkg/util"
discoveryfake "github.com/jetstack/cert-manager/test/unit/discovery"
)
func init() {
@@ -111,6 +113,29 @@ func (b *Builder) Init() {
b.Client = kubefake.NewSimpleClientset(b.KubeObjects...)
b.CMClient = cmfake.NewSimpleClientset(b.CertManagerObjects...)
b.GWClient = gwfake.NewSimpleClientset(b.GWObjects...)
b.DiscoveryClient = discoveryfake.NewDiscovery().WithServerResourcesForGroupVersion(func(groupVersion string) (*metav1.APIResourceList, error) {
if groupVersion == networkingv1.SchemeGroupVersion.String() {
return &metav1.APIResourceList{
TypeMeta: metav1.TypeMeta{},
GroupVersion: networkingv1.SchemeGroupVersion.String(),
APIResources: []metav1.APIResource{
{
Name: "ingresses",
SingularName: "Ingress",
Namespaced: true,
Group: networkingv1.GroupName,
Version: networkingv1.SchemeGroupVersion.Version,
Kind: networkingv1.SchemeGroupVersion.WithKind("Ingress").Kind,
Verbs: metav1.Verbs{"get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"},
ShortNames: []string{"ing"},
Categories: []string{"all"},
StorageVersionHash: "testing",
},
},
}, nil
}
return &metav1.APIResourceList{}, nil
})
b.Recorder = new(FakeRecorder)
b.FakeKubeClient().PrependReactor("create", "*", b.generateNameReactor)
b.FakeCMClient().PrependReactor("create", "*", b.generateNameReactor)
+1
View File
@@ -14,6 +14,7 @@ filegroup(
"//pkg/internal/apis/acme:all-srcs",
"//pkg/internal/apis/certmanager:all-srcs",
"//pkg/internal/apis/meta:all-srcs",
"//pkg/internal/ingress:all-srcs",
"//pkg/internal/vault:all-srcs",
],
tags = ["automanaged"],
@@ -31,9 +31,9 @@ go_test(
embed = [":go_default_library"],
deps = [
"//pkg/internal/apis/certmanager:go_default_library",
"//pkg/internal/apis/certmanager/validation/plugins/fake:go_default_library",
"//pkg/internal/apis/meta:go_default_library",
"//pkg/webhook:go_default_library",
"//test/unit/discovery:go_default_library",
"@io_k8s_api//admission/v1:go_default_library",
"@io_k8s_api//authentication/v1:go_default_library",
"@io_k8s_api//authorization/v1:go_default_library",
@@ -55,10 +55,7 @@ filegroup(
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//pkg/internal/apis/certmanager/validation/plugins/fake:all-srcs",
],
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
@@ -33,9 +33,9 @@ import (
coretesting "k8s.io/client-go/testing"
internalcmapi "github.com/jetstack/cert-manager/pkg/internal/apis/certmanager"
pluginsfake "github.com/jetstack/cert-manager/pkg/internal/apis/certmanager/validation/plugins/fake"
internalcmmeta "github.com/jetstack/cert-manager/pkg/internal/apis/meta"
"github.com/jetstack/cert-manager/pkg/webhook"
discoveryfake "github.com/jetstack/cert-manager/test/unit/discovery"
)
var (
@@ -54,7 +54,7 @@ var (
}
expNoDiscovery = func(t *testing.T) discovery.DiscoveryInterface {
return pluginsfake.NewDiscovery().
return discoveryfake.NewDiscovery().
WithServerGroups(expNoServerGroups(t)).
WithServerResourcesForGroupVersion(expNoServerResourcesForGroupVersion(t))
}
@@ -147,7 +147,7 @@ func TestValidate(t *testing.T) {
newCR: approvedCR,
sarreaction: expNoSARReaction,
discoverclient: func(t *testing.T) discovery.DiscoveryInterface {
return pluginsfake.NewDiscovery().
return discoveryfake.NewDiscovery().
WithServerGroups(func() (*metav1.APIGroupList, error) {
return &metav1.APIGroupList{
Groups: []metav1.APIGroup{
@@ -175,7 +175,7 @@ func TestValidate(t *testing.T) {
oldCR: baseCR,
newCR: approvedCR,
discoverclient: func(t *testing.T) discovery.DiscoveryInterface {
return pluginsfake.NewDiscovery().
return discoveryfake.NewDiscovery().
WithServerGroups(func() (*metav1.APIGroupList, error) {
return &metav1.APIGroupList{
Groups: []metav1.APIGroup{
@@ -229,7 +229,7 @@ func TestValidate(t *testing.T) {
oldCR: baseCR,
newCR: approvedCR,
discoverclient: func(t *testing.T) discovery.DiscoveryInterface {
return pluginsfake.NewDiscovery().
return discoveryfake.NewDiscovery().
WithServerGroups(func() (*metav1.APIGroupList, error) {
return &metav1.APIGroupList{
Groups: []metav1.APIGroup{
@@ -683,7 +683,7 @@ func TestSignerResource(t *testing.T) {
},
client: func(t *testing.T) discovery.DiscoveryInterface {
return pluginsfake.NewDiscovery().
return discoveryfake.NewDiscovery().
WithServerGroups(func() (*metav1.APIGroupList, error) {
return nil, errors.New("this is an error")
}).
@@ -708,7 +708,7 @@ func TestSignerResource(t *testing.T) {
},
client: func(t *testing.T) discovery.DiscoveryInterface {
return pluginsfake.NewDiscovery().
return discoveryfake.NewDiscovery().
WithServerGroups(func() (*metav1.APIGroupList, error) {
return &metav1.APIGroupList{
Groups: []metav1.APIGroup{
@@ -738,7 +738,7 @@ func TestSignerResource(t *testing.T) {
},
client: func(t *testing.T) discovery.DiscoveryInterface {
return pluginsfake.NewDiscovery().
return discoveryfake.NewDiscovery().
WithServerGroups(func() (*metav1.APIGroupList, error) {
return &metav1.APIGroupList{
Groups: []metav1.APIGroup{
@@ -776,7 +776,7 @@ func TestSignerResource(t *testing.T) {
},
client: func(t *testing.T) discovery.DiscoveryInterface {
return pluginsfake.NewDiscovery().
return discoveryfake.NewDiscovery().
WithServerGroups(func() (*metav1.APIGroupList, error) {
return &metav1.APIGroupList{
Groups: []metav1.APIGroup{
@@ -824,7 +824,7 @@ func TestSignerResource(t *testing.T) {
},
client: func(t *testing.T) discovery.DiscoveryInterface {
return pluginsfake.NewDiscovery().
return discoveryfake.NewDiscovery().
WithServerGroups(func() (*metav1.APIGroupList, error) {
return &metav1.APIGroupList{
Groups: []metav1.APIGroup{
@@ -880,7 +880,7 @@ func TestSignerResource(t *testing.T) {
},
client: func(t *testing.T) discovery.DiscoveryInterface {
return pluginsfake.NewDiscovery().
return discoveryfake.NewDiscovery().
WithServerGroups(func() (*metav1.APIGroupList, error) {
return &metav1.APIGroupList{
Groups: []metav1.APIGroup{
+61
View File
@@ -0,0 +1,61 @@
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/jetstack/cert-manager/pkg/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 = ["ingress_test.go"],
embed = [":go_default_library"],
deps = [
"//pkg/controller:go_default_library",
"//test/unit/discovery: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_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"],
)
+341
View File
@@ -0,0 +1,341 @@
/*
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.
*/
func Convert_networking_Ingress_To_v1beta1_Ingress(in *networkingv1.Ingress, out *networkingv1beta1.Ingress, s conversion.Scope) error {
return autoConvert_networking_Ingress_To_v1beta1_Ingress(in, out, s)
}
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
}
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
}
+151
View File
@@ -0,0 +1,151 @@
/*
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
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/jetstack/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/<version>, 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))
}
+231
View File
@@ -0,0 +1,231 @@
/*
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/jetstack/cert-manager/pkg/controller"
discoveryfake "github.com/jetstack/cert-manager/test/unit/discovery"
)
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
}
+83
View File
@@ -0,0 +1,83 @@
/*
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)
}
+182
View File
@@ -0,0 +1,182 @@
/*
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)
}
+3 -4
View File
@@ -14,11 +14,12 @@ go_library(
"//pkg/apis/acme/v1:go_default_library",
"//pkg/apis/certmanager/v1:go_default_library",
"//pkg/controller:go_default_library",
"//pkg/internal/ingress:go_default_library",
"//pkg/issuer/acme/http/solver:go_default_library",
"//pkg/logs:go_default_library",
"//pkg/util:go_default_library",
"@io_k8s_api//core/v1:go_default_library",
"@io_k8s_api//networking/v1beta1:go_default_library",
"@io_k8s_api//networking/v1: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",
@@ -26,7 +27,6 @@ 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/v1beta1:go_default_library",
"@io_k8s_utils//net:go_default_library",
"@io_k8s_utils//pointer:go_default_library",
],
@@ -47,13 +47,12 @@ go_test(
"//pkg/controller/test:go_default_library",
"//test/unit/gen:go_default_library",
"@io_k8s_api//core/v1:go_default_library",
"@io_k8s_api//networking/v1beta1:go_default_library",
"@io_k8s_api//networking/v1: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",
"@io_k8s_apimachinery//pkg/runtime:go_default_library",
"@io_k8s_apimachinery//pkg/util/diff:go_default_library",
"@io_k8s_apimachinery//pkg/util/intstr:go_default_library",
"@io_k8s_client_go//testing:go_default_library",
],
)
+23 -14
View File
@@ -31,11 +31,11 @@ import (
utilerrors "k8s.io/apimachinery/pkg/util/errors"
corev1listers "k8s.io/client-go/listers/core/v1"
networkingv1beta1listers "k8s.io/client-go/listers/networking/v1beta1"
cmacme "github.com/jetstack/cert-manager/pkg/apis/acme/v1"
v1 "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1"
"github.com/jetstack/cert-manager/pkg/controller"
"github.com/jetstack/cert-manager/pkg/internal/ingress"
"github.com/jetstack/cert-manager/pkg/issuer/acme/http/solver"
logf "github.com/jetstack/cert-manager/pkg/logs"
pkgutil "github.com/jetstack/cert-manager/pkg/util"
@@ -57,9 +57,10 @@ var (
type Solver struct {
*controller.Context
podLister corev1listers.PodLister
serviceLister corev1listers.ServiceLister
ingressLister networkingv1beta1listers.IngressLister
podLister corev1listers.PodLister
serviceLister corev1listers.ServiceLister
ingressLister ingress.InternalIngressLister
ingressCreateUpdater ingress.InternalIngressCreateUpdater
testReachability reachabilityTest
requiredPasses int
@@ -67,17 +68,25 @@ type Solver struct {
type reachabilityTest func(ctx context.Context, url *url.URL, key string) error
// NewSolver returns a new ACME HTTP01 solver for the given Issuer and client.
// TODO: refactor this to have fewer args
func NewSolver(ctx *controller.Context) *Solver {
return &Solver{
Context: ctx,
podLister: ctx.KubeSharedInformerFactory.Core().V1().Pods().Lister(),
serviceLister: ctx.KubeSharedInformerFactory.Core().V1().Services().Lister(),
ingressLister: ctx.KubeSharedInformerFactory.Networking().V1beta1().Ingresses().Lister(),
testReachability: testReachability,
requiredPasses: 5,
// 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,
testReachability: testReachability,
requiredPasses: 5,
}, nil
}
func http01LogCtx(ctx context.Context) context.Context {
+45 -39
View File
@@ -21,13 +21,12 @@ import (
"fmt"
"net"
networkingv1beta1 "k8s.io/api/networking/v1beta1"
networkingv1 "k8s.io/api/networking/v1"
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/selection"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/intstr"
cmacme "github.com/jetstack/cert-manager/pkg/apis/acme/v1"
cmapi "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1"
@@ -37,7 +36,7 @@ import (
// getIngressesForChallenge returns a list of Ingresses that were created to solve
// http challenges for the given domain
func (s *Solver) getIngressesForChallenge(ctx context.Context, ch *cmacme.Challenge) ([]*networkingv1beta1.Ingress, error) {
func (s *Solver) getIngressesForChallenge(ctx context.Context, ch *cmacme.Challenge) ([]*networkingv1.Ingress, error) {
log := logf.FromContext(ctx)
podLabels := podLabels(ch)
@@ -56,7 +55,7 @@ func (s *Solver) getIngressesForChallenge(ctx context.Context, ch *cmacme.Challe
return nil, err
}
var relevantIngresses []*networkingv1beta1.Ingress
var relevantIngresses []*networkingv1.Ingress
for _, ingress := range ingressList {
if !metav1.IsControlledBy(ingress, ch) {
logf.WithRelatedResource(log, ingress).Info("found existing solver ingress for this challenge resource, however " +
@@ -72,7 +71,7 @@ func (s *Solver) getIngressesForChallenge(ctx context.Context, ch *cmacme.Challe
// ensureIngress will ensure the ingress required to solve this challenge
// exists, or if an existing ingress is specified on the secret will ensure
// that the ingress has an appropriate challenge path configured
func (s *Solver) ensureIngress(ctx context.Context, ch *cmacme.Challenge, svcName string) (ing *networkingv1beta1.Ingress, err error) {
func (s *Solver) ensureIngress(ctx context.Context, ch *cmacme.Challenge, svcName string) (ing *networkingv1.Ingress, err error) {
log := logf.FromContext(ctx).WithName("ensureIngress")
httpDomainCfg, err := httpDomainCfgForChallenge(ch)
if err != nil {
@@ -113,13 +112,13 @@ func (s *Solver) ensureIngress(ctx context.Context, ch *cmacme.Challenge, svcNam
return s.createIngress(ctx, ch, svcName)
}
func ingressServiceName(ing *networkingv1beta1.Ingress) string {
return ing.Spec.Rules[0].HTTP.Paths[0].Backend.ServiceName
func ingressServiceName(ing *networkingv1.Ingress) string {
return ing.Spec.Rules[0].HTTP.Paths[0].Backend.Service.Name
}
// createIngress will create a challenge solving ingress for the given certificate,
// domain, token and key.
func (s *Solver) createIngress(ctx context.Context, ch *cmacme.Challenge, svcName string) (*networkingv1beta1.Ingress, error) {
func (s *Solver) createIngress(ctx context.Context, ch *cmacme.Challenge, svcName string) (*networkingv1.Ingress, error) {
ing, err := buildIngressResource(ch, svcName)
if err != nil {
return nil, err
@@ -131,10 +130,10 @@ func (s *Solver) createIngress(ctx context.Context, ch *cmacme.Challenge, svcNam
ing = s.mergeIngressObjectMetaWithIngressResourceTemplate(ing, ch.Spec.Solver.HTTP01.Ingress.IngressTemplate)
}
return s.Client.NetworkingV1beta1().Ingresses(ch.Namespace).Create(ctx, ing, metav1.CreateOptions{})
return s.ingressCreateUpdater.Ingresses(ch.Namespace).Create(ctx, ing, metav1.CreateOptions{})
}
func buildIngressResource(ch *cmacme.Challenge, svcName string) (*networkingv1beta1.Ingress, error) {
func buildIngressResource(ch *cmacme.Challenge, svcName string) (*networkingv1.Ingress, error) {
httpDomainCfg, err := httpDomainCfgForChallenge(ch)
if err != nil {
return nil, err
@@ -162,7 +161,7 @@ func buildIngressResource(ch *cmacme.Challenge, svcName string) (*networkingv1be
if net.ParseIP(httpHost) != nil {
httpHost = ""
}
return &networkingv1beta1.Ingress{
return &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "cm-acme-http-solver-",
Namespace: ch.Namespace,
@@ -170,13 +169,15 @@ func buildIngressResource(ch *cmacme.Challenge, svcName string) (*networkingv1be
Annotations: ingAnnotations,
OwnerReferences: []metav1.OwnerReference{*metav1.NewControllerRef(ch, challengeGvk)},
},
Spec: networkingv1beta1.IngressSpec{
Rules: []networkingv1beta1.IngressRule{
Spec: networkingv1.IngressSpec{
Rules: []networkingv1.IngressRule{
{
Host: httpHost,
IngressRuleValue: networkingv1beta1.IngressRuleValue{
HTTP: &networkingv1beta1.HTTPIngressRuleValue{
Paths: []networkingv1beta1.HTTPIngressPath{ingPathToAdd},
IngressRuleValue: networkingv1.IngressRuleValue{
HTTP: &networkingv1.HTTPIngressRuleValue{
Paths: []networkingv1.HTTPIngressPath{
ingPathToAdd,
},
},
},
},
@@ -186,7 +187,7 @@ func buildIngressResource(ch *cmacme.Challenge, svcName string) (*networkingv1be
}
// Merge object meta from the ingress template. Fall back to default values.
func (s *Solver) mergeIngressObjectMetaWithIngressResourceTemplate(ingress *networkingv1beta1.Ingress, ingressTempl *cmacme.ACMEChallengeSolverHTTP01IngressTemplate) *networkingv1beta1.Ingress {
func (s *Solver) mergeIngressObjectMetaWithIngressResourceTemplate(ingress *networkingv1.Ingress, ingressTempl *cmacme.ACMEChallengeSolverHTTP01IngressTemplate) *networkingv1.Ingress {
if ingressTempl == nil {
return ingress
}
@@ -210,7 +211,7 @@ func (s *Solver) mergeIngressObjectMetaWithIngressResourceTemplate(ingress *netw
return ingress
}
func (s *Solver) addChallengePathToIngress(ctx context.Context, ch *cmacme.Challenge, svcName string) (*networkingv1beta1.Ingress, error) {
func (s *Solver) addChallengePathToIngress(ctx context.Context, ch *cmacme.Challenge, svcName string) (*networkingv1.Ingress, error) {
httpDomainCfg, err := httpDomainCfgForChallenge(ch)
if err != nil {
return nil, err
@@ -227,36 +228,36 @@ func (s *Solver) addChallengePathToIngress(ctx context.Context, ch *cmacme.Chall
for _, rule := range ing.Spec.Rules {
if rule.Host == ch.Spec.DNSName {
if rule.HTTP == nil {
rule.HTTP = &networkingv1beta1.HTTPIngressRuleValue{}
rule.HTTP = &networkingv1.HTTPIngressRuleValue{}
}
for i, p := range rule.HTTP.Paths {
// if an existing path exists on this rule for the challenge path,
// we overwrite it else we'll confuse ingress controllers
if p.Path == ingPathToAdd.Path {
// ingress resource is already up to date
if p.Backend.ServiceName == ingPathToAdd.Backend.ServiceName &&
p.Backend.ServicePort == ingPathToAdd.Backend.ServicePort {
if p.Backend.Service.Name == ingPathToAdd.Backend.Service.Name &&
p.Backend.Service.Port == ingPathToAdd.Backend.Service.Port {
return ing, nil
}
rule.HTTP.Paths[i] = ingPathToAdd
return s.Client.NetworkingV1beta1().Ingresses(ing.Namespace).Update(ctx, ing, metav1.UpdateOptions{})
return s.ingressCreateUpdater.Ingresses(ing.Namespace).Update(ctx, ing, metav1.UpdateOptions{})
}
}
rule.HTTP.Paths = append([]networkingv1beta1.HTTPIngressPath{ingPathToAdd}, rule.HTTP.Paths...)
return s.Client.NetworkingV1beta1().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{})
}
}
// if one doesn't exist, create a new IngressRule
ing.Spec.Rules = append(ing.Spec.Rules, networkingv1beta1.IngressRule{
ing.Spec.Rules = append(ing.Spec.Rules, networkingv1.IngressRule{
Host: ch.Spec.DNSName,
IngressRuleValue: networkingv1beta1.IngressRuleValue{
HTTP: &networkingv1beta1.HTTPIngressRuleValue{
Paths: []networkingv1beta1.HTTPIngressPath{ingPathToAdd},
IngressRuleValue: networkingv1.IngressRuleValue{
HTTP: &networkingv1.HTTPIngressRuleValue{
Paths: []networkingv1.HTTPIngressPath{ingPathToAdd},
},
},
})
return s.Client.NetworkingV1beta1().Ingresses(ing.Namespace).Update(ctx, ing, metav1.UpdateOptions{})
return s.ingressCreateUpdater.Ingresses(ing.Namespace).Update(ctx, ing, metav1.UpdateOptions{})
}
// cleanupIngresses will remove the rules added by cert-manager to an existing
@@ -283,7 +284,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.Client.NetworkingV1beta1().Ingresses(ingress.Namespace).Delete(ctx, ingress.Name, metav1.DeleteOptions{})
err := s.ingressCreateUpdater.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)
@@ -295,7 +296,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.Client.NetworkingV1beta1().Ingresses(ch.Namespace).Get(ctx, existingIngressName, metav1.GetOptions{})
ing, err := s.ingressCreateUpdater.Ingresses(ch.Namespace).Get(ctx, existingIngressName, metav1.GetOptions{})
if k8sErrors.IsNotFound(err) {
log.Error(err, "named ingress resource not found, skipping cleanup")
return nil
@@ -307,7 +308,7 @@ func (s *Solver) cleanupIngresses(ctx context.Context, ch *cmacme.Challenge) err
log.V(logf.DebugLevel).Info("attempting to clean up automatically added solver paths on ingress resource")
ingPathToDel := solverPathFn(ch.Spec.Token)
var ingRules []networkingv1beta1.IngressRule
var ingRules []networkingv1.IngressRule
for _, rule := range ing.Spec.Rules {
// always retain rules that are not for the same DNSName
if rule.Host != ch.Spec.DNSName {
@@ -338,7 +339,7 @@ func (s *Solver) cleanupIngresses(ctx context.Context, ch *cmacme.Challenge) err
ing.Spec.Rules = ingRules
_, err = s.Client.NetworkingV1beta1().Ingresses(ing.Namespace).Update(ctx, ing, metav1.UpdateOptions{})
_, err = s.ingressCreateUpdater.Ingresses(ing.Namespace).Update(ctx, ing, metav1.UpdateOptions{})
if err != nil {
return err
}
@@ -350,12 +351,17 @@ func (s *Solver) cleanupIngresses(ctx context.Context, ch *cmacme.Challenge) err
// ingressPath returns the ingress HTTPIngressPath object needed to solve this
// challenge.
func ingressPath(token, serviceName string) networkingv1beta1.HTTPIngressPath {
return networkingv1beta1.HTTPIngressPath{
Path: solverPathFn(token),
Backend: networkingv1beta1.IngressBackend{
ServiceName: serviceName,
ServicePort: intstr.FromInt(acmeSolverListenPort),
func ingressPath(token, serviceName string) networkingv1.HTTPIngressPath {
return networkingv1.HTTPIngressPath{
Path: solverPathFn(token),
PathType: func() *networkingv1.PathType { s := networkingv1.PathTypeExact; return &s }(),
Backend: networkingv1.IngressBackend{
Service: &networkingv1.IngressServiceBackend{
Name: serviceName,
Port: networkingv1.ServiceBackendPort{
Number: acmeSolverListenPort,
},
},
},
}
}
+67 -48
View File
@@ -22,13 +22,12 @@ import (
"reflect"
"testing"
"k8s.io/api/networking/v1beta1"
"k8s.io/api/networking/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/apimachinery/pkg/util/intstr"
coretesting "k8s.io/client-go/testing"
cmacme "github.com/jetstack/cert-manager/pkg/apis/acme/v1"
@@ -59,8 +58,8 @@ func TestGetIngressesForChallenge(t *testing.T) {
s.Builder.Sync()
},
CheckFn: func(t *testing.T, s *solverFixture, args ...interface{}) {
createdIngress := s.testResources[createdIngressKey].(*v1beta1.Ingress)
resp := args[0].([]*v1beta1.Ingress)
createdIngress := s.testResources[createdIngressKey].(*v1.Ingress)
resp := args[0].([]*v1.Ingress)
if len(resp) != 1 {
t.Errorf("expected one ingress to be returned, but got %d", len(resp))
t.Fail()
@@ -92,8 +91,8 @@ func TestGetIngressesForChallenge(t *testing.T) {
s.Builder.Sync()
},
CheckFn: func(t *testing.T, s *solverFixture, args ...interface{}) {
createdIngress := s.testResources[createdIngressKey].(*v1beta1.Ingress)
resp := args[0].([]*v1beta1.Ingress)
createdIngress := s.testResources[createdIngressKey].(*v1.Ingress)
resp := args[0].([]*v1.Ingress)
if len(resp) != 1 {
t.Errorf("expected one ingress to be returned, but got %d", len(resp))
t.Fail()
@@ -126,7 +125,7 @@ func TestGetIngressesForChallenge(t *testing.T) {
s.Builder.Sync()
},
CheckFn: func(t *testing.T, s *solverFixture, args ...interface{}) {
resp := args[0].([]*v1beta1.Ingress)
resp := args[0].([]*v1.Ingress)
if len(resp) != 0 {
t.Errorf("expected zero ingresses to be returned, but got %d", len(resp))
t.Fail()
@@ -176,8 +175,8 @@ func TestCleanupIngresses(t *testing.T) {
s.Builder.Sync()
},
CheckFn: func(t *testing.T, s *solverFixture, args ...interface{}) {
createdIngress := s.testResources[createdIngressKey].(*v1beta1.Ingress)
ing, err := s.Builder.FakeKubeClient().NetworkingV1beta1().Ingresses(s.Challenge.Namespace).Get(context.TODO(), createdIngress.Name, metav1.GetOptions{})
createdIngress := s.testResources[createdIngressKey].(*v1.Ingress)
ing, err := s.Builder.FakeKubeClient().NetworkingV1().Ingresses(s.Challenge.Namespace).Get(context.TODO(), createdIngress.Name, metav1.GetOptions{})
if err != nil && !apierrors.IsNotFound(err) {
t.Errorf("error when getting test ingress, expected 'not found' but got: %v", err)
}
@@ -210,8 +209,8 @@ func TestCleanupIngresses(t *testing.T) {
s.testResources[createdIngressKey] = ing
},
CheckFn: func(t *testing.T, s *solverFixture, args ...interface{}) {
createdIngress := s.testResources[createdIngressKey].(*v1beta1.Ingress)
_, err := s.Builder.FakeKubeClient().NetworkingV1beta1().Ingresses(s.Challenge.Namespace).Get(context.TODO(), createdIngress.Name, metav1.GetOptions{})
createdIngress := s.testResources[createdIngressKey].(*v1.Ingress)
_, err := s.Builder.FakeKubeClient().NetworkingV1().Ingresses(s.Challenge.Namespace).Get(context.TODO(), createdIngress.Name, metav1.GetOptions{})
if apierrors.IsNotFound(err) {
t.Errorf("expected ingress resource %q to not be deleted, but it was deleted", createdIngress.Name)
}
@@ -223,27 +222,35 @@ func TestCleanupIngresses(t *testing.T) {
"should clean up an ingress with a single challenge path inserted": {
Builder: &test.Builder{
KubeObjects: []runtime.Object{
&v1beta1.Ingress{
&v1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "testingress",
Namespace: defaultTestNamespace,
},
Spec: v1beta1.IngressSpec{
Backend: &v1beta1.IngressBackend{
ServiceName: "testsvc",
ServicePort: intstr.FromInt(8080),
Spec: v1.IngressSpec{
DefaultBackend: &v1.IngressBackend{
Service: &v1.IngressServiceBackend{
Name: "",
Port: v1.ServiceBackendPort{
Number: 8080,
},
},
},
Rules: []v1beta1.IngressRule{
Rules: []v1.IngressRule{
{
Host: "example.com",
IngressRuleValue: v1beta1.IngressRuleValue{
HTTP: &v1beta1.HTTPIngressRuleValue{
Paths: []v1beta1.HTTPIngressPath{
IngressRuleValue: v1.IngressRuleValue{
HTTP: &v1.HTTPIngressRuleValue{
Paths: []v1.HTTPIngressPath{
{
Path: "/.well-known/acme-challenge/abcd",
Backend: v1beta1.IngressBackend{
ServiceName: "solversvc",
ServicePort: intstr.FromInt(8081),
Backend: v1.IngressBackend{
Service: &v1.IngressServiceBackend{
Name: "solversvc",
Port: v1.ServiceBackendPort{
Number: 8081,
},
},
},
},
},
@@ -275,10 +282,10 @@ func TestCleanupIngresses(t *testing.T) {
PreFn: func(t *testing.T, s *solverFixture) {
},
CheckFn: func(t *testing.T, s *solverFixture, args ...interface{}) {
expectedIng := s.KubeObjects[0].(*v1beta1.Ingress).DeepCopy()
expectedIng := s.KubeObjects[0].(*v1.Ingress).DeepCopy()
expectedIng.Spec.Rules = nil
actualIng, err := s.Builder.FakeKubeClient().NetworkingV1beta1().Ingresses(s.Challenge.Namespace).Get(context.TODO(), expectedIng.Name, metav1.GetOptions{})
actualIng, err := s.Builder.FakeKubeClient().NetworkingV1().Ingresses(s.Challenge.Namespace).Get(context.TODO(), expectedIng.Name, metav1.GetOptions{})
if apierrors.IsNotFound(err) {
t.Errorf("expected ingress resource %q to not be deleted, but it was deleted", expectedIng.Name)
}
@@ -294,27 +301,35 @@ func TestCleanupIngresses(t *testing.T) {
"should clean up an ingress with a single challenge path inserted without removing second HTTP rule": {
Builder: &test.Builder{
KubeObjects: []runtime.Object{
&v1beta1.Ingress{
&v1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: "testingress",
Namespace: defaultTestNamespace,
},
Spec: v1beta1.IngressSpec{
Backend: &v1beta1.IngressBackend{
ServiceName: "testsvc",
ServicePort: intstr.FromInt(8080),
Spec: v1.IngressSpec{
DefaultBackend: &v1.IngressBackend{
Service: &v1.IngressServiceBackend{
Name: "testsvc",
Port: v1.ServiceBackendPort{
Number: 8080,
},
},
},
Rules: []v1beta1.IngressRule{
Rules: []v1.IngressRule{
{
Host: "example.com",
IngressRuleValue: v1beta1.IngressRuleValue{
HTTP: &v1beta1.HTTPIngressRuleValue{
Paths: []v1beta1.HTTPIngressPath{
IngressRuleValue: v1.IngressRuleValue{
HTTP: &v1.HTTPIngressRuleValue{
Paths: []v1.HTTPIngressPath{
{
Path: "/.well-known/acme-challenge/abcd",
Backend: v1beta1.IngressBackend{
ServiceName: "solversvc",
ServicePort: intstr.FromInt(8081),
Backend: v1.IngressBackend{
Service: &v1.IngressServiceBackend{
Name: "solversvc",
Port: v1.ServiceBackendPort{
Number: 8081,
},
},
},
},
},
@@ -323,14 +338,18 @@ func TestCleanupIngresses(t *testing.T) {
},
{
Host: "a.example.com",
IngressRuleValue: v1beta1.IngressRuleValue{
HTTP: &v1beta1.HTTPIngressRuleValue{
Paths: []v1beta1.HTTPIngressPath{
IngressRuleValue: v1.IngressRuleValue{
HTTP: &v1.HTTPIngressRuleValue{
Paths: []v1.HTTPIngressPath{
{
Path: "/",
Backend: v1beta1.IngressBackend{
ServiceName: "real-backend-svc",
ServicePort: intstr.FromInt(8081),
Backend: v1.IngressBackend{
Service: &v1.IngressServiceBackend{
Name: "real-backend-svc",
Port: v1.ServiceBackendPort{
Number: 8081,
},
},
},
},
},
@@ -362,10 +381,10 @@ func TestCleanupIngresses(t *testing.T) {
PreFn: func(t *testing.T, s *solverFixture) {
},
CheckFn: func(t *testing.T, s *solverFixture, args ...interface{}) {
expectedIng := s.KubeObjects[0].(*v1beta1.Ingress).DeepCopy()
expectedIng.Spec.Rules = []v1beta1.IngressRule{expectedIng.Spec.Rules[1]}
expectedIng := s.KubeObjects[0].(*v1.Ingress).DeepCopy()
expectedIng.Spec.Rules = []v1.IngressRule{expectedIng.Spec.Rules[1]}
actualIng, err := s.Builder.FakeKubeClient().NetworkingV1beta1().Ingresses(s.Challenge.Namespace).Get(context.TODO(), expectedIng.Name, metav1.GetOptions{})
actualIng, err := s.Builder.FakeKubeClient().NetworkingV1().Ingresses(s.Challenge.Namespace).Get(context.TODO(), expectedIng.Name, metav1.GetOptions{})
if apierrors.IsNotFound(err) {
t.Errorf("expected ingress resource %q to not be deleted, but it was deleted", expectedIng.Name)
}
@@ -520,9 +539,9 @@ func TestMergeIngressObjectMetaWithIngressResourceTemplate(t *testing.T) {
s.Builder.Sync()
},
CheckFn: func(t *testing.T, s *solverFixture, args ...interface{}) {
expectedIngress := s.testResources[createdIngressKey].(*v1beta1.Ingress)
expectedIngress := s.testResources[createdIngressKey].(*v1.Ingress)
resp, ok := args[0].(*v1beta1.Ingress)
resp, ok := args[0].(*v1.Ingress)
if !ok {
t.Errorf("expected ingress to be returned, but got %v", args[0])
t.Fail()
+11 -4
View File
@@ -63,7 +63,11 @@ func (s *solverFixture) Setup(t *testing.T) {
s.Builder.T = t
}
s.Builder.Init()
s.Solver = buildFakeSolver(s.Builder)
var err error
s.Solver, err = buildFakeSolver(s.Builder)
if err != nil {
t.Fatal(err)
}
if s.PreFn != nil {
s.PreFn(t, s)
s.Builder.Sync()
@@ -80,11 +84,14 @@ func (s *solverFixture) Finish(t *testing.T, args ...interface{}) {
}
}
func buildFakeSolver(b *test.Builder) *Solver {
func buildFakeSolver(b *test.Builder) (*Solver, error) {
b.Init()
s := NewSolver(b.Context)
s, err := NewSolver(b.Context)
if err != nil {
return nil, err
}
b.Start()
return s
return s, nil
}
func strPtr(s string) *string {
@@ -21,6 +21,8 @@ go_library(
"@com_github_onsi_ginkgo//:go_default_library",
"@com_github_onsi_gomega//: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/types:go_default_library",
"@io_k8s_client_go//util/retry:go_default_library",
@@ -24,6 +24,8 @@ import (
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
networkingv1beta1 "k8s.io/api/networking/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/util/retry"
@@ -641,20 +643,38 @@ func (s *Suite) Define() {
}, featureset.ReusePrivateKeyFeature, featureset.OnlySAN)
s.it(f, "should issue a certificate for a single distinct DNS Name defined by an ingress with annotations", func(issuerRef cmmeta.ObjectReference) {
ingClient := f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace.Name)
var certName string
switch {
case e2eutil.HasIngresses(f.KubeClientSet.Discovery(), networkingv1.SchemeGroupVersion.String()):
ingClient := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace.Name)
name := "testcert-ingress"
secretName := "testcert-ingress-tls"
name := "testcert-ingress"
secretName := "testcert-ingress-tls"
By("Creating an Ingress with the issuer name annotation set")
ingress, err := ingClient.Create(context.TODO(), e2eutil.NewIngress(name, secretName, map[string]string{
"cert-manager.io/issuer": issuerRef.Name,
"cert-manager.io/issuer-kind": issuerRef.Kind,
"cert-manager.io/issuer-group": issuerRef.Group,
}, e2eutil.RandomSubdomain(s.DomainSuffix)), metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
By("Creating an Ingress with the issuer name annotation set")
ingress, err := ingClient.Create(context.TODO(), e2eutil.NewIngress(name, secretName, map[string]string{
"cert-manager.io/issuer": issuerRef.Name,
"cert-manager.io/issuer-kind": issuerRef.Kind,
"cert-manager.io/issuer-group": issuerRef.Group,
}, e2eutil.RandomSubdomain(s.DomainSuffix)), metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
certName = ingress.Spec.TLS[0].SecretName
case e2eutil.HasIngresses(f.KubeClientSet.Discovery(), networkingv1beta1.SchemeGroupVersion.String()):
ingClient := f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace.Name)
name := "testcert-ingress"
secretName := "testcert-ingress-tls"
certName := ingress.Spec.TLS[0].SecretName
By("Creating an Ingress with the issuer name annotation set")
ingress, err := ingClient.Create(context.TODO(), e2eutil.NewV1Beta1Ingress(name, secretName, map[string]string{
"cert-manager.io/issuer": issuerRef.Name,
"cert-manager.io/issuer-kind": issuerRef.Kind,
"cert-manager.io/issuer-group": issuerRef.Group,
}, e2eutil.RandomSubdomain(s.DomainSuffix)), metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
certName = ingress.Spec.TLS[0].SecretName
default:
Fail("Neither " + networkingv1.SchemeGroupVersion.String() + " nor " + networkingv1beta1.SchemeGroupVersion.String() + " were discovered in the API server")
}
By("Waiting for the Certificate to exist...")
Expect(e2eutil.WaitForCertificateToExist(
@@ -662,7 +682,7 @@ func (s *Suite) Define() {
)).NotTo(HaveOccurred())
By("Waiting for the Certificate to be issued...")
_, err = f.Helper().WaitForCertificateReady(f.Namespace.Name, certName, time.Minute*5)
_, err := f.Helper().WaitForCertificateReady(f.Namespace.Name, certName, time.Minute*5)
Expect(err).NotTo(HaveOccurred())
By("Validating the issued Certificate...")
@@ -671,26 +691,51 @@ func (s *Suite) Define() {
}, featureset.OnlySAN)
s.it(f, "should issue a certificate defined by an ingress with certificate field annotations", func(issuerRef cmmeta.ObjectReference) {
ingClient := f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace.Name)
name := "testcert-ingress"
secretName := "testcert-ingress-tls"
var certName string
domain := e2eutil.RandomSubdomain(s.DomainSuffix)
duration := time.Hour * 999
renewBefore := time.Hour * 111
By("Creating an Ingress with annotations for issuerRef and other Certificate fields")
ingress, err := ingClient.Create(context.TODO(), e2eutil.NewIngress(name, secretName, map[string]string{
"cert-manager.io/issuer": issuerRef.Name,
"cert-manager.io/issuer-kind": issuerRef.Kind,
"cert-manager.io/issuer-group": issuerRef.Group,
"cert-manager.io/common-name": domain,
"cert-manager.io/duration": duration.String(),
"cert-manager.io/renew-before": renewBefore.String(),
}, domain), metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
switch {
case e2eutil.HasIngresses(f.KubeClientSet.Discovery(), networkingv1.SchemeGroupVersion.String()):
ingClient := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace.Name)
certName := ingress.Spec.TLS[0].SecretName
name := "testcert-ingress"
secretName := "testcert-ingress-tls"
By("Creating an Ingress with annotations for issuerRef and other Certificate fields")
ingress, err := ingClient.Create(context.TODO(), e2eutil.NewIngress(name, secretName, map[string]string{
"cert-manager.io/issuer": issuerRef.Name,
"cert-manager.io/issuer-kind": issuerRef.Kind,
"cert-manager.io/issuer-group": issuerRef.Group,
"cert-manager.io/common-name": domain,
"cert-manager.io/duration": duration.String(),
"cert-manager.io/renew-before": renewBefore.String(),
}, domain), metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
certName = ingress.Spec.TLS[0].SecretName
case e2eutil.HasIngresses(f.KubeClientSet.Discovery(), networkingv1beta1.SchemeGroupVersion.String()):
ingClient := f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace.Name)
name := "testcert-ingress"
secretName := "testcert-ingress-tls"
By("Creating an Ingress with annotations for issuerRef and other Certificate fields")
ingress, err := ingClient.Create(context.TODO(), e2eutil.NewV1Beta1Ingress(name, secretName, map[string]string{
"cert-manager.io/issuer": issuerRef.Name,
"cert-manager.io/issuer-kind": issuerRef.Kind,
"cert-manager.io/issuer-group": issuerRef.Group,
"cert-manager.io/common-name": domain,
"cert-manager.io/duration": duration.String(),
"cert-manager.io/renew-before": renewBefore.String(),
}, domain), metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
certName = ingress.Spec.TLS[0].SecretName
default:
Fail("Neither " + networkingv1.SchemeGroupVersion.String() + " nor " + networkingv1beta1.SchemeGroupVersion.String() + " were discovered in the API server")
}
By("Waiting for the Certificate to exist...")
Expect(e2eutil.WaitForCertificateToExist(
@@ -698,7 +743,7 @@ func (s *Suite) Define() {
)).NotTo(HaveOccurred())
By("Waiting for the Certificate to be issued...")
_, err = f.Helper().WaitForCertificateReady(f.Namespace.Name, certName, time.Minute*5)
_, err := f.Helper().WaitForCertificateReady(f.Namespace.Name, certName, time.Minute*5)
Expect(err).NotTo(HaveOccurred())
// Verify that the ingres-shim has translated all the supplied
@@ -26,11 +26,14 @@ go_library(
"@com_github_onsi_ginkgo//:go_default_library",
"@com_github_onsi_gomega//: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_apiextensions_apiserver//pkg/apis/apiextensions/v1beta1:go_default_library",
"@io_k8s_apimachinery//pkg/apis/meta/v1:go_default_library",
"@io_k8s_apimachinery//pkg/util/intstr:go_default_library",
"@io_k8s_apimachinery//pkg/util/wait:go_default_library",
"@io_k8s_client_go//util/retry:go_default_library",
"@io_k8s_utils//pointer:go_default_library",
],
)
+116 -44
View File
@@ -27,10 +27,13 @@ import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
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/apimachinery/pkg/util/wait"
"k8s.io/client-go/util/retry"
"k8s.io/utils/pointer"
cmacme "github.com/jetstack/cert-manager/pkg/apis/acme/v1"
v1 "github.com/jetstack/cert-manager/pkg/apis/certmanager/v1"
@@ -174,13 +177,22 @@ var _ = framework.CertManagerDescribe("ACME Certificate (HTTP01)", func() {
_, err = f.Helper().WaitForCertificateNotReadyUpdate(cert, 30*time.Second)
Expect(err).NotTo(HaveOccurred())
By("Getting the latest version of the Certificate")
cert, err = certClient.Get(context.TODO(), certificateName, metav1.GetOptions{})
Expect(err).NotTo(HaveOccurred())
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
By("Getting the latest version of the Certificate")
cert, err = certClient.Get(context.TODO(), certificateName, metav1.GetOptions{})
if err != nil {
return err
}
By("Replacing dnsNames with a valid dns name")
cert.Spec.DNSNames = []string{e2eutil.RandomSubdomain(acmeIngressDomain)}
_, err = certClient.Update(context.TODO(), cert, metav1.UpdateOptions{})
By("Replacing dnsNames with a valid dns name")
cert = cert.DeepCopy()
cert.Spec.DNSNames = []string{e2eutil.RandomSubdomain(acmeIngressDomain)}
_, err = certClient.Update(context.TODO(), cert, metav1.UpdateOptions{})
if err != nil {
return err
}
return nil
})
Expect(err).NotTo(HaveOccurred())
By("Waiting for the Certificate to have the Ready=True condition")
@@ -226,17 +238,29 @@ var _ = framework.CertManagerDescribe("ACME Certificate (HTTP01)", func() {
})
It("should obtain a signed certificate with a single CN from the ACME server when putting an annotation on an ingress resource", func() {
ingClient := f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace.Name)
switch {
case util.HasIngresses(f.KubeClientSet.Discovery(), networkingv1.SchemeGroupVersion.String()):
ingClient := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace.Name)
By("Creating an Ingress with the issuer name annotation set")
_, err := ingClient.Create(context.TODO(), util.NewIngress(certificateSecretName, certificateSecretName, map[string]string{
"cert-manager.io/issuer": issuerName,
}, acmeIngressDomain), metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
case util.HasIngresses(f.KubeClientSet.Discovery(), networkingv1beta1.SchemeGroupVersion.String()):
ingClient := f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace.Name)
By("Creating an Ingress with the issuer name annotation set")
_, err := ingClient.Create(context.TODO(), util.NewV1Beta1Ingress(certificateSecretName, certificateSecretName, map[string]string{
"cert-manager.io/issuer": issuerName,
}, acmeIngressDomain), metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
default:
Fail("Neither " + networkingv1.SchemeGroupVersion.String() + " nor " + networkingv1beta1.SchemeGroupVersion.String() + " were discovered in the API server")
}
certClient := f.CertManagerClientSet.CertmanagerV1().Certificates(f.Namespace.Name)
By("Creating an Ingress with the issuer name annotation set")
_, err := ingClient.Create(context.TODO(), util.NewIngress(certificateSecretName, certificateSecretName, map[string]string{
"cert-manager.io/issuer": issuerName,
}, acmeIngressDomain), metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
By("Waiting for Certificate to exist")
err = util.WaitForCertificateToExist(certClient, certificateSecretName, foreverTestTimeout)
err := util.WaitForCertificateToExist(certClient, certificateSecretName, foreverTestTimeout)
Expect(err).NotTo(HaveOccurred())
By("Waiting for the Certificate to be issued...")
@@ -287,33 +311,42 @@ var _ = framework.CertManagerDescribe("ACME Certificate (HTTP01)", func() {
// create an ingress that points at nothing, but has the TLS redirect annotation set
// using the TLS secret that we just got from the self-sign
ingress := f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace.Name)
_, err = ingress.Create(context.TODO(), &networkingv1beta1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: fixedIngressName,
Annotations: map[string]string{
"nginx.ingress.kubernetes.io/force-ssl-redirect": "true",
"kubernetes.io/ingress.class": "nginx",
},
},
Spec: networkingv1beta1.IngressSpec{
TLS: []networkingv1beta1.IngressTLS{
{
Hosts: []string{acmeIngressDomain},
SecretName: secretname,
switch {
case util.HasIngresses(f.KubeClientSet.Discovery(), networkingv1.SchemeGroupVersion.String()):
ingress := f.KubeClientSet.NetworkingV1().Ingresses(f.Namespace.Name)
_, err = ingress.Create(context.TODO(), &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: fixedIngressName,
Annotations: map[string]string{
"nginx.ingress.kubernetes.io/force-ssl-redirect": "true",
},
},
Rules: []networkingv1beta1.IngressRule{
{
Host: acmeIngressDomain,
IngressRuleValue: networkingv1beta1.IngressRuleValue{
HTTP: &networkingv1beta1.HTTPIngressRuleValue{
Paths: []networkingv1beta1.HTTPIngressPath{
{
Path: "/",
Backend: networkingv1beta1.IngressBackend{
ServiceName: "doesnotexist",
ServicePort: intstr.FromInt(443),
Spec: networkingv1.IngressSpec{
IngressClassName: pointer.StringPtr("nginx"),
TLS: []networkingv1.IngressTLS{
{
Hosts: []string{acmeIngressDomain},
SecretName: secretname,
},
},
Rules: []networkingv1.IngressRule{
{
Host: acmeIngressDomain,
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: "doesnotexist",
Port: networkingv1.ServiceBackendPort{
Number: 443,
},
},
},
},
},
},
@@ -321,11 +354,50 @@ var _ = framework.CertManagerDescribe("ACME Certificate (HTTP01)", func() {
},
},
},
},
}, metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
}, metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
case util.HasIngresses(f.KubeClientSet.Discovery(), networkingv1beta1.SchemeGroupVersion.String()):
ingress := f.KubeClientSet.NetworkingV1beta1().Ingresses(f.Namespace.Name)
_, err = ingress.Create(context.TODO(), &networkingv1beta1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: fixedIngressName,
Annotations: map[string]string{
"nginx.ingress.kubernetes.io/force-ssl-redirect": "true",
},
},
Spec: networkingv1beta1.IngressSpec{
IngressClassName: pointer.StringPtr("nginx"),
TLS: []networkingv1beta1.IngressTLS{
{
Hosts: []string{acmeIngressDomain},
SecretName: secretname,
},
},
Rules: []networkingv1beta1.IngressRule{
{
Host: acmeIngressDomain,
IngressRuleValue: networkingv1beta1.IngressRuleValue{
HTTP: &networkingv1beta1.HTTPIngressRuleValue{
Paths: []networkingv1beta1.HTTPIngressPath{
{
Path: "/",
Backend: networkingv1beta1.IngressBackend{
ServiceName: "doesnotexist",
ServicePort: intstr.FromInt(443),
},
},
},
},
},
},
},
},
}, metav1.CreateOptions{})
Expect(err).NotTo(HaveOccurred())
default:
Fail("Neither " + networkingv1.SchemeGroupVersion.String() + " nor " + networkingv1beta1.SchemeGroupVersion.String() + " were discovered in the API server")
}
By("Creating a Certificate")
// This is a special cert for the test suite, where we specify an ingress rather than a
// class
By("Creating a Certificate")
+2
View File
@@ -18,12 +18,14 @@ go_library(
"//pkg/util/pki:go_default_library",
"//test/e2e/framework/log: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_apiextensions_apiserver//pkg/client/clientset/clientset/typed/apiextensions/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/util/intstr:go_default_library",
"@io_k8s_apimachinery//pkg/util/wait:go_default_library",
"@io_k8s_client_go//discovery:go_default_library",
"@io_k8s_client_go//kubernetes:go_default_library",
"@io_k8s_sigs_gateway_api//apis/v1alpha1:go_default_library",
],
+64 -2
View File
@@ -30,12 +30,14 @@ import (
"time"
corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
networkingv1beta1 "k8s.io/api/networking/v1beta1"
apiextcs "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/discovery"
"k8s.io/client-go/kubernetes"
"sigs.k8s.io/gateway-api/apis/v1alpha1"
gwapiv1alpha1 "sigs.k8s.io/gateway-api/apis/v1alpha1"
@@ -417,7 +419,47 @@ func NewCertManagerVaultCertificate(name, secretName, issuerName string, issuerK
}
}
func NewIngress(name, secretName string, annotations map[string]string, dnsNames ...string) *networkingv1beta1.Ingress {
func NewIngress(name, secretName string, annotations map[string]string, dnsNames ...string) *networkingv1.Ingress {
return &networkingv1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Annotations: annotations,
},
Spec: networkingv1.IngressSpec{
TLS: []networkingv1.IngressTLS{
{
Hosts: dnsNames,
SecretName: secretName,
},
},
Rules: []networkingv1.IngressRule{
{
Host: dnsNames[0],
IngressRuleValue: networkingv1.IngressRuleValue{
HTTP: &networkingv1.HTTPIngressRuleValue{
Paths: []networkingv1.HTTPIngressPath{
{
Path: "/",
PathType: pathTypePrefix(),
Backend: networkingv1.IngressBackend{
Service: &networkingv1.IngressServiceBackend{
Name: "somesvc",
Port: networkingv1.ServiceBackendPort{
Number: 80,
},
},
},
},
},
},
},
},
},
},
}
}
func NewV1Beta1Ingress(name, secretName string, annotations map[string]string, dnsNames ...string) *networkingv1beta1.Ingress {
return &networkingv1beta1.Ingress{
ObjectMeta: metav1.ObjectMeta{
Name: name,
@@ -439,7 +481,7 @@ func NewIngress(name, secretName string, annotations map[string]string, dnsNames
{
Path: "/",
Backend: networkingv1beta1.IngressBackend{
ServiceName: "dummy-service",
ServiceName: "somesvc",
ServicePort: intstr.FromInt(80),
},
},
@@ -452,6 +494,11 @@ func NewIngress(name, secretName string, annotations map[string]string, dnsNames
}
}
func pathTypePrefix() *networkingv1.PathType {
p := networkingv1.PathTypePrefix
return &p
}
func NewGateway(gatewayName, ns, secretName string, annotations map[string]string, dnsNames ...string) (*gwapiv1alpha1.Gateway, *gwapiv1alpha1.HTTPRoute) {
var hostnames []gwapiv1alpha1.Hostname
for _, dnsName := range dnsNames {
@@ -526,3 +573,18 @@ func ptrPort(port int32) *gwapiv1alpha1.PortNumber {
p := gwapiv1alpha1.PortNumber(port)
return &p
}
// HasIngresses lets you know if an API exists in the discovery API
// calling this function always performs a request to the API server.
func HasIngresses(d discovery.DiscoveryInterface, GroupVersion string) bool {
resourceList, err := d.ServerResourcesForGroupVersion(GroupVersion)
if err != nil {
return false
}
for _, r := range resourceList.APIResources {
if r.Kind == "Ingress" {
return true
}
}
return false
}
@@ -3,7 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["discovery.go"],
importpath = "github.com/jetstack/cert-manager/pkg/internal/apis/certmanager/validation/plugins/fake",
importpath = "github.com/jetstack/cert-manager/test/unit/discovery",
visibility = ["//pkg:__subpackages__"],
deps = [
"@com_github_googleapis_gnostic//openapiv2:go_default_library",
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
package fake
package discovery
import (
openapi_v2 "github.com/googleapis/gnostic/openapiv2"