From 6cffa0cf3e85891c6c79da07b5d1414342dc272c Mon Sep 17 00:00:00 2001 From: Karol Szwaj Date: Tue, 23 Dec 2025 16:22:13 +0100 Subject: [PATCH 1/3] fix: check for isolation mode in the permission claims references Signed-off-by: Karol Szwaj On-behalf-of: @SAP karol.szwaj@sap.com --- pkg/resources/resources.go | 54 +++++++-- pkg/resources/resources_test.go | 198 +++++++++++++++++++++++++++++++- 2 files changed, 241 insertions(+), 11 deletions(-) diff --git a/pkg/resources/resources.go b/pkg/resources/resources.go index 3180d9158..4ea30e389 100644 --- a/pkg/resources/resources.go +++ b/pkg/resources/resources.go @@ -19,6 +19,7 @@ package resources import ( "context" "fmt" + "slices" "strings" "time" @@ -80,7 +81,12 @@ func matchesNamedResources(logger klog.Logger, namedResources []kubebindv1alpha2 return false } -func matchesReferences(logger klog.Logger, references []kubebindv1alpha2.SelectorReference, obj *unstructured.Unstructured, potentiallyReferencedResources *unstructured.UnstructuredList) bool { +func matchesReferences(logger klog.Logger, + references []kubebindv1alpha2.SelectorReference, + obj *unstructured.Unstructured, + potentiallyReferencedResources *unstructured.UnstructuredList, + isolation kubebindv1alpha2.Isolation, + ) bool { if len(references) == 0 { return false } @@ -131,12 +137,18 @@ func matchesReferences(logger klog.Logger, references []kubebindv1alpha2.Selecto namespaceMatches = false objNamespace := obj.GetNamespace() - for _, extractedNamespace := range namespaceValues { - if extractedNamespace == objNamespace { + if slices.Contains(namespaceValues, objNamespace) { namespaceMatches = true - break } - } + } + + if selector.JSONPath.Namespace == "" && isolation == kubebindv1alpha2.IsolationNamespaced { + namespaceMatches = (refObj.GetNamespace() == obj.GetNamespace()) + logger.V(4).Info("namespace extracted from referenced object", + "referencedObjectNamespace", refObj.GetNamespace(), + "objectNamespace", obj.GetNamespace(), + "namespaceMatches", namespaceMatches, + ) } if nameMatches && namespaceMatches { @@ -152,7 +164,7 @@ func matchesReferences(logger klog.Logger, references []kubebindv1alpha2.Selecto // IsClaimed returns true if the given object matches the given selector and named resources. // Logger here is already at V(4) level. -func IsClaimed(logger klog.Logger, selector kubebindv1alpha2.Selector, obj *unstructured.Unstructured, potentiallyReferencedResources *unstructured.UnstructuredList) bool { +func IsClaimed(logger klog.Logger, selector kubebindv1alpha2.Selector, obj *unstructured.Unstructured, potentiallyReferencedResources *unstructured.UnstructuredList, isolation kubebindv1alpha2.Isolation) bool { if obj == nil { return false } @@ -164,7 +176,7 @@ func IsClaimed(logger klog.Logger, selector kubebindv1alpha2.Selector, obj *unst labelSelectorMatches := matchesLabelSelector(logger, selector.LabelSelector, obj) namedResourceMatches := matchesNamedResources(logger, selector.NamedResources, obj) - referenceMatches := matchesReferences(logger, selector.References, obj, potentiallyReferencedResources) + referenceMatches := matchesReferences(logger, selector.References, obj, potentiallyReferencedResources, isolation) return labelSelectorMatches || namedResourceMatches || referenceMatches } @@ -193,6 +205,16 @@ func IsClaimedWithReference( for _, ref := range claim.Selector.References { logger := logger.WithValues("referenceGroup", ref.Group, "referenceResource", ref.Resource, "referenceJSONPathName", ref.JSONPath.Name, "referenceJSONPathNamespace", ref.JSONPath.Namespace) logger.Info("processing reference selector") + + if !isReferenceAllowed(ref, apiServiceExport) { + logger.Info("reference not allowed, resource is not part of the contract", + "isolation", apiServiceExport.Spec.ClusterScopedIsolation, + "referenceGroup", ref.Group, + "referenceResource", ref.Resource, + ) + continue + } + if len(ref.Versions) > 0 { versions = ref.Versions } else { @@ -232,7 +254,7 @@ func IsClaimedWithReference( if consumerSide { logger.Info("checking claim on consumer side") - result := IsClaimed(logger, claim.Selector, copy, potentiallyReferencedResources) + result := IsClaimed(logger, claim.Selector, copy, potentiallyReferencedResources, apiServiceExport.Spec.ClusterScopedIsolation) logger.Info("IsClaimed result", "result", result) return result } @@ -258,7 +280,21 @@ func IsClaimedWithReference( copy.SetNamespace(sn.Name) } - result := IsClaimed(logger, claim.Selector, copy, potentiallyReferencedResources) + result := IsClaimed(logger, claim.Selector, copy, potentiallyReferencedResources, apiServiceExport.Spec.ClusterScopedIsolation) logger.V(4).Info("IsClaimed result (provider side)", "result", result) return result } + +func isReferenceAllowed(ref kubebindv1alpha2.SelectorReference, apiServiceExport *kubebindv1alpha2.APIServiceExport) bool { + // If isolation is None, everything should be allowed, as both ends are owned. + if apiServiceExport.Spec.ClusterScopedIsolation == kubebindv1alpha2.IsolationNone { + return true + } + for _, resource := range apiServiceExport.Spec.Resources { + if ref.Group == resource.Group && ref.Resource == resource.Resource { + return true + } + } + + return false +} diff --git a/pkg/resources/resources_test.go b/pkg/resources/resources_test.go index 985c806ad..89f5eb83f 100644 --- a/pkg/resources/resources_test.go +++ b/pkg/resources/resources_test.go @@ -32,6 +32,7 @@ func TestSelector_IsClaimed(t *testing.T) { selector kubebindv1alpha2.Selector obj *unstructured.Unstructured potentiallyReferencedResources *unstructured.UnstructuredList + isolation kubebindv1alpha2.Isolation want bool }{ { @@ -95,6 +96,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: false, }, { @@ -116,6 +118,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: true, }, { @@ -137,6 +140,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: true, }, { @@ -158,6 +162,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: false, }, { @@ -179,6 +184,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: false, }, { @@ -204,6 +210,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: true, }, { @@ -224,6 +231,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: false, }, { @@ -253,6 +261,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: true, }, { @@ -282,6 +291,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: true, }, { @@ -311,6 +321,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: true, }, { @@ -348,6 +359,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: true, // Should match because label selector matches (OR logic) }, // JSONPath Reference tests @@ -391,6 +403,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: true, }, { @@ -435,6 +448,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: true, }, { @@ -477,6 +491,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: false, }, { @@ -521,6 +536,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: false, }, { @@ -565,6 +581,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: true, }, { @@ -619,6 +636,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: true, }, { @@ -665,10 +683,11 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: false, // Should not match because [*] syntax is not supported by gjson }, { - name: "reference selector should not match when no referenced resources provided", + name: "reference selector should not match when no referenced resources provided", potentiallyReferencedResources: nil, selector: kubebindv1alpha2.Selector{ References: []kubebindv1alpha2.SelectorReference{ @@ -691,6 +710,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: false, }, { @@ -731,6 +751,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: false, }, { @@ -786,6 +807,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: false, // Should NOT match because it doesn't have app=sheriff label and is not referenced by Sheriff }, { @@ -840,6 +862,7 @@ func TestSelector_IsClaimed(t *testing.T) { "type": "kubernetes.io/tls", }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: true, // Should match because certificate's .spec.secretName equals secret name and no namespace JSONPath means namespace matching is handled by caller }, { @@ -887,6 +910,7 @@ func TestSelector_IsClaimed(t *testing.T) { "type": "kubernetes.io/tls", }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: false, // Should not match because certificate's .spec.secretName is "other-secret", not "my-tls-cert" }, { @@ -934,17 +958,187 @@ func TestSelector_IsClaimed(t *testing.T) { "type": "kubernetes.io/tls", }, }, + isolation: kubebindv1alpha2.IsolationPrefixed, want: true, // Should match because when no namespace JSONPath is provided, namespace matching is delegated to caller + }, + { + name: "namespace inherited from referencing object when JSONPath not provided", + potentiallyReferencedResources: &unstructured.UnstructuredList{ + Items: []unstructured. Unstructured{ + { + Object: map[string]any{ + "metadata": map[string]any{ + "name": "mangodb-instance", + "namespace": "default", + }, + "spec": map[string]any{ + "secret": map[string]any{ + "name": "my-secret", + }, + }, + }, + }, + }, + }, + selector: kubebindv1alpha2.Selector{ + References: []kubebindv1alpha2.SelectorReference{ + { + GroupResource: kubebindv1alpha2.GroupResource{ + Group: "mangodb.com", + Resource: "mangodbs", + }, + JSONPath: &kubebindv1alpha2.JSONPath{ + Name: "spec.secret.name", + }, + }, + }, + }, + obj: &unstructured.Unstructured{ + Object: map[string]any{ + "metadata": map[string]any{ + "name": "my-secret", + "namespace": "default", + }, + }, + }, + isolation: kubebindv1alpha2.IsolationNamespaced, + want: true, + }, + { + name: "namespace inheritance fails when in different namespace", + potentiallyReferencedResources: &unstructured.UnstructuredList{ + Items: []unstructured. Unstructured{ + { + Object: map[string]any{ + "metadata": map[string]any{ + "name": "mangodb-instance", + "namespace": "default", + }, + "spec": map[string]any{ + "secret": map[string]any{ + "name": "my-secret", + }, + }, + }, + }, + }, + }, + selector: kubebindv1alpha2.Selector{ + References: []kubebindv1alpha2.SelectorReference{ + { + GroupResource: kubebindv1alpha2.GroupResource{ + Group: "mangodb.com", + Resource: "mangodbs", + }, + JSONPath: &kubebindv1alpha2.JSONPath{ + Name: "spec.secret.name", + }, + }, + }, + }, + obj: &unstructured.Unstructured{ + Object: map[string]any{ + "metadata": map[string]any{ + "name": "my-secret", + "namespace": "other-namespace", + }, + }, + }, + isolation: kubebindv1alpha2.IsolationNamespaced, + want: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { logger := klog.Background().V(4) - got := IsClaimed(logger, tt.selector, tt.obj, tt.potentiallyReferencedResources) + got := IsClaimed(logger, tt.selector, tt.obj, tt.potentiallyReferencedResources, tt.isolation) if got != tt.want { t.Errorf("IsClaimed() = %v, want %v", got, tt.want) } }) } } + + +func TestReferenceSelector_IsolationMode(t *testing. T) { + tests := []struct { + name string + isolation kubebindv1alpha2.Isolation + exportedResources []kubebindv1alpha2.APIServiceExportResource + reference kubebindv1alpha2.SelectorReference + shouldAllow bool + }{ + { + name: "IsolationNone allows all references", + isolation: kubebindv1alpha2.IsolationNone, + exportedResources: []kubebindv1alpha2.APIServiceExportResource{ + {GroupResource: kubebindv1alpha2.GroupResource{Group: "mangodb.com", Resource: "mangodbs"}}, + }, + reference: kubebindv1alpha2.SelectorReference{ + GroupResource: kubebindv1alpha2.GroupResource{Group: "secret.com", Resource: "secrets"}, + }, + shouldAllow: true, + }, + { + name: "IsolationNamespaced blocks non-exported references", + isolation: kubebindv1alpha2.IsolationNamespaced, + exportedResources: []kubebindv1alpha2.APIServiceExportResource{ + {GroupResource: kubebindv1alpha2.GroupResource{Group: "mangodb.com", Resource: "mangodbs"}}, + }, + reference: kubebindv1alpha2.SelectorReference{ + GroupResource: kubebindv1alpha2.GroupResource{Group: "secret.com", Resource: "secrets"}, + }, + shouldAllow: false, + }, + { + name: "IsolationPrefixed blocks non-exported references", + isolation: kubebindv1alpha2.IsolationPrefixed, + exportedResources: []kubebindv1alpha2.APIServiceExportResource{ + {GroupResource: kubebindv1alpha2.GroupResource{Group: "mangodb.com", Resource: "mangodbs"}}, + }, + reference: kubebindv1alpha2.SelectorReference{ + GroupResource: kubebindv1alpha2.GroupResource{Group: "secret.com", Resource: "secrets"}, + }, + shouldAllow: false, + }, + { + name: "IsolationPrefixed allows exported references", + isolation: kubebindv1alpha2.IsolationPrefixed, + exportedResources: []kubebindv1alpha2.APIServiceExportResource{ + {GroupResource: kubebindv1alpha2.GroupResource{Group: "mangodb.com", Resource: "mangodbs"}}, + }, + reference: kubebindv1alpha2.SelectorReference{ + GroupResource: kubebindv1alpha2.GroupResource{Group: "mangodb.com", Resource: "mangodbs"}, + }, + shouldAllow: true, + }, + { + name: "IsolationNamespaced allows exported references", + isolation: kubebindv1alpha2.IsolationNamespaced, + exportedResources: []kubebindv1alpha2.APIServiceExportResource{ + {GroupResource: kubebindv1alpha2.GroupResource{Group: "mangodb.com", Resource: "mangodbs"}}, + }, + reference: kubebindv1alpha2.SelectorReference{ + GroupResource: kubebindv1alpha2.GroupResource{Group: "mangodb.com", Resource: "mangodbs"}, + }, + shouldAllow: true, + }, + + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + export := &kubebindv1alpha2.APIServiceExport{ + Spec: kubebindv1alpha2.APIServiceExportSpec{ + ClusterScopedIsolation: tt.isolation, + Resources: tt.exportedResources, + }, + } + got := isReferenceAllowed(tt.reference, export) + if got != tt.shouldAllow { + t.Errorf("isReferenceAllowed() = %v, want %v", got, tt.shouldAllow) + } + }) + } +} From c2a56898bde14a65f59a9223f40ba0b22be748e5 Mon Sep 17 00:00:00 2001 From: Karol Szwaj Date: Tue, 23 Dec 2025 16:30:30 +0100 Subject: [PATCH 2/3] add namespaced test cases Signed-off-by: Karol Szwaj On-behalf-of: @SAP karol.szwaj@sap.com --- pkg/resources/resources_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/resources/resources_test.go b/pkg/resources/resources_test.go index 89f5eb83f..33f815b52 100644 --- a/pkg/resources/resources_test.go +++ b/pkg/resources/resources_test.go @@ -962,7 +962,7 @@ func TestSelector_IsClaimed(t *testing.T) { want: true, // Should match because when no namespace JSONPath is provided, namespace matching is delegated to caller }, { - name: "namespace inherited from referencing object when JSONPath not provided", + name: "namespace inherited from referencing object when JSONPath not provided in the namespaced isolation mode", potentiallyReferencedResources: &unstructured.UnstructuredList{ Items: []unstructured. Unstructured{ { @@ -1005,7 +1005,7 @@ func TestSelector_IsClaimed(t *testing.T) { want: true, }, { - name: "namespace inheritance fails when in different namespace", + name: "namespace inheritance fails when in different namespace in the namespaced isolation mode", potentiallyReferencedResources: &unstructured.UnstructuredList{ Items: []unstructured. Unstructured{ { From 00c8228145173a2671799e87ca4dfbb65917fe43 Mon Sep 17 00:00:00 2001 From: Karol Szwaj Date: Tue, 23 Dec 2025 16:32:39 +0100 Subject: [PATCH 3/3] fix lint Signed-off-by: Karol Szwaj On-behalf-of: @SAP karol.szwaj@sap.com --- pkg/resources/resources.go | 6 +-- pkg/resources/resources_test.go | 82 ++++++++++++++++----------------- 2 files changed, 43 insertions(+), 45 deletions(-) diff --git a/pkg/resources/resources.go b/pkg/resources/resources.go index 4ea30e389..d2eedb729 100644 --- a/pkg/resources/resources.go +++ b/pkg/resources/resources.go @@ -86,7 +86,7 @@ func matchesReferences(logger klog.Logger, obj *unstructured.Unstructured, potentiallyReferencedResources *unstructured.UnstructuredList, isolation kubebindv1alpha2.Isolation, - ) bool { +) bool { if len(references) == 0 { return false } @@ -138,8 +138,8 @@ func matchesReferences(logger klog.Logger, namespaceMatches = false objNamespace := obj.GetNamespace() if slices.Contains(namespaceValues, objNamespace) { - namespaceMatches = true - } + namespaceMatches = true + } } if selector.JSONPath.Namespace == "" && isolation == kubebindv1alpha2.IsolationNamespaced { diff --git a/pkg/resources/resources_test.go b/pkg/resources/resources_test.go index 33f815b52..bf1685dfe 100644 --- a/pkg/resources/resources_test.go +++ b/pkg/resources/resources_test.go @@ -32,7 +32,7 @@ func TestSelector_IsClaimed(t *testing.T) { selector kubebindv1alpha2.Selector obj *unstructured.Unstructured potentiallyReferencedResources *unstructured.UnstructuredList - isolation kubebindv1alpha2.Isolation + isolation kubebindv1alpha2.Isolation want bool }{ { @@ -97,7 +97,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: false, + want: false, }, { name: "named resource selector should match exact name and namespace", @@ -119,7 +119,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: true, + want: true, }, { name: "named resource selector should match name when namespace is empty", @@ -141,7 +141,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: true, + want: true, }, { name: "named resource selector should not match different name", @@ -163,7 +163,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: false, + want: false, }, { name: "named resource selector should not match different namespace", @@ -185,7 +185,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: false, + want: false, }, { name: "named resource selector should match one of multiple resources", @@ -211,7 +211,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: true, + want: true, }, { name: "label selector with object having no labels should not match", @@ -232,7 +232,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: false, + want: false, }, { name: "combination of label selector and named resource should match when both match", @@ -262,7 +262,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: true, + want: true, }, { name: "combination of label selector and named resource should match when named resource matches (OR logic)", @@ -292,7 +292,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: true, + want: true, }, { name: "combination of label selector and named resource should match when label matches (OR logic)", @@ -322,7 +322,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: true, + want: true, }, { name: "label-only-secret test case - should sync when has matching label (OR logic)", @@ -360,7 +360,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: true, // Should match because label selector matches (OR logic) + want: true, // Should match because label selector matches (OR logic) }, // JSONPath Reference tests { @@ -404,7 +404,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: true, + want: true, }, { name: "reference selector should match when JSONPath extracts matching name and namespace", @@ -449,7 +449,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: true, + want: true, }, { name: "reference selector should not match when JSONPath extracts different name", @@ -492,7 +492,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: false, + want: false, }, { name: "reference selector should not match when JSONPath extracts different namespace", @@ -537,7 +537,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: false, + want: false, }, { name: "reference selector should handle array JSONPath results", @@ -582,7 +582,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: true, + want: true, }, { name: "reference selector should handle array JSONPath with namespace extraction", @@ -637,7 +637,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: true, + want: true, }, { name: "reference selector should not match with bracket wildcard syntax (unsupported)", @@ -684,10 +684,10 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: false, // Should not match because [*] syntax is not supported by gjson + want: false, // Should not match because [*] syntax is not supported by gjson }, { - name: "reference selector should not match when no referenced resources provided", + name: "reference selector should not match when no referenced resources provided", potentiallyReferencedResources: nil, selector: kubebindv1alpha2.Selector{ References: []kubebindv1alpha2.SelectorReference{ @@ -711,7 +711,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: false, + want: false, }, { name: "reference selector should not match when JSONPath does not exist", @@ -752,7 +752,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: false, + want: false, }, { name: "kubeconfig secret case - should not match when only has kube-bind.io/owner label but selector requires app=sheriff", @@ -808,7 +808,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: false, // Should NOT match because it doesn't have app=sheriff label and is not referenced by Sheriff + want: false, // Should NOT match because it doesn't have app=sheriff label and is not referenced by Sheriff }, { name: "cert-manager secret reference - should match when certificate references secret via secretName", @@ -863,7 +863,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: true, // Should match because certificate's .spec.secretName equals secret name and no namespace JSONPath means namespace matching is handled by caller + want: true, // Should match because certificate's .spec.secretName equals secret name and no namespace JSONPath means namespace matching is handled by caller }, { name: "cert-manager secret reference - should not match when certificate references different secret", @@ -911,7 +911,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: false, // Should not match because certificate's .spec.secretName is "other-secret", not "my-tls-cert" + want: false, // Should not match because certificate's .spec.secretName is "other-secret", not "my-tls-cert" }, { name: "cert-manager secret reference - cross-namespace scenario with no namespace JSONPath", @@ -959,12 +959,12 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationPrefixed, - want: true, // Should match because when no namespace JSONPath is provided, namespace matching is delegated to caller + want: true, // Should match because when no namespace JSONPath is provided, namespace matching is delegated to caller }, - { + { name: "namespace inherited from referencing object when JSONPath not provided in the namespaced isolation mode", potentiallyReferencedResources: &unstructured.UnstructuredList{ - Items: []unstructured. Unstructured{ + Items: []unstructured.Unstructured{ { Object: map[string]any{ "metadata": map[string]any{ @@ -984,30 +984,30 @@ func TestSelector_IsClaimed(t *testing.T) { References: []kubebindv1alpha2.SelectorReference{ { GroupResource: kubebindv1alpha2.GroupResource{ - Group: "mangodb.com", + Group: "mangodb.com", Resource: "mangodbs", }, - JSONPath: &kubebindv1alpha2.JSONPath{ + JSONPath: &kubebindv1alpha2.JSONPath{ Name: "spec.secret.name", }, }, }, }, - obj: &unstructured.Unstructured{ + obj: &unstructured.Unstructured{ Object: map[string]any{ "metadata": map[string]any{ "name": "my-secret", - "namespace": "default", + "namespace": "default", }, }, }, isolation: kubebindv1alpha2.IsolationNamespaced, - want: true, + want: true, }, { name: "namespace inheritance fails when in different namespace in the namespaced isolation mode", potentiallyReferencedResources: &unstructured.UnstructuredList{ - Items: []unstructured. Unstructured{ + Items: []unstructured.Unstructured{ { Object: map[string]any{ "metadata": map[string]any{ @@ -1026,7 +1026,7 @@ func TestSelector_IsClaimed(t *testing.T) { selector: kubebindv1alpha2.Selector{ References: []kubebindv1alpha2.SelectorReference{ { - GroupResource: kubebindv1alpha2.GroupResource{ + GroupResource: kubebindv1alpha2.GroupResource{ Group: "mangodb.com", Resource: "mangodbs", }, @@ -1045,7 +1045,7 @@ func TestSelector_IsClaimed(t *testing.T) { }, }, isolation: kubebindv1alpha2.IsolationNamespaced, - want: false, + want: false, }, } @@ -1060,8 +1060,7 @@ func TestSelector_IsClaimed(t *testing.T) { } } - -func TestReferenceSelector_IsolationMode(t *testing. T) { +func TestReferenceSelector_IsolationMode(t *testing.T) { tests := []struct { name string isolation kubebindv1alpha2.Isolation @@ -1082,7 +1081,7 @@ func TestReferenceSelector_IsolationMode(t *testing. T) { }, { name: "IsolationNamespaced blocks non-exported references", - isolation: kubebindv1alpha2.IsolationNamespaced, + isolation: kubebindv1alpha2.IsolationNamespaced, exportedResources: []kubebindv1alpha2.APIServiceExportResource{ {GroupResource: kubebindv1alpha2.GroupResource{Group: "mangodb.com", Resource: "mangodbs"}}, }, @@ -1115,7 +1114,7 @@ func TestReferenceSelector_IsolationMode(t *testing. T) { }, { name: "IsolationNamespaced allows exported references", - isolation: kubebindv1alpha2.IsolationNamespaced, + isolation: kubebindv1alpha2.IsolationNamespaced, exportedResources: []kubebindv1alpha2.APIServiceExportResource{ {GroupResource: kubebindv1alpha2.GroupResource{Group: "mangodb.com", Resource: "mangodbs"}}, }, @@ -1124,14 +1123,13 @@ func TestReferenceSelector_IsolationMode(t *testing. T) { }, shouldAllow: true, }, - } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { export := &kubebindv1alpha2.APIServiceExport{ Spec: kubebindv1alpha2.APIServiceExportSpec{ - ClusterScopedIsolation: tt.isolation, + ClusterScopedIsolation: tt.isolation, Resources: tt.exportedResources, }, }