99 "reflect"
1010 "testing"
1111
12+ "github.com/stretchr/testify/assert"
1213 "github.com/stretchr/testify/require"
1314 corev1 "k8s.io/api/core/v1"
1415 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -20,6 +21,7 @@ import (
2021
2122 esv1 "github.com/elastic/cloud-on-k8s/v3/pkg/apis/elasticsearch/v1"
2223 policyv1alpha1 "github.com/elastic/cloud-on-k8s/v3/pkg/apis/stackconfigpolicy/v1alpha1"
24+ commonannotation "github.com/elastic/cloud-on-k8s/v3/pkg/controller/common/annotation"
2325 "github.com/elastic/cloud-on-k8s/v3/pkg/utils/k8s"
2426 "github.com/elastic/cloud-on-k8s/v3/pkg/utils/maps"
2527)
@@ -257,6 +259,15 @@ func ownedSecret(namespace, name, ownerNs, ownerName, ownerKind string) *corev1.
257259 }}}
258260}
259261
262+ func ownedSecretMultiRefs (namespace , name , ownerRefs , ownerKind string ) * corev1.Secret {
263+ return & corev1.Secret {
264+ ObjectMeta : metav1.ObjectMeta {Namespace : namespace , Name : name , Labels : map [string ]string {
265+ SoftOwnerKindLabel : ownerKind ,
266+ }, Annotations : map [string ]string {
267+ commonannotation .SoftOwnerRefsAnnotation : ownerRefs ,
268+ }}}
269+ }
270+
260271func TestGarbageCollectSoftOwnedSecrets (t * testing.T ) {
261272 tests := []struct {
262273 name string
@@ -433,6 +444,37 @@ func TestGarbageCollectAllSoftOwnedOrphanSecrets(t *testing.T) {
433444 ownedSecret ("ns" , "secret-1" , "another-namespace" , sampleOwner ().Name , sampleOwner ().Kind ),
434445 },
435446 },
447+ {
448+ name : "secret with multiple soft-owners that all exist" ,
449+ runtimeObjs : []client.Object {
450+ & policyv1alpha1.StackConfigPolicy {ObjectMeta : metav1.ObjectMeta {Name : "policy-1" , Namespace : "namespace-1" }},
451+ & policyv1alpha1.StackConfigPolicy {ObjectMeta : metav1.ObjectMeta {Name : "policy-2" , Namespace : "namespace-2" }},
452+ & policyv1alpha1.StackConfigPolicy {ObjectMeta : metav1.ObjectMeta {Name : "policy-3" , Namespace : "namespace-3" }},
453+ ownedSecretMultiRefs ("ns" , "secret-1" , `{"namespace-1/policy-1":{},"namespace-2/policy-2":{},"namespace-3/policy-3":{}}` , "StackConfigPolicy" ),
454+ },
455+ wantObjs : []client.Object {
456+ ownedSecretMultiRefs ("ns" , "secret-1" , `{"namespace-1/policy-1":{},"namespace-2/policy-2":{},"namespace-3/policy-3":{}}` , "StackConfigPolicy" ),
457+ },
458+ },
459+ {
460+ name : "secret with multiple soft-owners that all exist but some in different namespace" ,
461+ runtimeObjs : []client.Object {
462+ & policyv1alpha1.StackConfigPolicy {ObjectMeta : metav1.ObjectMeta {Name : "policy-1" , Namespace : "namespace-1" }},
463+ & policyv1alpha1.StackConfigPolicy {ObjectMeta : metav1.ObjectMeta {Name : "policy-2" , Namespace : "namespace-other" }},
464+ & policyv1alpha1.StackConfigPolicy {ObjectMeta : metav1.ObjectMeta {Name : "policy-3" , Namespace : "namespace-3" }},
465+ ownedSecretMultiRefs ("ns" , "secret-1" , `{"namespace-1/policy-1":{},"namespace-2/policy-2":{},"namespace-3/policy-3":{}}` , "StackConfigPolicy" ),
466+ },
467+ wantObjs : []client.Object {
468+ ownedSecretMultiRefs ("ns" , "secret-1" , `{"namespace-1/policy-1":{},"namespace-2/policy-2":{},"namespace-3/policy-3":{}}` , "StackConfigPolicy" ),
469+ },
470+ },
471+ {
472+ name : "secret with multiple soft-owners that none exists" ,
473+ runtimeObjs : []client.Object {
474+ ownedSecretMultiRefs ("ns" , "secret-1" , `{"namespace-1/policy-1":{},"namespace-2/policy-2":{},"namespace-3/policy-3":{}}` , "StackConfigPolicy" ),
475+ },
476+ wantObjs : []client.Object {},
477+ },
436478 }
437479 for _ , tt := range tests {
438480 t .Run (tt .name , func (t * testing.T ) {
@@ -546,3 +588,132 @@ func TestSoftOwnerRefFromLabels(t *testing.T) {
546588 })
547589 }
548590}
591+
592+ //nolint:thelper
593+ func TestSoftOwnerRefs (t * testing.T ) {
594+ tests := []struct {
595+ name string
596+ secret * corev1.Secret
597+ validate func (t * testing.T , owners []SoftOwnerRef , err error )
598+ }{
599+ {
600+ name : "returns multi-owner policies from annotation" ,
601+ secret : & corev1.Secret {
602+ ObjectMeta : metav1.ObjectMeta {
603+ Name : "test-secret" ,
604+ Namespace : "test-namespace" ,
605+ Labels : map [string ]string {
606+ SoftOwnerKindLabel : policyv1alpha1 .Kind ,
607+ },
608+ Annotations : map [string ]string {
609+ commonannotation .SoftOwnerRefsAnnotation : `{"namespace-1/policy-1":{},"namespace-2/policy-2":{}}` ,
610+ },
611+ },
612+ },
613+ validate : func (t * testing.T , owners []SoftOwnerRef , err error ) {
614+ require .NoError (t , err )
615+ require .Len (t , owners , 2 )
616+ assert .Contains (t , owners , SoftOwnerRef {Name : "policy-1" , Namespace : "namespace-1" , Kind : policyv1alpha1 .Kind })
617+ assert .Contains (t , owners , SoftOwnerRef {Name : "policy-2" , Namespace : "namespace-2" , Kind : policyv1alpha1 .Kind })
618+ },
619+ },
620+ {
621+ name : "returns single-owner policy from labels" ,
622+ secret : & corev1.Secret {
623+ ObjectMeta : metav1.ObjectMeta {
624+ Name : "test-secret" ,
625+ Namespace : "test-namespace" ,
626+ Labels : map [string ]string {
627+ SoftOwnerKindLabel : policyv1alpha1 .Kind ,
628+ SoftOwnerNameLabel : "single-policy" ,
629+ SoftOwnerNamespaceLabel : "single-namespace" ,
630+ },
631+ },
632+ },
633+ validate : func (t * testing.T , owners []SoftOwnerRef , err error ) {
634+ require .NoError (t , err )
635+ require .Len (t , owners , 1 )
636+ assert .Equal (t , SoftOwnerRef {Name : "single-policy" , Namespace : "single-namespace" , Kind : policyv1alpha1 .Kind }, owners [0 ])
637+ },
638+ },
639+ {
640+ name : "returns nil when secret has kind label but no owner labels" ,
641+ secret : & corev1.Secret {
642+ ObjectMeta : metav1.ObjectMeta {
643+ Name : "test-secret" ,
644+ Namespace : "test-namespace" ,
645+ Labels : map [string ]string {
646+ SoftOwnerKindLabel : policyv1alpha1 .Kind ,
647+ "other-label" : "other-value" ,
648+ },
649+ },
650+ },
651+ validate : func (t * testing.T , owners []SoftOwnerRef , err error ) {
652+ require .NoError (t , err )
653+ assert .Nil (t , owners )
654+ },
655+ },
656+ {
657+ name : "returns nil for non-policy-owned secret" ,
658+ secret : & corev1.Secret {
659+ ObjectMeta : metav1.ObjectMeta {
660+ Name : "test-secret" ,
661+ Namespace : "test-namespace" ,
662+ Labels : map [string ]string {
663+ "some-other-label" : "some-value" ,
664+ },
665+ },
666+ },
667+ validate : func (t * testing.T , owners []SoftOwnerRef , err error ) {
668+ require .NoError (t , err )
669+ assert .Nil (t , owners )
670+ },
671+ },
672+ {
673+ name : "returns error for invalid JSON in annotation" ,
674+ secret : & corev1.Secret {
675+ ObjectMeta : metav1.ObjectMeta {
676+ Name : "test-secret" ,
677+ Namespace : "test-namespace" ,
678+ Labels : map [string ]string {
679+ SoftOwnerKindLabel : policyv1alpha1 .Kind ,
680+ },
681+ Annotations : map [string ]string {
682+ commonannotation .SoftOwnerRefsAnnotation : `invalid-json` ,
683+ },
684+ },
685+ },
686+ validate : func (t * testing.T , owners []SoftOwnerRef , err error ) {
687+ require .Error (t , err )
688+ assert .Nil (t , owners )
689+ },
690+ },
691+ {
692+ name : "skips malformed namespaced names in annotation" ,
693+ secret : & corev1.Secret {
694+ ObjectMeta : metav1.ObjectMeta {
695+ Name : "test-secret" ,
696+ Namespace : "test-namespace" ,
697+ Labels : map [string ]string {
698+ SoftOwnerKindLabel : policyv1alpha1 .Kind ,
699+ },
700+ Annotations : map [string ]string {
701+ commonannotation .SoftOwnerRefsAnnotation : `{"namespace-1/policy-1":{},"malformed":{},"too/many/slashes":{}}` ,
702+ },
703+ },
704+ },
705+ validate : func (t * testing.T , owners []SoftOwnerRef , err error ) {
706+ require .NoError (t , err )
707+ require .Len (t , owners , 1 )
708+ assert .Equal (t , SoftOwnerRef {Name : "policy-1" , Namespace : "namespace-1" , Kind : policyv1alpha1 .Kind }, owners [0 ])
709+ },
710+ },
711+ }
712+
713+ for _ , tt := range tests {
714+ t .Run (tt .name , func (t * testing.T ) {
715+ owners , err := SoftOwnerRefs (tt .secret )
716+ tt .validate (t , owners , err )
717+ })
718+ }
719+ }
0 commit comments