Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pkg/psmdb/tls/certmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,11 @@ func (c *certManagerController) WaitForCerts(ctx context.Context, cr *api.Percon
if v, ok := secret.Annotations[cm.CertificateNameKey]; !ok || v != secret.Name {
continue
}
// cert-manager sets the Certificate as the controller owner.
// In that case, the operator should not set a new controller reference.
if metav1.GetControllerOf(secret) != nil {
continue
}
Comment on lines +316 to +320
Copy link
Member

@mayankshah1607 mayankshah1607 Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can just check if the error below (when calling SetControllerReference) returns a controllerutil.AlreadyOwnedError{} type using errors.Is

if err = controllerutil.SetControllerReference(cr, secret, c.scheme); err != nil {
return errors.Wrap(err, "set controller reference")
}
Expand Down
134 changes: 134 additions & 0 deletions pkg/psmdb/tls/certmanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ import (

cm "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake" // nolint

api "github.com/percona/percona-server-mongodb-operator/pkg/apis/psmdb/v1"
"github.com/percona/percona-server-mongodb-operator/pkg/version"
)

func TestCreateIssuer(t *testing.T) {
Expand Down Expand Up @@ -130,6 +133,137 @@ func TestCreateCertificate(t *testing.T) {
})
}

func TestWaitForCerts(t *testing.T) {
ctx := context.Background()

cr := &api.PerconaServerMongoDB{
ObjectMeta: metav1.ObjectMeta{
Name: "test-cluster",
Namespace: "default",
UID: "test-uid-123",
},
Spec: api.PerconaServerMongoDBSpec{
CRVersion: version.Version(),
},
}

certName := CACertificateSecretName(cr)

tests := map[string]struct {
certificate *cm.Certificate
secret *corev1.Secret
}{
"with cert-manager managed secret": {
certificate: &cm.Certificate{
ObjectMeta: metav1.ObjectMeta{
Name: certName,
Namespace: cr.Namespace,
UID: "cert-uid-456",
},
Spec: cm.CertificateSpec{
SecretName: certName,
},
},
secret: &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: certName,
Namespace: cr.Namespace,
Annotations: map[string]string{
cm.CertificateNameKey: certName,
},
OwnerReferences: []metav1.OwnerReference{
{
APIVersion: cm.SchemeGroupVersion.String(),
Kind: cm.CertificateKind,
Name: certName,
UID: "cert-uid-456",
Controller: pointer(true),
},
},
},
Data: map[string][]byte{
"ca.crt": []byte("fake-ca-cert"),
"tls.crt": []byte("fake-tls-cert"),
"tls.key": []byte("fake-tls-key"),
},
},
},
"with cert-manager managed secret but without OwnerReferences": {
certificate: &cm.Certificate{
ObjectMeta: metav1.ObjectMeta{
Name: certName,
Namespace: cr.Namespace,
UID: "cert-uid-456",
},
Spec: cm.CertificateSpec{
SecretName: certName,
},
},
secret: &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: certName,
Namespace: cr.Namespace,
Annotations: map[string]string{
cm.CertificateNameKey: certName,
},
},
Data: map[string][]byte{
"ca.crt": []byte("fake-ca-cert"),
"tls.crt": []byte("fake-tls-cert"),
"tls.key": []byte("fake-tls-key"),
},
},
},
"without cert-manager": {
certificate: nil,
secret: &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: certName,
Namespace: cr.Namespace,
},
Data: map[string][]byte{
"ca.crt": []byte("fake-ca-cert"),
"tls.crt": []byte("fake-tls-cert"),
"tls.key": []byte("fake-tls-key"),
},
},
},
}

for name, tc := range tests {
t.Run(name, func(t *testing.T) {
s := scheme.Scheme
s.AddKnownTypes(api.SchemeGroupVersion, new(api.PerconaServerMongoDB))
s.AddKnownTypes(cm.SchemeGroupVersion, new(cm.Certificate))
s.AddKnownTypes(corev1.SchemeGroupVersion, new(corev1.Secret))

objects := []client.Object{cr, tc.secret}
if tc.certificate != nil {
objects = append(objects, tc.certificate)
}

cl := fake.NewClientBuilder().
WithScheme(s).
WithObjects(objects...).
WithStatusSubresource(cr).
Build()

controller := &certManagerController{
cl: cl,
scheme: s,
dryRun: false,
}

err := controller.WaitForCerts(ctx, cr, certName)
assert.NoError(t, err)
})
}
}

func pointer(b bool) *bool {
return &b
}

// creates a fake client to mock API calls with the mock objects
func buildFakeClient(objs ...client.Object) CertManagerController {
s := scheme.Scheme
Expand Down
Loading