From 671a4cc9bbecf20a1dd5da810eb36a6b5aa1940f Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 21 Mar 2026 14:05:53 +0100 Subject: [PATCH 1/4] Migration from PlacementRule to Placement API Changes per pair: - PlacementBinding: kind: PlacementRule -> kind: Placement, apiGroup: apps.open-cluster-management.io -> apiGroup: cluster.open-cluster-management.io - PlacementRule -> Placement: apiVersion: apps.open-cluster-management.io/v1 -> apiVersion: cluster.open-cluster-management.io/v1beta1, kind: PlacementRule -> kind: Placement, removed clusterConditions --- templates/_helpers.tpl | 76 +++++++++++-------- templates/policies/acm-hub-ca-policy.yaml | 39 ++++------ templates/policies/application-policies.yaml | 13 ++-- templates/policies/ocp-gitops-policy.yaml | 26 +++---- templates/policies/private-repo-policies.yaml | 38 +++++----- tests/application_policy_test.yaml | 10 +-- 6 files changed, 95 insertions(+), 107 deletions(-) diff --git a/templates/_helpers.tpl b/templates/_helpers.tpl index e07e38c..f6349ba 100644 --- a/templates/_helpers.tpl +++ b/templates/_helpers.tpl @@ -79,47 +79,57 @@ if this chart gets DeleteSpokeChildApps, it will set deletePattern to DeleteChil {{- $isMap := kindIs "map" $rawLabels -}} {{- $hasAny := and $rawLabels (gt (len $rawLabels) 0) -}} {{- if $cs -}} -clusterSelector: {{ $cs | toPrettyJson }} +predicates: + - requiredClusterSelector: + labelSelector: {{ $cs | toPrettyJson | nindent 8 }} {{- else if not $hasAny -}} -clusterSelector: - matchExpressions: - - key: local-cluster - operator: NotIn - values: - - 'true' - matchLabels: - clusterGroup: {{ $g.name }} +predicates: + - requiredClusterSelector: + labelSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' + matchLabels: + clusterGroup: {{ $g.name }} {{- else if $isSlice -}} -clusterSelector: - matchExpressions: - - key: local-cluster - operator: NotIn - values: - - 'true' - matchLabels: +predicates: + - requiredClusterSelector: + labelSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' + matchLabels: {{- range $rawLabels }} - {{ .name }}: {{ .value }} + {{ .name }}: {{ .value }} {{- end }} {{- else if $isMap -}} -clusterSelector: - matchExpressions: - - key: local-cluster - operator: NotIn - values: - - 'true' - matchLabels: +predicates: + - requiredClusterSelector: + labelSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' + matchLabels: {{- range $k, $v := $rawLabels }} - {{ $k }}: {{ $v }} + {{ $k }}: {{ $v }} {{- end }} {{- else -}} {{- /* Fallback: unknown acmlabels shape then default to group */}} -clusterSelector: - matchExpressions: - - key: local-cluster - operator: NotIn - values: - - 'true' - matchLabels: - clusterGroup: {{ $g.name }} +predicates: + - requiredClusterSelector: + labelSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' + matchLabels: + clusterGroup: {{ $g.name }} {{- end -}} {{- end -}} {{- /*acm.app.clusterSelector */}} diff --git a/templates/policies/acm-hub-ca-policy.yaml b/templates/policies/acm-hub-ca-policy.yaml index 9612814..6e2dfa5 100644 --- a/templates/policies/acm-hub-ca-policy.yaml +++ b/templates/policies/acm-hub-ca-policy.yaml @@ -47,24 +47,21 @@ metadata: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true placementRef: name: hub-argo-ca-{{ .name }}-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io + kind: Placement + apiGroup: cluster.open-cluster-management.io subjects: - name: hub-argo-ca-{{ .name }}-policy kind: Policy apiGroup: policy.open-cluster-management.io --- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule +apiVersion: cluster.open-cluster-management.io/v1beta1 +kind: Placement metadata: name: hub-argo-ca-{{ .name }}-placement annotations: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable -{{- include "acm.app.clusterSelector" (dict +{{- include "acm.app.clusterSelector" (dict "clusterSelector" .clusterSelector "group" $group ) | nindent 2 }} @@ -127,24 +124,21 @@ metadata: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true placementRef: name: {{ .name }}-acm-hub-ca-policy-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io + kind: Placement + apiGroup: cluster.open-cluster-management.io subjects: - name: {{ .name }}-acm-hub-ca-policy kind: Policy apiGroup: policy.open-cluster-management.io --- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule +apiVersion: cluster.open-cluster-management.io/v1beta1 +kind: Placement metadata: name: {{ .name }}-acm-hub-ca-policy-placement annotations: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable -{{- include "acm.app.clusterSelector" (dict +{{- include "acm.app.clusterSelector" (dict "clusterSelector" .clusterSelector "group" $group ) | nindent 2 }} @@ -193,24 +187,21 @@ metadata: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true placementRef: name: {{ .name }}-hub-argo-ca-gitops-policy-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io + kind: Placement + apiGroup: cluster.open-cluster-management.io subjects: - name: {{ .name }}-hub-argo-ca-gitops-policy kind: Policy apiGroup: policy.open-cluster-management.io --- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule +apiVersion: cluster.open-cluster-management.io/v1beta1 +kind: Placement metadata: name: {{ .name }}-hub-argo-ca-gitops-policy-placement annotations: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable -{{- include "acm.app.clusterSelector" (dict +{{- include "acm.app.clusterSelector" (dict "clusterSelector" .clusterSelector "group" $group ) | nindent 2 }} diff --git a/templates/policies/application-policies.yaml b/templates/policies/application-policies.yaml index 51a7ec0..434bb64 100644 --- a/templates/policies/application-policies.yaml +++ b/templates/policies/application-policies.yaml @@ -177,24 +177,21 @@ metadata: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true placementRef: name: {{ .name }}-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io + kind: Placement + apiGroup: cluster.open-cluster-management.io subjects: - name: {{ .name }}-clustergroup-policy kind: Policy apiGroup: policy.open-cluster-management.io --- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule +apiVersion: cluster.open-cluster-management.io/v1beta1 +kind: Placement metadata: name: {{ .name }}-placement annotations: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable -{{- include "acm.app.clusterSelector" (dict +{{- include "acm.app.clusterSelector" (dict "clusterSelector" .clusterSelector "group" $group ) | nindent 2 }} diff --git a/templates/policies/ocp-gitops-policy.yaml b/templates/policies/ocp-gitops-policy.yaml index 9b731d5..7d5b0b7 100644 --- a/templates/policies/ocp-gitops-policy.yaml +++ b/templates/policies/ocp-gitops-policy.yaml @@ -78,24 +78,21 @@ metadata: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true placementRef: name: {{ .name }}-gitops-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io + kind: Placement + apiGroup: cluster.open-cluster-management.io subjects: - name: {{ .name }}-gitops-policy kind: Policy apiGroup: policy.open-cluster-management.io --- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule +apiVersion: cluster.open-cluster-management.io/v1beta1 +kind: Placement metadata: name: {{ .name }}-gitops-placement annotations: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable -{{- include "acm.app.clusterSelector" (dict +{{- include "acm.app.clusterSelector" (dict "clusterSelector" .clusterSelector "group" $group ) | nindent 2 }} @@ -310,24 +307,21 @@ metadata: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true placementRef: name: {{ .name }}-gitops-placement-argocd - kind: PlacementRule - apiGroup: apps.open-cluster-management.io + kind: Placement + apiGroup: cluster.open-cluster-management.io subjects: - name: {{ .name }}-gitops-policy-argocd kind: Policy apiGroup: policy.open-cluster-management.io --- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule +apiVersion: cluster.open-cluster-management.io/v1beta1 +kind: Placement metadata: name: {{ .name }}-gitops-placement-argocd annotations: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable -{{- include "acm.app.clusterSelector" (dict +{{- include "acm.app.clusterSelector" (dict "clusterSelector" .clusterSelector "group" $group ) | nindent 2 }} diff --git a/templates/policies/private-repo-policies.yaml b/templates/policies/private-repo-policies.yaml index aa86b9f..dc6f451 100644 --- a/templates/policies/private-repo-policies.yaml +++ b/templates/policies/private-repo-policies.yaml @@ -62,24 +62,21 @@ metadata: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true placementRef: name: private-{{ .name }}-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io + kind: Placement + apiGroup: cluster.open-cluster-management.io subjects: - name: private-{{ .name }}-policy kind: Policy apiGroup: policy.open-cluster-management.io --- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule +apiVersion: cluster.open-cluster-management.io/v1beta1 +kind: Placement metadata: name: private-{{ .name }}-placement annotations: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable -{{- include "acm.app.clusterSelector" (dict +{{- include "acm.app.clusterSelector" (dict "clusterSelector" .clusterSelector "group" $group ) | nindent 2 }} @@ -129,29 +126,28 @@ metadata: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true placementRef: name: vp-private-hub-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io + kind: Placement + apiGroup: cluster.open-cluster-management.io subjects: - name: vp-private-hub-policy kind: Policy apiGroup: policy.open-cluster-management.io --- -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule +apiVersion: cluster.open-cluster-management.io/v1beta1 +kind: Placement metadata: name: vp-private-hub-placement annotations: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: local-cluster - operator: In - values: - - 'true' + predicates: + - requiredClusterSelector: + labelSelector: + matchExpressions: + - key: local-cluster + operator: In + values: + - 'true' --- {{ end }}{{- /* if ishubcluster */}} {{- end }}{{- /* if $.Values.global.privateRepo */}} diff --git a/tests/application_policy_test.yaml b/tests/application_policy_test.yaml index a017090..fa7eb00 100644 --- a/tests/application_policy_test.yaml +++ b/tests/application_policy_test.yaml @@ -14,7 +14,7 @@ tests: path: metadata.name value: group-one-placement equal: - path: spec.clusterSelector.matchLabels.clusterGroup + path: spec.predicates[0].requiredClusterSelector.labelSelector.matchLabels.clusterGroup value: group-one - it: Should render the clusterselector when using acmlabels with an override @@ -33,7 +33,7 @@ tests: path: metadata.name value: group-two-placement equal: - path: spec.clusterSelector.matchLabels.clusterGroup + path: spec.predicates[0].requiredClusterSelector.labelSelector.matchLabels.clusterGroup value: group-two - it: Should render the clusterselector when using json @@ -50,7 +50,7 @@ tests: path: metadata.name value: group-one-placement equal: - path: spec.clusterSelector + path: spec.predicates[0].requiredClusterSelector.labelSelector value: {foo: bar} - it: Should render the clusterselector when acmlabels is empty @@ -67,7 +67,7 @@ tests: path: metadata.name value: group-two-placement equal: - path: spec.clusterSelector.matchLabels.clusterGroup + path: spec.predicates[0].requiredClusterSelector.labelSelector.matchLabels.clusterGroup value: group-two - it: Should render the clusterselector when acmlabels is unset @@ -84,7 +84,7 @@ tests: path: metadata.name value: group-two-placement equal: - path: spec.clusterSelector.matchLabels.clusterGroup + path: spec.predicates[0].requiredClusterSelector.labelSelector.matchLabels.clusterGroup value: group-two # Test for openshift-gitops-cluster-admin-rolebinding CRB From e4f2008d9a52de01dce4b3fb05339cf84fd277a6 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 21 Mar 2026 14:49:12 +0100 Subject: [PATCH 2/4] Add managedclustersetbinding --- templates/policies/managedclustersetbinding.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 templates/policies/managedclustersetbinding.yaml diff --git a/templates/policies/managedclustersetbinding.yaml b/templates/policies/managedclustersetbinding.yaml new file mode 100644 index 0000000..1348a58 --- /dev/null +++ b/templates/policies/managedclustersetbinding.yaml @@ -0,0 +1,12 @@ +# ManagedClusterSetBinding is required for the Placement API to schedule +# clusters from the default ManagedClusterSet in this namespace. +{{- if .Values.clusterGroup.managedClusterGroups }} +apiVersion: cluster.open-cluster-management.io/v1beta2 +kind: ManagedClusterSetBinding +metadata: + name: default + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterSet: default +{{- end }} From 6e75ecaa5c2dfe4b52b7873d91fbd9d0617520e3 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 21 Mar 2026 15:31:17 +0100 Subject: [PATCH 3/4] Stop using musthaveonly for the configmap It causes flapping of the status of the subscription because the ca operator will fill in the data, and acm will try to empty it again --- templates/policies/ocp-gitops-policy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/policies/ocp-gitops-policy.yaml b/templates/policies/ocp-gitops-policy.yaml index 7d5b0b7..5d6c47c 100644 --- a/templates/policies/ocp-gitops-policy.yaml +++ b/templates/policies/ocp-gitops-policy.yaml @@ -44,7 +44,7 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" - - complianceType: mustonlyhave + - complianceType: musthave objectDefinition: kind: ConfigMap apiVersion: v1 From 91922a461ced0a14cdbce4cf6ad09202054c0847 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 23 Mar 2026 10:44:47 +0100 Subject: [PATCH 4/4] Add some more unit tests --- tests/placement_api_migration_test.yaml | 534 ++++++++++++++++++++++++ 1 file changed, 534 insertions(+) create mode 100644 tests/placement_api_migration_test.yaml diff --git a/tests/placement_api_migration_test.yaml b/tests/placement_api_migration_test.yaml new file mode 100644 index 0000000..6a24f88 --- /dev/null +++ b/tests/placement_api_migration_test.yaml @@ -0,0 +1,534 @@ +suite: Test Placement API migration (PlacementRule -> Placement) +templates: + - templates/policies/application-policies.yaml + - templates/policies/ocp-gitops-policy.yaml + - templates/policies/acm-hub-ca-policy.yaml + - templates/policies/private-repo-policies.yaml +release: + name: release-test +tests: + - it: "application-policies: PlacementBinding should reference kind Placement" + template: templates/policies/application-policies.yaml + values: + - ./clusterselector_values.yaml + set: + global: + multiSourceSupport: true + multiSourceRepoUrl: "https://charts.example.com" + multiSourceTargetRevision: "0.1.0" + asserts: + - documentSelector: + path: metadata.name + value: group-one-placement-binding + equal: + path: placementRef.kind + value: Placement + - documentSelector: + path: metadata.name + value: group-one-placement-binding + equal: + path: placementRef.apiGroup + value: cluster.open-cluster-management.io + + - it: "application-policies: Placement should use cluster.open-cluster-management.io/v1beta1" + template: templates/policies/application-policies.yaml + values: + - ./clusterselector_values.yaml + set: + global: + multiSourceSupport: true + multiSourceRepoUrl: "https://charts.example.com" + multiSourceTargetRevision: "0.1.0" + asserts: + - documentSelector: + path: metadata.name + value: group-one-placement + isKind: + of: Placement + - documentSelector: + path: metadata.name + value: group-one-placement + isAPIVersion: + of: cluster.open-cluster-management.io/v1beta1 + - documentSelector: + path: metadata.name + value: group-one-placement + isNull: + path: spec.clusterConditions + + - it: "ocp-gitops: PlacementBinding should reference kind Placement (gitops)" + template: templates/policies/ocp-gitops-policy.yaml + values: + - ./clusterselector_values.yaml + asserts: + - documentSelector: + path: metadata.name + value: group-one-gitops-placement-binding + equal: + path: placementRef.kind + value: Placement + - documentSelector: + path: metadata.name + value: group-one-gitops-placement-binding + equal: + path: placementRef.apiGroup + value: cluster.open-cluster-management.io + + - it: "ocp-gitops: Placement should use cluster.open-cluster-management.io/v1beta1 (gitops)" + template: templates/policies/ocp-gitops-policy.yaml + values: + - ./clusterselector_values.yaml + asserts: + - documentSelector: + path: metadata.name + value: group-one-gitops-placement + isKind: + of: Placement + - documentSelector: + path: metadata.name + value: group-one-gitops-placement + isAPIVersion: + of: cluster.open-cluster-management.io/v1beta1 + - documentSelector: + path: metadata.name + value: group-one-gitops-placement + isNull: + path: spec.clusterConditions + + - it: "ocp-gitops: PlacementBinding should reference kind Placement (argocd)" + template: templates/policies/ocp-gitops-policy.yaml + values: + - ./clusterselector_values.yaml + asserts: + - documentSelector: + path: metadata.name + value: group-one-gitops-placement-binding-argocd + equal: + path: placementRef.kind + value: Placement + - documentSelector: + path: metadata.name + value: group-one-gitops-placement-binding-argocd + equal: + path: placementRef.apiGroup + value: cluster.open-cluster-management.io + + - it: "ocp-gitops: Placement should use cluster.open-cluster-management.io/v1beta1 (argocd)" + template: templates/policies/ocp-gitops-policy.yaml + values: + - ./clusterselector_values.yaml + asserts: + - documentSelector: + path: metadata.name + value: group-one-gitops-placement-argocd + isKind: + of: Placement + - documentSelector: + path: metadata.name + value: group-one-gitops-placement-argocd + isAPIVersion: + of: cluster.open-cluster-management.io/v1beta1 + - documentSelector: + path: metadata.name + value: group-one-gitops-placement-argocd + isNull: + path: spec.clusterConditions + + - it: "ocp-gitops: Placement predicates should have correct clusterSelector structure" + template: templates/policies/ocp-gitops-policy.yaml + values: + - ./clusterselector_values.yaml + asserts: + - documentSelector: + path: metadata.name + value: group-one-gitops-placement + equal: + path: spec.predicates[0].requiredClusterSelector.labelSelector.matchLabels.clusterGroup + value: group-one + - documentSelector: + path: metadata.name + value: group-one-gitops-placement + contains: + path: spec.predicates[0].requiredClusterSelector.labelSelector.matchExpressions + content: + key: local-cluster + operator: NotIn + values: + - "true" + + - it: "acm-hub-ca: PlacementBinding should reference kind Placement (hub-argo-ca)" + template: templates/policies/acm-hub-ca-policy.yaml + set: + global: + repoURL: https://github.com/test/repo + hubClusterDomain: "apps.hub.example.com" + localClusterDomain: "apps.hub.example.com" + secretStore: + backend: "vault" + pattern: "test-pattern" + clusterGroup: + isHubCluster: true + managedClusterGroups: + testRegion: + name: region-one + labels: + - name: clusterGroup + value: region-one + asserts: + - documentSelector: + path: metadata.name + value: hub-argo-ca-region-one-placement-binding + equal: + path: placementRef.kind + value: Placement + - documentSelector: + path: metadata.name + value: hub-argo-ca-region-one-placement-binding + equal: + path: placementRef.apiGroup + value: cluster.open-cluster-management.io + + - it: "acm-hub-ca: Placement should use cluster.open-cluster-management.io/v1beta1 (hub-argo-ca)" + template: templates/policies/acm-hub-ca-policy.yaml + set: + global: + repoURL: https://github.com/test/repo + hubClusterDomain: "apps.hub.example.com" + localClusterDomain: "apps.hub.example.com" + secretStore: + backend: "vault" + pattern: "test-pattern" + clusterGroup: + isHubCluster: true + managedClusterGroups: + testRegion: + name: region-one + labels: + - name: clusterGroup + value: region-one + asserts: + - documentSelector: + path: metadata.name + value: hub-argo-ca-region-one-placement + isKind: + of: Placement + - documentSelector: + path: metadata.name + value: hub-argo-ca-region-one-placement + isAPIVersion: + of: cluster.open-cluster-management.io/v1beta1 + - documentSelector: + path: metadata.name + value: hub-argo-ca-region-one-placement + isNull: + path: spec.clusterConditions + + - it: "acm-hub-ca: All three PlacementBindings should reference kind Placement (vault)" + template: templates/policies/acm-hub-ca-policy.yaml + set: + global: + repoURL: https://github.com/test/repo + hubClusterDomain: "apps.hub.example.com" + localClusterDomain: "apps.hub.example.com" + secretStore: + backend: "vault" + pattern: "test-pattern" + clusterGroup: + isHubCluster: true + managedClusterGroups: + testRegion: + name: region-one + labels: + - name: clusterGroup + value: region-one + asserts: + - documentSelector: + path: metadata.name + value: region-one-acm-hub-ca-policy-placement-binding + equal: + path: placementRef.kind + value: Placement + - documentSelector: + path: metadata.name + value: region-one-acm-hub-ca-policy-placement-binding + equal: + path: placementRef.apiGroup + value: cluster.open-cluster-management.io + - documentSelector: + path: metadata.name + value: region-one-hub-argo-ca-gitops-policy-binding + equal: + path: placementRef.kind + value: Placement + - documentSelector: + path: metadata.name + value: region-one-hub-argo-ca-gitops-policy-binding + equal: + path: placementRef.apiGroup + value: cluster.open-cluster-management.io + + - it: "acm-hub-ca: All three Placements should use correct apiVersion (vault)" + template: templates/policies/acm-hub-ca-policy.yaml + set: + global: + repoURL: https://github.com/test/repo + hubClusterDomain: "apps.hub.example.com" + localClusterDomain: "apps.hub.example.com" + secretStore: + backend: "vault" + pattern: "test-pattern" + clusterGroup: + isHubCluster: true + managedClusterGroups: + testRegion: + name: region-one + labels: + - name: clusterGroup + value: region-one + asserts: + - documentSelector: + path: metadata.name + value: region-one-acm-hub-ca-policy-placement + isKind: + of: Placement + - documentSelector: + path: metadata.name + value: region-one-acm-hub-ca-policy-placement + isAPIVersion: + of: cluster.open-cluster-management.io/v1beta1 + - documentSelector: + path: metadata.name + value: region-one-acm-hub-ca-policy-placement + isNull: + path: spec.clusterConditions + - documentSelector: + path: metadata.name + value: region-one-hub-argo-ca-gitops-policy-placement + isKind: + of: Placement + - documentSelector: + path: metadata.name + value: region-one-hub-argo-ca-gitops-policy-placement + isAPIVersion: + of: cluster.open-cluster-management.io/v1beta1 + - documentSelector: + path: metadata.name + value: region-one-hub-argo-ca-gitops-policy-placement + isNull: + path: spec.clusterConditions + + - it: "acm-hub-ca: Placement predicates should have correct clusterSelector structure" + template: templates/policies/acm-hub-ca-policy.yaml + set: + global: + repoURL: https://github.com/test/repo + hubClusterDomain: "apps.hub.example.com" + localClusterDomain: "apps.hub.example.com" + secretStore: + backend: "vault" + pattern: "test-pattern" + clusterGroup: + isHubCluster: true + managedClusterGroups: + testRegion: + name: region-one + labels: + - name: clusterGroup + value: region-one + asserts: + - documentSelector: + path: metadata.name + value: hub-argo-ca-region-one-placement + equal: + path: spec.predicates[0].requiredClusterSelector.labelSelector.matchLabels.clusterGroup + value: region-one + + - it: "private-repo: PlacementBinding should reference kind Placement (per-group)" + template: templates/policies/private-repo-policies.yaml + set: + global: + repoURL: https://github.com/test/repo + hubClusterDomain: "apps.hub.example.com" + localClusterDomain: "apps.hub.example.com" + privateRepo: true + pattern: "test-pattern" + clusterGroup: + isHubCluster: true + managedClusterGroups: + testRegion: + name: region-one + labels: + - name: clusterGroup + value: region-one + asserts: + - documentSelector: + path: metadata.name + value: private-region-one-placement-binding + equal: + path: placementRef.kind + value: Placement + - documentSelector: + path: metadata.name + value: private-region-one-placement-binding + equal: + path: placementRef.apiGroup + value: cluster.open-cluster-management.io + + - it: "private-repo: Placement should use cluster.open-cluster-management.io/v1beta1 (per-group)" + template: templates/policies/private-repo-policies.yaml + set: + global: + repoURL: https://github.com/test/repo + hubClusterDomain: "apps.hub.example.com" + localClusterDomain: "apps.hub.example.com" + privateRepo: true + pattern: "test-pattern" + clusterGroup: + isHubCluster: true + managedClusterGroups: + testRegion: + name: region-one + labels: + - name: clusterGroup + value: region-one + asserts: + - documentSelector: + path: metadata.name + value: private-region-one-placement + isKind: + of: Placement + - documentSelector: + path: metadata.name + value: private-region-one-placement + isAPIVersion: + of: cluster.open-cluster-management.io/v1beta1 + - documentSelector: + path: metadata.name + value: private-region-one-placement + isNull: + path: spec.clusterConditions + + - it: "private-repo: Hub PlacementBinding should reference kind Placement" + template: templates/policies/private-repo-policies.yaml + set: + global: + repoURL: https://github.com/test/repo + hubClusterDomain: "apps.hub.example.com" + localClusterDomain: "apps.hub.example.com" + privateRepo: true + pattern: "test-pattern" + clusterGroup: + isHubCluster: true + managedClusterGroups: + testRegion: + name: region-one + labels: + - name: clusterGroup + value: region-one + asserts: + - documentSelector: + path: metadata.name + value: vp-private-hub-placement-binding + equal: + path: placementRef.kind + value: Placement + - documentSelector: + path: metadata.name + value: vp-private-hub-placement-binding + equal: + path: placementRef.apiGroup + value: cluster.open-cluster-management.io + + - it: "private-repo: Hub Placement should use predicates with local-cluster selector" + template: templates/policies/private-repo-policies.yaml + set: + global: + repoURL: https://github.com/test/repo + hubClusterDomain: "apps.hub.example.com" + localClusterDomain: "apps.hub.example.com" + privateRepo: true + pattern: "test-pattern" + clusterGroup: + isHubCluster: true + managedClusterGroups: + testRegion: + name: region-one + labels: + - name: clusterGroup + value: region-one + asserts: + - documentSelector: + path: metadata.name + value: vp-private-hub-placement + isKind: + of: Placement + - documentSelector: + path: metadata.name + value: vp-private-hub-placement + isAPIVersion: + of: cluster.open-cluster-management.io/v1beta1 + - documentSelector: + path: metadata.name + value: vp-private-hub-placement + isNull: + path: spec.clusterConditions + - documentSelector: + path: metadata.name + value: vp-private-hub-placement + contains: + path: spec.predicates[0].requiredClusterSelector.labelSelector.matchExpressions + content: + key: local-cluster + operator: In + values: + - "true" + + - it: "application-policies: Placement predicates work with map-style labels" + template: templates/policies/application-policies.yaml + values: + - ./clusterselector_values.yaml + set: + global: + multiSourceSupport: true + multiSourceRepoUrl: "https://charts.example.com" + multiSourceTargetRevision: "0.1.0" + clusterGroup: + managedClusterGroups: + exampleRegion: + name: group-one + acmlabels: + environment: production + region: us-east + asserts: + - documentSelector: + path: metadata.name + value: group-one-placement + isKind: + of: Placement + - documentSelector: + path: metadata.name + value: group-one-placement + isAPIVersion: + of: cluster.open-cluster-management.io/v1beta1 + - documentSelector: + path: metadata.name + value: group-one-placement + equal: + path: spec.predicates[0].requiredClusterSelector.labelSelector.matchLabels.environment + value: production + - documentSelector: + path: metadata.name + value: group-one-placement + equal: + path: spec.predicates[0].requiredClusterSelector.labelSelector.matchLabels.region + value: us-east + - documentSelector: + path: metadata.name + value: group-one-placement + contains: + path: spec.predicates[0].requiredClusterSelector.labelSelector.matchExpressions + content: + key: local-cluster + operator: NotIn + values: + - "true"