You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pc...@apache.org on 2026/09/18 06:43:06 UTC

(camel-k) 04/09: refactor: added types to prevent unstructured, ingress_test made it enabled by default and added a function to disable it

This is an automated email from the ASF dual-hosted git repository.

squakez pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit fd2b535b6ef2b7727c206b3f434b1d939ca82c95
Author: Keerthan <po...@gmail.com>
AuthorDate: Wed Sep 16 21:20:11 2026 +0530

    refactor: added types to prevent unstructured, ingress_test made it enabled by default and added a function to disable it
---
 pkg/apis/addtoscheme_certmanager_duck_v1.go        |  27 +++++
 pkg/apis/duck/certmanager/v1/doc.go                |  21 ++++
 pkg/apis/duck/certmanager/v1/duck_types.go         |  65 +++++++++++
 pkg/apis/duck/certmanager/v1/register.go           |  48 ++++++++
 .../duck/certmanager/v1/zz_generated.deepcopy.go   | 123 +++++++++++++++++++++
 pkg/internal/client.go                             |  12 +-
 pkg/trait/ingress.go                               |  27 ++---
 pkg/trait/ingress_test.go                          |  41 +++----
 pkg/util/certmanager/enabled.go                    |  51 ++-------
 pkg/util/certmanager/enabled_test.go               |  42 ++++---
 10 files changed, 346 insertions(+), 111 deletions(-)

diff --git a/pkg/apis/addtoscheme_certmanager_duck_v1.go b/pkg/apis/addtoscheme_certmanager_duck_v1.go
new file mode 100644
index 000000000..4cffce670
--- /dev/null
+++ b/pkg/apis/addtoscheme_certmanager_duck_v1.go
@@ -0,0 +1,27 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 apis
+
+import (
+	v1 "github.com/apache/camel-k/v2/pkg/apis/duck/certmanager/v1"
+)
+
+func init() {
+	// Register the types with the Scheme so the components can map objects to GroupVersionKinds and back
+	AddToSchemes = append(AddToSchemes, v1.SchemeBuilder.AddToScheme)
+}
diff --git a/pkg/apis/duck/certmanager/v1/doc.go b/pkg/apis/duck/certmanager/v1/doc.go
new file mode 100644
index 000000000..154ce67a2
--- /dev/null
+++ b/pkg/apis/duck/certmanager/v1/doc.go
@@ -0,0 +1,21 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 v1 contains a partial schema of the cert-manager APIs
+// +kubebuilder:object:generate=true
+// +groupName=cert-manager.io
+package v1
diff --git a/pkg/apis/duck/certmanager/v1/duck_types.go b/pkg/apis/duck/certmanager/v1/duck_types.go
new file mode 100644
index 000000000..3e0121562
--- /dev/null
+++ b/pkg/apis/duck/certmanager/v1/duck_types.go
@@ -0,0 +1,65 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 v1
+
+import (
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+const (
+	CertManagerGroup   = "cert-manager.io"
+	CertManagerVersion = "v1"
+)
+
+// +kubebuilder:object:root=true
+
+// ClusterIssuer is a partial schema of the cert-manager ClusterIssuer resource,
+// carrying only the fields Camel K needs to verify its existence.
+type ClusterIssuer struct {
+	metav1.TypeMeta   `json:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty"`
+}
+
+// +kubebuilder:object:root=true
+
+// ClusterIssuerList contains a list of ClusterIssuer.
+type ClusterIssuerList struct {
+	metav1.TypeMeta `json:",inline"`
+	metav1.ListMeta `json:"metadata,omitempty"`
+
+	Items []ClusterIssuer `json:"items"`
+}
+
+// +kubebuilder:object:root=true
+
+// Issuer is a partial schema of the cert-manager Issuer resource, carrying
+// only the fields Camel K needs to verify its existence.
+type Issuer struct {
+	metav1.TypeMeta   `json:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty"`
+}
+
+// +kubebuilder:object:root=true
+
+// IssuerList contains a list of Issuer.
+type IssuerList struct {
+	metav1.TypeMeta `json:",inline"`
+	metav1.ListMeta `json:"metadata,omitempty"`
+
+	Items []Issuer `json:"items"`
+}
diff --git a/pkg/apis/duck/certmanager/v1/register.go b/pkg/apis/duck/certmanager/v1/register.go
new file mode 100644
index 000000000..bc4f114eb
--- /dev/null
+++ b/pkg/apis/duck/certmanager/v1/register.go
@@ -0,0 +1,48 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You 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 v1
+
+import (
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+)
+
+var (
+	// SchemeGroupVersion is group version used to register these objects.
+	SchemeGroupVersion = schema.GroupVersion{Group: CertManagerGroup, Version: CertManagerVersion}
+
+	// SchemeBuilder is used to add go types to the GroupVersionKind scheme.
+	SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
+
+	// AddToScheme is a shortcut to SchemeBuilder.AddToScheme.
+	AddToScheme = SchemeBuilder.AddToScheme
+)
+
+// Adds the list of known types to Scheme.
+func addKnownTypes(scheme *runtime.Scheme) error {
+	scheme.AddKnownTypes(SchemeGroupVersion,
+		&ClusterIssuer{},
+		&ClusterIssuerList{},
+		&Issuer{},
+		&IssuerList{},
+	)
+	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
+
+	return nil
+}
diff --git a/pkg/apis/duck/certmanager/v1/zz_generated.deepcopy.go b/pkg/apis/duck/certmanager/v1/zz_generated.deepcopy.go
new file mode 100644
index 000000000..26a2dc12e
--- /dev/null
+++ b/pkg/apis/duck/certmanager/v1/zz_generated.deepcopy.go
@@ -0,0 +1,123 @@
+//go:build !ignore_autogenerated
+
+// Code generated by controller-gen. DO NOT EDIT.
+
+package v1
+
+import (
+	"k8s.io/apimachinery/pkg/runtime"
+)
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ClusterIssuer) DeepCopyInto(out *ClusterIssuer) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterIssuer.
+func (in *ClusterIssuer) DeepCopy() *ClusterIssuer {
+	if in == nil {
+		return nil
+	}
+	out := new(ClusterIssuer)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ClusterIssuer) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ClusterIssuerList) DeepCopyInto(out *ClusterIssuerList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]ClusterIssuer, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterIssuerList.
+func (in *ClusterIssuerList) DeepCopy() *ClusterIssuerList {
+	if in == nil {
+		return nil
+	}
+	out := new(ClusterIssuerList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ClusterIssuerList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Issuer) DeepCopyInto(out *Issuer) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Issuer.
+func (in *Issuer) DeepCopy() *Issuer {
+	if in == nil {
+		return nil
+	}
+	out := new(Issuer)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *Issuer) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *IssuerList) DeepCopyInto(out *IssuerList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]Issuer, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IssuerList.
+func (in *IssuerList) DeepCopy() *IssuerList {
+	if in == nil {
+		return nil
+	}
+	out := new(IssuerList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *IssuerList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
diff --git a/pkg/internal/client.go b/pkg/internal/client.go
index 2c15d3892..50f014123 100644
--- a/pkg/internal/client.go
+++ b/pkg/internal/client.go
@@ -79,7 +79,8 @@ func NewFakeClient(initObjs ...runtime.Object) (client.Client, error) {
 		return strings.Contains(gvk.Group, "camel")
 	})...)
 	clientset := fakeclientset.NewSimpleClientset(filterObjects(scheme, initObjs, func(gvk schema.GroupVersionKind) bool {
-		return !strings.Contains(gvk.Group, "camel") && !strings.Contains(gvk.Group, "knative")
+		return !strings.Contains(gvk.Group, "camel") && !strings.Contains(gvk.Group, "knative") &&
+			!strings.Contains(gvk.Group, "cert-manager")
 	})...)
 	replicasCount := make(map[string]int32)
 	fakescaleclient := fakescale.FakeScaleClient{}
@@ -125,6 +126,7 @@ func NewFakeClient(initObjs ...runtime.Object) (client.Client, error) {
 		scales:                 &fakescaleclient,
 		enabledKnativeServing:  true,
 		enabledKnativeEventing: true,
+		enabledCertManager:     true,
 	}, nil
 }
 
@@ -203,10 +205,6 @@ func (c *FakeClient) EnableOpenshiftDiscovery() {
 	c.enabledOpenshift = true
 }
 
-func (c *FakeClient) EnableCertManagerDiscovery() {
-	c.enabledCertManager = true
-}
-
 func (c *FakeClient) DisableKnativeServing() {
 	c.enabledKnativeServing = false
 }
@@ -215,6 +213,10 @@ func (c *FakeClient) DisableKnativeEventing() {
 	c.enabledKnativeEventing = false
 }
 
+func (c *FakeClient) DisableCertManagerDiscovery() {
+	c.enabledCertManager = false
+}
+
 func (c *FakeClient) AuthorizationV1() authorizationv1.AuthorizationV1Interface {
 	return &FakeAuthorization{
 		AuthorizationV1Interface: c.Interface.AuthorizationV1(),
diff --git a/pkg/trait/ingress.go b/pkg/trait/ingress.go
index b06efeec3..aadcce161 100644
--- a/pkg/trait/ingress.go
+++ b/pkg/trait/ingress.go
@@ -191,11 +191,12 @@ func (t *ingressTrait) Apply(e *Environment) error {
 func (t *ingressTrait) resolveCertManagerIssuer(e *Environment) (annotationKey, issuerName string, err error) {
 	namespace := e.Integration.Namespace
 
+	installed, err := certmanager.IsInstalled(t.Client)
+	if err != nil {
+		return "", "", err
+	}
+
 	if t.TLSIssuerName != "" {
-		installed, err := certmanager.IsInstalled(e.Client)
-		if err != nil {
-			return "", "", err
-		}
 		if !installed {
 			return "", "", fmt.Errorf("cert-manager is not installed but tlsIssuerName %q was set", t.TLSIssuerName)
 		}
@@ -207,7 +208,7 @@ func (t *ingressTrait) resolveCertManagerIssuer(e *Environment) (annotationKey,
 
 		switch kind {
 		case "Issuer":
-			exists, err := certmanager.GetIssuer(e.Ctx, e.Client, namespace, t.TLSIssuerName)
+			exists, err := certmanager.GetIssuer(e.Ctx, t.Client, namespace, t.TLSIssuerName)
 			if err != nil {
 				return "", "", err
 			}
@@ -217,7 +218,7 @@ func (t *ingressTrait) resolveCertManagerIssuer(e *Environment) (annotationKey,
 
 			return certmanager.AnnotationIssuer, t.TLSIssuerName, nil
 		case "ClusterIssuer":
-			exists, err := certmanager.GetClusterIssuer(e.Ctx, e.Client, t.TLSIssuerName)
+			exists, err := certmanager.GetClusterIssuer(e.Ctx, t.Client, t.TLSIssuerName)
 			if err != nil {
 				return "", "", err
 			}
@@ -231,19 +232,11 @@ func (t *ingressTrait) resolveCertManagerIssuer(e *Environment) (annotationKey,
 		}
 	}
 
-	if !ptr.Deref(t.TLSCertManagerAuto, false) {
-		return "", "", nil
-	}
-
-	installed, err := certmanager.IsInstalled(e.Client)
-	if err != nil {
-		return "", "", err
-	}
-	if !installed {
+	if !ptr.Deref(t.TLSCertManagerAuto, false) || !installed {
 		return "", "", nil
 	}
 
-	clusterIssuers, err := certmanager.ListClusterIssuers(e.Ctx, e.Client)
+	clusterIssuers, err := certmanager.ListClusterIssuers(e.Ctx, t.Client)
 	if err != nil {
 		return "", "", err
 	}
@@ -251,7 +244,7 @@ func (t *ingressTrait) resolveCertManagerIssuer(e *Environment) (annotationKey,
 		return certmanager.AnnotationClusterIssuer, clusterIssuers[0], nil
 	}
 
-	issuers, err := certmanager.ListIssuers(e.Ctx, e.Client, namespace)
+	issuers, err := certmanager.ListIssuers(e.Ctx, t.Client, namespace)
 	if err != nil {
 		return "", "", err
 	}
diff --git a/pkg/trait/ingress_test.go b/pkg/trait/ingress_test.go
index e7477567c..dd0acd237 100644
--- a/pkg/trait/ingress_test.go
+++ b/pkg/trait/ingress_test.go
@@ -27,11 +27,11 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	networkingv1 "k8s.io/api/networking/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/utils/ptr"
 
 	v1 "github.com/apache/camel-k/v2/pkg/apis/camel/v1"
+	certmanagerv1 "github.com/apache/camel-k/v2/pkg/apis/duck/certmanager/v1"
 	"github.com/apache/camel-k/v2/pkg/internal"
 	"github.com/apache/camel-k/v2/pkg/util/certmanager"
 	"github.com/apache/camel-k/v2/pkg/util/kubernetes"
@@ -345,7 +345,8 @@ func TestApplyIngressTraitCertManagerAutoNotInstalledDoesNoop(t *testing.T) {
 	environment.Ctx = context.Background()
 	fakeClient, err := internal.NewFakeClient()
 	require.NoError(t, err)
-	environment.Client = fakeClient
+	fakeClient.(*internal.FakeClient).DisableCertManagerDiscovery()
+	ingressTrait.Client = fakeClient
 
 	_, _, err = ingressTrait.Configure(environment)
 	require.NoError(t, err)
@@ -367,8 +368,7 @@ func TestApplyIngressTraitCertManagerAutoNoIssuerDoesNoop(t *testing.T) {
 	environment.Ctx = context.Background()
 	fakeClient, err := internal.NewFakeClient()
 	require.NoError(t, err)
-	fakeClient.(*internal.FakeClient).EnableCertManagerDiscovery()
-	environment.Client = fakeClient
+	ingressTrait.Client = fakeClient
 
 	_, _, err = ingressTrait.Configure(environment)
 	require.NoError(t, err)
@@ -391,8 +391,7 @@ func TestApplyIngressTraitCertManagerAutoClusterIssuerFoundDoesSucceed(t *testin
 	clusterIssuer := newClusterIssuer("letsencrypt-prod")
 	fakeClient, err := internal.NewFakeClient(clusterIssuer)
 	require.NoError(t, err)
-	fakeClient.(*internal.FakeClient).EnableCertManagerDiscovery()
-	environment.Client = fakeClient
+	ingressTrait.Client = fakeClient
 
 	_, _, err = ingressTrait.Configure(environment)
 	require.NoError(t, err)
@@ -419,8 +418,7 @@ func TestApplyIngressTraitForcedIssuerExistsDoesSucceed(t *testing.T) {
 	issuer := newIssuer("my-issuer", "namespace")
 	fakeClient, err := internal.NewFakeClient(issuer)
 	require.NoError(t, err)
-	fakeClient.(*internal.FakeClient).EnableCertManagerDiscovery()
-	environment.Client = fakeClient
+	ingressTrait.Client = fakeClient
 
 	_, _, err = ingressTrait.Configure(environment)
 	require.NoError(t, err)
@@ -443,8 +441,7 @@ func TestApplyIngressTraitForcedIssuerMissingDoesNotSucceed(t *testing.T) {
 
 	fakeClient, err := internal.NewFakeClient()
 	require.NoError(t, err)
-	fakeClient.(*internal.FakeClient).EnableCertManagerDiscovery()
-	environment.Client = fakeClient
+	ingressTrait.Client = fakeClient
 
 	_, _, err = ingressTrait.Configure(environment)
 
@@ -460,7 +457,8 @@ func TestApplyIngressTraitForcedIssuerCertManagerNotInstalledDoesNotSucceed(t *t
 
 	fakeClient, err := internal.NewFakeClient()
 	require.NoError(t, err)
-	environment.Client = fakeClient
+	fakeClient.(*internal.FakeClient).DisableCertManagerDiscovery()
+	ingressTrait.Client = fakeClient
 
 	_, _, err = ingressTrait.Configure(environment)
 
@@ -468,21 +466,16 @@ func TestApplyIngressTraitForcedIssuerCertManagerNotInstalledDoesNotSucceed(t *t
 	assert.Contains(t, err.Error(), "cert-manager is not installed")
 }
 
-func newClusterIssuer(name string) *unstructured.Unstructured {
-	u := &unstructured.Unstructured{}
-	u.SetGroupVersionKind(certmanager.ClusterIssuerGVK)
-	u.SetName(name)
-
-	return u
+func newClusterIssuer(name string) *certmanagerv1.ClusterIssuer {
+	return &certmanagerv1.ClusterIssuer{
+		ObjectMeta: metav1.ObjectMeta{Name: name},
+	}
 }
 
-func newIssuer(name, namespace string) *unstructured.Unstructured {
-	u := &unstructured.Unstructured{}
-	u.SetGroupVersionKind(certmanager.IssuerGVK)
-	u.SetName(name)
-	u.SetNamespace(namespace)
-
-	return u
+func newIssuer(name, namespace string) *certmanagerv1.Issuer {
+	return &certmanagerv1.Issuer{
+		ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: namespace},
+	}
 }
 
 func createNominalIngressTestWithIngressClassName(ingressClassName string) (*ingressTrait, *Environment) {
diff --git a/pkg/util/certmanager/enabled.go b/pkg/util/certmanager/enabled.go
index 627002280..32b13a7d4 100644
--- a/pkg/util/certmanager/enabled.go
+++ b/pkg/util/certmanager/enabled.go
@@ -23,42 +23,21 @@ import (
 
 	k8serrors "k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/api/meta"
-	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/apimachinery/pkg/runtime/schema"
 	"k8s.io/client-go/kubernetes"
 	ctrl "sigs.k8s.io/controller-runtime/pkg/client"
 
+	certmanagerv1 "github.com/apache/camel-k/v2/pkg/apis/duck/certmanager/v1"
 	kubernetesutil "github.com/apache/camel-k/v2/pkg/util/kubernetes"
 )
 
 const (
-	// CertManagerAPIGroup is the API group for cert-manager.
-	CertManagerAPIGroup = "cert-manager.io"
-	// CertManagerAPIVersion is the current API version for cert-manager.
-	CertManagerAPIVersion = "v1"
-
 	// AnnotationClusterIssuer is the Ingress annotation to specify a ClusterIssuer.
 	AnnotationClusterIssuer = "cert-manager.io/cluster-issuer"
 	// AnnotationIssuer is the Ingress annotation to specify a namespaced Issuer.
 	AnnotationIssuer = "cert-manager.io/issuer"
 )
 
-var (
-	// ClusterIssuerGVK is the GroupVersionKind for cert-manager ClusterIssuer.
-	ClusterIssuerGVK = schema.GroupVersionKind{
-		Group:   CertManagerAPIGroup,
-		Version: CertManagerAPIVersion,
-		Kind:    "ClusterIssuer",
-	}
-
-	// IssuerGVK is the GroupVersionKind for cert-manager Issuer.
-	IssuerGVK = schema.GroupVersionKind{
-		Group:   CertManagerAPIGroup,
-		Version: CertManagerAPIVersion,
-		Kind:    "Issuer",
-	}
-)
-
 func isResourceNotFoundError(err error) bool {
 	if err == nil {
 		return false
@@ -70,8 +49,8 @@ func isResourceNotFoundError(err error) bool {
 // IsInstalled returns true if connected to a cluster with cert-manager installed.
 func IsInstalled(c kubernetes.Interface) (bool, error) {
 	_, err := c.Discovery().ServerResourcesForGroupVersion(schema.GroupVersion{
-		Group:   CertManagerAPIGroup,
-		Version: CertManagerAPIVersion,
+		Group:   certmanagerv1.CertManagerGroup,
+		Version: certmanagerv1.CertManagerVersion,
 	}.String())
 	if isResourceNotFoundError(err) {
 		return false, nil
@@ -84,13 +63,7 @@ func IsInstalled(c kubernetes.Interface) (bool, error) {
 
 // ListClusterIssuers returns all ClusterIssuer names available in the cluster.
 func ListClusterIssuers(ctx context.Context, c ctrl.Reader) ([]string, error) {
-	list := &unstructured.UnstructuredList{}
-	list.SetGroupVersionKind(schema.GroupVersionKind{
-		Group:   CertManagerAPIGroup,
-		Version: CertManagerAPIVersion,
-		Kind:    "ClusterIssuerList",
-	})
-
+	list := &certmanagerv1.ClusterIssuerList{}
 	if err := c.List(ctx, list); err != nil {
 		if isResourceNotFoundError(err) {
 			return nil, nil
@@ -101,7 +74,7 @@ func ListClusterIssuers(ctx context.Context, c ctrl.Reader) ([]string, error) {
 
 	names := make([]string, 0, len(list.Items))
 	for _, item := range list.Items {
-		names = append(names, item.GetName())
+		names = append(names, item.Name)
 	}
 	sort.Strings(names)
 
@@ -110,7 +83,7 @@ func ListClusterIssuers(ctx context.Context, c ctrl.Reader) ([]string, error) {
 
 // GetClusterIssuer checks if a specific ClusterIssuer exists in the cluster.
 func GetClusterIssuer(ctx context.Context, c ctrl.Reader, name string) (bool, error) {
-	_, err := kubernetesutil.GetUnstructured(ctx, c, ClusterIssuerGVK, name, "")
+	err := c.Get(ctx, ctrl.ObjectKey{Name: name}, &certmanagerv1.ClusterIssuer{})
 	if err != nil {
 		if isResourceNotFoundError(err) {
 			return false, nil
@@ -124,13 +97,7 @@ func GetClusterIssuer(ctx context.Context, c ctrl.Reader, name string) (bool, er
 
 // ListIssuers returns all Issuer names available in a specific namespace.
 func ListIssuers(ctx context.Context, c ctrl.Reader, namespace string) ([]string, error) {
-	list := &unstructured.UnstructuredList{}
-	list.SetGroupVersionKind(schema.GroupVersionKind{
-		Group:   CertManagerAPIGroup,
-		Version: CertManagerAPIVersion,
-		Kind:    "IssuerList",
-	})
-
+	list := &certmanagerv1.IssuerList{}
 	if err := c.List(ctx, list, ctrl.InNamespace(namespace)); err != nil {
 		if isResourceNotFoundError(err) {
 			return nil, nil
@@ -141,7 +108,7 @@ func ListIssuers(ctx context.Context, c ctrl.Reader, namespace string) ([]string
 
 	names := make([]string, 0, len(list.Items))
 	for _, item := range list.Items {
-		names = append(names, item.GetName())
+		names = append(names, item.Name)
 	}
 	sort.Strings(names)
 
@@ -150,7 +117,7 @@ func ListIssuers(ctx context.Context, c ctrl.Reader, namespace string) ([]string
 
 // GetIssuer checks if a specific namespaced Issuer exists.
 func GetIssuer(ctx context.Context, c ctrl.Reader, namespace, name string) (bool, error) {
-	_, err := kubernetesutil.GetUnstructured(ctx, c, IssuerGVK, name, namespace)
+	err := c.Get(ctx, ctrl.ObjectKey{Name: name, Namespace: namespace}, &certmanagerv1.Issuer{})
 	if err != nil {
 		if isResourceNotFoundError(err) {
 			return false, nil
diff --git a/pkg/util/certmanager/enabled_test.go b/pkg/util/certmanager/enabled_test.go
index 65a0c60ef..5b77247a7 100644
--- a/pkg/util/certmanager/enabled_test.go
+++ b/pkg/util/certmanager/enabled_test.go
@@ -27,10 +27,11 @@ import (
 	"github.com/stretchr/testify/require"
 	k8serrors "k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/api/meta"
-	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime/schema"
 	ctrl "sigs.k8s.io/controller-runtime/pkg/client"
 
+	certmanagerv1 "github.com/apache/camel-k/v2/pkg/apis/duck/certmanager/v1"
 	"github.com/apache/camel-k/v2/pkg/internal"
 )
 
@@ -56,26 +57,21 @@ func (m *errorMockReader) Get(ctx context.Context, key ctrl.ObjectKey, obj ctrl.
 	return m.Reader.Get(ctx, key, obj, opts...)
 }
 
-func newUnstructuredClusterIssuer(name string) *unstructured.Unstructured {
-	u := &unstructured.Unstructured{}
-	u.SetGroupVersionKind(ClusterIssuerGVK)
-	u.SetName(name)
-
-	return u
+func newClusterIssuer(name string) *certmanagerv1.ClusterIssuer {
+	return &certmanagerv1.ClusterIssuer{
+		ObjectMeta: metav1.ObjectMeta{Name: name},
+	}
 }
 
-func newUnstructuredIssuer(namespace, name string) *unstructured.Unstructured {
-	u := &unstructured.Unstructured{}
-	u.SetGroupVersionKind(IssuerGVK)
-	u.SetNamespace(namespace)
-	u.SetName(name)
-
-	return u
+func newIssuer(namespace, name string) *certmanagerv1.Issuer {
+	return &certmanagerv1.Issuer{
+		ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: name},
+	}
 }
 
 func TestListClusterIssuers(t *testing.T) {
-	ci1 := newUnstructuredClusterIssuer("letsencrypt-staging")
-	ci2 := newUnstructuredClusterIssuer("letsencrypt-prod")
+	ci1 := newClusterIssuer("letsencrypt-staging")
+	ci2 := newClusterIssuer("letsencrypt-prod")
 
 	c, err := internal.NewFakeClient(ci1, ci2)
 	require.NoError(t, err)
@@ -86,7 +82,7 @@ func TestListClusterIssuers(t *testing.T) {
 }
 
 func TestGetClusterIssuer(t *testing.T) {
-	ci := newUnstructuredClusterIssuer("my-cluster-issuer")
+	ci := newClusterIssuer("my-cluster-issuer")
 
 	c, err := internal.NewFakeClient(ci)
 	require.NoError(t, err)
@@ -101,9 +97,9 @@ func TestGetClusterIssuer(t *testing.T) {
 }
 
 func TestListIssuers(t *testing.T) {
-	i1 := newUnstructuredIssuer("ns1", "issuer-b")
-	i2 := newUnstructuredIssuer("ns1", "issuer-a")
-	i3 := newUnstructuredIssuer("ns2", "issuer-other")
+	i1 := newIssuer("ns1", "issuer-b")
+	i2 := newIssuer("ns1", "issuer-a")
+	i3 := newIssuer("ns2", "issuer-other")
 
 	c, err := internal.NewFakeClient(i1, i2, i3)
 	require.NoError(t, err)
@@ -122,7 +118,7 @@ func TestListIssuers(t *testing.T) {
 }
 
 func TestGetIssuer(t *testing.T) {
-	i := newUnstructuredIssuer("test-ns", "my-issuer")
+	i := newIssuer("test-ns", "my-issuer")
 
 	c, err := internal.NewFakeClient(i)
 	require.NoError(t, err)
@@ -145,7 +141,7 @@ func TestCRDsAbsentEntirely(t *testing.T) {
 	require.NoError(t, err)
 
 	noKindMatchErr := &meta.NoKindMatchError{
-		GroupKind:        schema.GroupKind{Group: CertManagerAPIGroup, Kind: "ClusterIssuerList"},
+		GroupKind:        schema.GroupKind{Group: certmanagerv1.CertManagerGroup, Kind: "ClusterIssuerList"},
 		SearchedVersions: []string{"v1"},
 	}
 
@@ -202,7 +198,7 @@ func TestCRDsAbsentViaNotFoundError(t *testing.T) {
 	require.NoError(t, err)
 
 	notFoundErr := k8serrors.NewNotFound(
-		schema.GroupResource{Group: CertManagerAPIGroup, Resource: "clusterissuers"},
+		schema.GroupResource{Group: certmanagerv1.CertManagerGroup, Resource: "clusterissuers"},
 		"my-ci",
 	)