diff --git a/integration-test/branch-19/target/output.html b/integration-test/branch-19/target/output.html index 27d28717..a15ccbb6 100644 --- a/integration-test/branch-19/target/output.html +++ b/integration-test/branch-19/target/output.html @@ -59,61 +59,13 @@

Argo CD Diff Preview

Summary:

-
Modified (6):
-± app-b (+25)
+
Modified (4):
 ± cluster-a-cluster-rbac (-25)
-± cluster-b-cluster-rbac (+12)
 ± kustomize-build-options (+2|-2)
 ± owner-a (-12)
 ± owner-b (+12)
-
- -app-b (examples/resource-application-boundary/applicationset.yaml) - - -

ClusterRole: app-b-node-reader

-
- - - - - - - - - - - - - - - -
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: app-b-node-reader
+rules:
+- apiGroups:
+  - ""
+  resources:
+  - nodes
+  verbs:
+  - get
+  - list
+  - watch
-
- -

ClusterRoleBinding: app-b-node-reader

-
- - - - - - - - - - - - - - -
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  name: app-b-node-reader
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: app-b-node-reader
+subjects:
+- apiGroup: rbac.authorization.k8s.io
+  kind: Group
+  name: app-b-readers
-
- -
-
cluster-a-cluster-rbac (examples/cluster-rbac-repro/deployment-config/applicationsets/cluster-rbac.yaml) @@ -160,32 +112,6 @@

ClusterRoleBinding: sympozium-agent-node-reader

-
- -cluster-b-cluster-rbac (examples/cluster-rbac-repro/deployment-config/applicationsets/cluster-rbac.yaml) - - -

ClusterRoleBinding: sympozium-agent-view

-
- - - - - - - - - - - - - - -
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  name: sympozium-agent-view
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: view
+subjects:
+- apiGroup: rbac.authorization.k8s.io
+  kind: Group
+  name: oidc:jwt:platform-cluster:system:serviceaccount:automation:automation-agent
-
- -
-
kustomize-build-options (examples/kustomize-build-options/application.yaml) diff --git a/integration-test/branch-19/target/output.md b/integration-test/branch-19/target/output.md index 31f6b74f..85481d0c 100644 --- a/integration-test/branch-19/target/output.md +++ b/integration-test/branch-19/target/output.md @@ -2,52 +2,13 @@ Summary: ```yaml -Modified (6): -± app-b (+25) +Modified (4): ± cluster-a-cluster-rbac (-25) -± cluster-b-cluster-rbac (+12) ± kustomize-build-options (+2|-2) ± owner-a (-12) ± owner-b (+12) ``` -
-app-b (examples/resource-application-boundary/applicationset.yaml) -
- -#### ClusterRole: app-b-node-reader -```diff -+apiVersion: rbac.authorization.k8s.io/v1 -+kind: ClusterRole -+metadata: -+ name: app-b-node-reader -+rules: -+- apiGroups: -+ - "" -+ resources: -+ - nodes -+ verbs: -+ - get -+ - list -+ - watch -``` -#### ClusterRoleBinding: app-b-node-reader -```diff -+apiVersion: rbac.authorization.k8s.io/v1 -+kind: ClusterRoleBinding -+metadata: -+ name: app-b-node-reader -+roleRef: -+ apiGroup: rbac.authorization.k8s.io -+ kind: ClusterRole -+ name: app-b-node-reader -+subjects: -+- apiGroup: rbac.authorization.k8s.io -+ kind: Group -+ name: app-b-readers -``` -
-
cluster-a-cluster-rbac (examples/cluster-rbac-repro/deployment-config/applicationsets/cluster-rbac.yaml)
@@ -85,27 +46,6 @@ Modified (6): ```
-
-cluster-b-cluster-rbac (examples/cluster-rbac-repro/deployment-config/applicationsets/cluster-rbac.yaml) -
- -#### ClusterRoleBinding: sympozium-agent-view -```diff -+apiVersion: rbac.authorization.k8s.io/v1 -+kind: ClusterRoleBinding -+metadata: -+ name: sympozium-agent-view -+roleRef: -+ apiGroup: rbac.authorization.k8s.io -+ kind: ClusterRole -+ name: view -+subjects: -+- apiGroup: rbac.authorization.k8s.io -+ kind: Group -+ name: oidc:jwt:platform-cluster:system:serviceaccount:automation:automation-agent -``` -
-
kustomize-build-options (examples/kustomize-build-options/application.yaml)
diff --git a/pkg/extract/extract.go b/pkg/extract/extract.go index b9e82344..97343056 100644 --- a/pkg/extract/extract.go +++ b/pkg/extract/extract.go @@ -430,10 +430,6 @@ func normalizeNamespaces( clusterScopedResources map[schema.GroupKind]bool, appName string, ) ([]unstructured.Unstructured, error) { - if destNamespace == "" { - return manifests, nil - } - // Convert to pointer slice for DeduplicateTargetObjects ptrManifests := make([]*unstructured.Unstructured, len(manifests)) for i := range manifests { diff --git a/pkg/extract/extract_test.go b/pkg/extract/extract_test.go index a3e47129..f221ad68 100644 --- a/pkg/extract/extract_test.go +++ b/pkg/extract/extract_test.go @@ -215,6 +215,29 @@ func TestNormalizeNamespacesPreservesSameNamedUnknownResources(t *testing.T) { assert.ElementsMatch(t, []string{"ns-a", "ns-b", "ns-c"}, actualNamespaces) } +func TestNormalizeNamespacesDeduplicatesClusterScopedResourcesWithoutDestinationNamespace(t *testing.T) { + first := unstructured.Unstructured{Object: map[string]any{ + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": map[string]any{ + "name": "node-reader", + }, + "rules": []any{map[string]any{"verbs": []any{"get"}}}, + }} + last := first.DeepCopy() + last.Object["rules"] = []any{map[string]any{"verbs": []any{"get", "list"}}} + + result, err := normalizeNamespaces( + []unstructured.Unstructured{first, *last}, + "", + map[schema.GroupKind]bool{{Group: "rbac.authorization.k8s.io", Kind: "ClusterRole"}: true}, + "test-app", + ) + require.NoError(t, err) + require.Len(t, result, 1) + assert.Equal(t, last.Object, result[0].Object, "Argo CD deduplication should keep the last resource") +} + func TestResourceInfoProviderDefaultsUnknownKindsToNamespaced(t *testing.T) { provider := &resourceInfoProvider{clusterScopedByGk: map[schema.GroupKind]bool{ {Group: "rbac.authorization.k8s.io", Kind: "ClusterRole"}: true, diff --git a/pkg/reposerverextract/extract.go b/pkg/reposerverextract/extract.go index db3f6ab2..569a7e29 100644 --- a/pkg/reposerverextract/extract.go +++ b/pkg/reposerverextract/extract.go @@ -1264,10 +1264,6 @@ func normalizeNamespaces( clusterScopedResources map[schema.GroupKind]bool, appName string, ) ([]unstructured.Unstructured, error) { - if destNamespace == "" { - return manifests, nil - } - ptrManifests := make([]*unstructured.Unstructured, len(manifests)) for i := range manifests { ptrManifests[i] = &manifests[i] diff --git a/pkg/reposerverextract/extract_test.go b/pkg/reposerverextract/extract_test.go index 366c056d..3e664750 100644 --- a/pkg/reposerverextract/extract_test.go +++ b/pkg/reposerverextract/extract_test.go @@ -35,6 +35,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" "sigs.k8s.io/yaml" ) @@ -80,6 +81,29 @@ func assertDefaultProjectFields(t *testing.T, req *repoapiclient.ManifestRequest assert.Equal(t, []string{"*"}, req.ProjectSourceRepos, "source repos must be permissive so helm build errors are not masked as permission errors") } +func TestNormalizeNamespacesDeduplicatesClusterScopedResourcesWithoutDestinationNamespace(t *testing.T) { + first := unstructured.Unstructured{Object: map[string]any{ + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": map[string]any{ + "name": "node-reader", + }, + "rules": []any{map[string]any{"verbs": []any{"get"}}}, + }} + last := first.DeepCopy() + last.Object["rules"] = []any{map[string]any{"verbs": []any{"get", "list"}}} + + result, err := normalizeNamespaces( + []unstructured.Unstructured{first, *last}, + "", + map[schema.GroupKind]bool{{Group: "rbac.authorization.k8s.io", Kind: "ClusterRole"}: true}, + "test-app", + ) + require.NoError(t, err) + require.Len(t, result, 1) + assert.Equal(t, last.Object, result[0].Object, "Argo CD deduplication should keep the last resource") +} + func testRepoSelector(t *testing.T, repo string) *repository.Selector { t.Helper() selector, err := repository.NewSelector(repo, "")