From bd91823ca33ed2e4c3cffcd7ec57ff097c6d6668 Mon Sep 17 00:00:00 2001 From: Patrick Lee Scott Date: Fri, 28 Aug 2026 18:28:11 -0500 Subject: [PATCH 1/2] fix: preserve restricted management policies Refs [[incidents/inc-008-stack-observe-policy-leak]] --- functions/render/000-state-init.yaml.gotmpl | 18 ++++++++++++ .../render/210-github-repository.yaml.gotmpl | 2 +- .../440-zitadel-client-secret.yaml.gotmpl | 4 +-- tests/test-render/main.k | 29 +++++++++++++++++++ 4 files changed, 49 insertions(+), 4 deletions(-) diff --git a/functions/render/000-state-init.yaml.gotmpl b/functions/render/000-state-init.yaml.gotmpl index b2b1b0d..5128703 100644 --- a/functions/render/000-state-init.yaml.gotmpl +++ b/functions/render/000-state-init.yaml.gotmpl @@ -14,6 +14,22 @@ {{- $clusterName := $spec.clusterName | default $name }} {{- $namespace := $spec.namespace | default "argocd" }} {{- $managementPolicies := $spec.managementPolicies | default (list "*") }} +{{- $nonDeletingManagementPolicies := list }} +{{- if has "*" $managementPolicies }} + {{- $nonDeletingManagementPolicies = list "Observe" "Create" "Update" "LateInitialize" }} +{{- else }} + {{- range $policy := $managementPolicies }} + {{- if ne $policy "Delete" }} + {{- $nonDeletingManagementPolicies = append $nonDeletingManagementPolicies $policy }} + {{- end }} + {{- end }} +{{- end }} +{{- $observeUpdateManagementPolicies := list }} +{{- range $policy := list "Observe" "Update" }} + {{- if or (has "*" $managementPolicies) (has $policy $managementPolicies) }} + {{- $observeUpdateManagementPolicies = append $observeUpdateManagementPolicies $policy }} + {{- end }} +{{- end }} # Labels {{- $defaultLabels := dict @@ -163,6 +179,8 @@ "clusterName" $clusterName "namespace" $namespace "managementPolicies" $managementPolicies + "nonDeletingManagementPolicies" $nonDeletingManagementPolicies + "observeUpdateManagementPolicies" $observeUpdateManagementPolicies "labels" $labels "helmProviderConfigRef" $helmProviderConfigRef "kubernetesProviderConfigRef" $k8sProviderConfigRef diff --git a/functions/render/210-github-repository.yaml.gotmpl b/functions/render/210-github-repository.yaml.gotmpl index d7e7fa1..1033c11 100644 --- a/functions/render/210-github-repository.yaml.gotmpl +++ b/functions/render/210-github-repository.yaml.gotmpl @@ -20,7 +20,7 @@ spec: {{- if $repo.allowDelete }} managementPolicies: {{ $state.managementPolicies | toJson }} {{- else }} - managementPolicies: ["Observe", "Create", "Update", "LateInitialize"] + managementPolicies: {{ $state.nonDeletingManagementPolicies | toJson }} {{- end }} forProvider: name: {{ $repo.name }} diff --git a/functions/render/440-zitadel-client-secret.yaml.gotmpl b/functions/render/440-zitadel-client-secret.yaml.gotmpl index 7442e17..340716e 100644 --- a/functions/render/440-zitadel-client-secret.yaml.gotmpl +++ b/functions/render/440-zitadel-client-secret.yaml.gotmpl @@ -16,9 +16,7 @@ metadata: {{ setResourceNameAnnotation "zitadel-client-secret" }} labels: {{ $state.labels | toJson }} spec: - managementPolicies: - - Observe - - Update + managementPolicies: {{ $state.observeUpdateManagementPolicies | toJson }} forProvider: manifest: apiVersion: v1 diff --git a/tests/test-render/main.k b/tests/test-render/main.k index 705a945..6186a13 100644 --- a/tests/test-render/main.k +++ b/tests/test-render/main.k @@ -78,6 +78,35 @@ _items = [ } } + # ========================================================================== + # Test 1b: Restricted parent policies never expand on the protected repo + # ========================================================================== + metav1alpha1.CompositionTest { + metadata.name = "observe-only-repository-stays-observe-only" + spec = { + compositionPath = "apis/gitopsstacks/composition.yaml" + xrdPath = "apis/gitopsstacks/definition.yaml" + timeoutSeconds = 60 + validate = False + xr = stacksv1alpha1.GitopsStack { + metadata.name = "observe-only" + spec = { + clusterName = "test-cluster" + managementPolicies = ["Observe", "LateInitialize"] + repository.org = "hops-ops" + } + } + assertResources = [ + { + apiVersion = "repo.github.m.upbound.io/v1alpha1" + kind = "Repository" + metadata.name = "test-cluster-gitops" + spec.managementPolicies = ["Observe", "LateInitialize"] + } + ] + } + } + # ========================================================================== # Test 2: Custom labels merged with defaults # ========================================================================== From 9cefd2e635e0d1426ae41763ac2647fc94cc0bb9 Mon Sep 17 00:00:00 2001 From: Patrick Lee Scott Date: Fri, 28 Aug 2026 18:43:43 -0500 Subject: [PATCH 2/2] fix: preserve empty management policies --- functions/render/000-state-init.yaml.gotmpl | 5 ++- tests/test-render/main.k | 35 +++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/functions/render/000-state-init.yaml.gotmpl b/functions/render/000-state-init.yaml.gotmpl index 5128703..4f9a91a 100644 --- a/functions/render/000-state-init.yaml.gotmpl +++ b/functions/render/000-state-init.yaml.gotmpl @@ -13,7 +13,10 @@ {{- $name := $metadata.name | default "gitops" }} {{- $clusterName := $spec.clusterName | default $name }} {{- $namespace := $spec.namespace | default "argocd" }} -{{- $managementPolicies := $spec.managementPolicies | default (list "*") }} +{{- $managementPolicies := list "*" }} +{{- if hasKey $spec "managementPolicies" }} + {{- $managementPolicies = get $spec "managementPolicies" }} +{{- end }} {{- $nonDeletingManagementPolicies := list }} {{- if has "*" $managementPolicies }} {{- $nonDeletingManagementPolicies = list "Observe" "Create" "Update" "LateInitialize" }} diff --git a/tests/test-render/main.k b/tests/test-render/main.k index 6186a13..c5fc420 100644 --- a/tests/test-render/main.k +++ b/tests/test-render/main.k @@ -107,6 +107,41 @@ _items = [ } } + # ========================================================================== + # Test 1c: An explicit empty policy list stays empty + # ========================================================================== + metav1alpha1.CompositionTest { + metadata.name = "empty-management-policies-stay-empty" + spec = { + compositionPath = "apis/gitopsstacks/composition.yaml" + xrdPath = "apis/gitopsstacks/definition.yaml" + timeoutSeconds = 60 + validate = False + xr = stacksv1alpha1.GitopsStack { + metadata.name = "no-authority" + spec = { + clusterName = "test-cluster" + managementPolicies = [] + repository.org = "hops-ops" + } + } + assertResources = [ + { + apiVersion = "helm.m.crossplane.io/v1beta1" + kind = "Release" + metadata.name = "argocd" + spec.managementPolicies = [] + } + { + apiVersion = "repo.github.m.upbound.io/v1alpha1" + kind = "Repository" + metadata.name = "test-cluster-gitops" + spec.managementPolicies = [] + } + ] + } + } + # ========================================================================== # Test 2: Custom labels merged with defaults # ==========================================================================