From f2215f746338b1c38f5fdfc2db096059935e8a4b Mon Sep 17 00:00:00 2001 From: Tomer Figenblat Date: Tue, 16 Apr 2024 17:41:21 -0400 Subject: [PATCH 01/77] feat: add support for hive clusterdeployments creating spokes Co-authored-by: Alejandro Villegas Signed-off-by: Tomer Figenblat --- .../provision/clusterdeployment.yaml | 71 +++++++++++++++++++ acm/templates/provision/clusterpool.yaml | 15 +--- .../provision/managedclusterset.yaml | 16 +++++ acm/templates/provision/secrets-aws.yaml | 65 +++++++++++------ acm/templates/provision/secrets-azure.yaml | 65 +++++++++++------ acm/templates/provision/secrets-common.yaml | 59 ++++++++++----- acm/values.yaml | 21 +++++- clustergroup/values.schema.json | 32 +++++++++ 8 files changed, 267 insertions(+), 77 deletions(-) create mode 100644 acm/templates/provision/clusterdeployment.yaml create mode 100644 acm/templates/provision/managedclusterset.yaml diff --git a/acm/templates/provision/clusterdeployment.yaml b/acm/templates/provision/clusterdeployment.yaml new file mode 100644 index 00000000..cc37c161 --- /dev/null +++ b/acm/templates/provision/clusterdeployment.yaml @@ -0,0 +1,71 @@ +{{- range .Values.clusterGroup.managedClusterGroups }} +{{- $group := . }} + +{{- range $group.clusterDeployments}} +{{ $cluster := . }} +{{- $deploymentName := print $cluster.name "-" $group.name }} + +{{- $cloud := "None" }} +{{- $region := "None" }} + +{{- if $cluster.platform.aws }} +{{- $cloud = "aws" }} +{{- $region = $cluster.platform.aws.region }} +{{- else if $cluster.platform.azure }} +{{- $cloud = "azure" }} +{{- $region = $cluster.platform.azure.region }} +{{- end }} + +--- +apiVersion: v1 +kind: Namespace +metadata: + name: {{ $deploymentName }} + +--- +apiVersion: hive.openshift.io/v1 +kind: ClusterDeployment +metadata: + name: {{ $deploymentName }} + namespace: {{ $deploymentName }} + labels: + vendor: OpenShift +spec: + baseDomain: {{ $cluster.baseDomain }} + clusterName: {{ $deploymentName }} + installAttemptsLimit: 1 + platform: + {{ $cloud }}: + credentialsSecretRef: + name: {{ $deploymentName }}-creds + region: {{ $region }} + provisioning: + installConfigSecretRef: + name: {{ $deploymentName }}-install-config + sshPrivateKeySecretRef: + name: {{ $deploymentName }}-ssh-private-key + imageSetRef: + name: img{{ $cluster.openshiftVersion }}-multi-appsub + pullSecretRef: + name: {{ $deploymentName }}-pull-secret + +--- +apiVersion: cluster.open-cluster-management.io/v1 +kind: ManagedCluster +metadata: + labels: + cluster.open-cluster-management.io/clusterset: {{ $group.name }} + {{- if (not $group.acmlabels) }} + clusterGroup: {{ $group.name }} + {{- else if eq (len $group.acmlabels) 0 }} + clusterGroup: {{ $group.name }} + {{- else }} + {{- range $group.acmlabels }} + {{ .name }}: {{ .value }} + {{- end }} + {{- end }} + name: {{ $deploymentName }} +spec: + hubAcceptsClient: true +{{- end }}{{- /* range $group.clusterDeployments */}} +{{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} diff --git a/acm/templates/provision/clusterpool.yaml b/acm/templates/provision/clusterpool.yaml index e2f9d3d1..d95905f7 100644 --- a/acm/templates/provision/clusterpool.yaml +++ b/acm/templates/provision/clusterpool.yaml @@ -1,17 +1,5 @@ {{- range .Values.clusterGroup.managedClusterGroups }} {{- $group := . }} -{{- if .clusterPools }}{{- /* We only create ManagedClusterSets if there are clusterPools defined */}} -apiVersion: cluster.open-cluster-management.io/v1beta1 -kind: ManagedClusterSet -metadata: - annotations: - cluster.open-cluster-management.io/submariner-broker-ns: {{ .name }}-broker - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - name: {{ .name }} -spec: - clusterSelector: - selectorType: LegacyClusterSetLabel ---- {{- range .clusterPools }} {{- $pool := . }} @@ -54,7 +42,7 @@ spec: runningCount: {{ $numClusters }} baseDomain: {{ .baseDomain }} installConfigSecretTemplateRef: - name: {{ $poolName }}-install-config + name: {{ $poolName }}-install-config imageSetRef: name: img{{ .openshiftVersion }}-multi-appsub pullSecretRef: @@ -91,5 +79,4 @@ spec: --- {{- end }}{{- /* range .range clusters */}} {{- end }}{{- /* range .clusterPools */}} -{{- end }}{{- /* if .clusterPools) */}} {{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} diff --git a/acm/templates/provision/managedclusterset.yaml b/acm/templates/provision/managedclusterset.yaml new file mode 100644 index 00000000..dce01f73 --- /dev/null +++ b/acm/templates/provision/managedclusterset.yaml @@ -0,0 +1,16 @@ +{{- range .Values.clusterGroup.managedClusterGroups }} +{{- if or .clusterPools .clusterDeployments }}{{- /* We only create ManagedClusterSets if there are clusterPools or clusterDeployments defined */}} +--- +apiVersion: cluster.open-cluster-management.io/v1beta2 +kind: ManagedClusterSet +metadata: + annotations: + cluster.open-cluster-management.io/submariner-broker-ns: {{ .name }}-broker + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + name: {{ .name }} +spec: + clusterSelector: + selectorType: LegacyClusterSetLabel + +{{- end }}{{- /* if .clusterPools) */}} +{{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} diff --git a/acm/templates/provision/secrets-aws.yaml b/acm/templates/provision/secrets-aws.yaml index 002c9247..a671638d 100644 --- a/acm/templates/provision/secrets-aws.yaml +++ b/acm/templates/provision/secrets-aws.yaml @@ -3,58 +3,82 @@ {{- range .clusterPools }} {{- $poolName := print .name "-" $group.name }} {{- if .platform.aws }} +--- +{{- template "externalsecret.aws.creds" (dict "name" $poolName "context" . "secretStore" $.Values.secretStore) }} +--- +{{- template "externalsecret.aws.infra-creds" (dict "name" $poolName "context" . "secretStore" $.Values.secretStore) }} + +{{- end }}{{- /* if .platform.aws */}} +{{- end }}{{- /* range .clusterPools */}} + +{{- range .clusterDeployments }} +{{- $deploymentName := print .name "-" $group.name }} +{{- if .platform.aws }} +--- +{{- template "externalsecret.aws.creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} +--- +{{- template "externalsecret.aws.infra-creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} + +{{- end }}{{- /* if .platform.aws */}} +{{- end }}{{- /* range .clusterDeployments */}} + +{{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} + +{{- define "externalsecret.aws.creds" }} apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: - name: {{ $poolName }}-creds + name: {{ .name }}-creds spec: dataFrom: - extract: # Expects entries called: aws_access_key_id and aws_secret_access_key - key: {{ default "secret/data/hub/aws" .awsKeyPath }} + key: {{ default "secret/data/hub/aws" .context.awsKeyPath }} refreshInterval: 24h0m0s secretStoreRef: - name: {{ $.Values.secretStore.name }} - kind: {{ $.Values.secretStore.kind }} + name: {{ .secretStore.name }} + kind: {{ .secretStore.kind }} target: - name: {{ $poolName }}-creds + name: {{ .name }}-creds creationPolicy: Owner template: type: Opaque ---- +{{- end}} + +{{- define "externalsecret.aws.infra-creds"}} # For use when manually creating clusters with ACM apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: - name: {{ $poolName }}-infra-creds -spec: + name: {{ .name }}-infra-creds +spec: data: - secretKey: openshiftPullSecret remoteRef: - key: {{ default "secret/data/hub/openshiftPullSecret" .pullSecretKeyPath }} + key: {{ default "secret/data/hub/openshiftPullSecret" .context.pullSecretKeyPath }} property: content - secretKey: awsKeyId remoteRef: - key: {{ default "secret/data/hub/aws" .awsKeyPath }} + key: {{ default "secret/data/hub/aws" .context.awsKeyPath }} property: aws_access_key_id - secretKey: awsAccessKey remoteRef: - key: {{ default "secret/data/hub/aws" .awsKeyPath }} + key: {{ default "secret/data/hub/aws" .context.awsKeyPath }} property: aws_secret_access_key - secretKey: sshPublicKey remoteRef: - key: {{ default "secret/data/hub/publickey" .sshPublicKeyPath }} + key: {{ default "secret/data/hub/publickey" .context.sshPublicKeyPath }} property: content - secretKey: sshPrivateKey remoteRef: - key: {{ default "secret/data/hub/privatekey" .sshPrivateKeyPath }} + key: {{ default "secret/data/hub/privatekey" .context.sshPrivateKeyPath }} property: content refreshInterval: 24h0m0s - secretStoreRef: - name: {{ $.Values.secretStore.name }} - kind: {{ $.Values.secretStore.kind }} + secretStoreRef: + name: {{ .secretStore.name }} + kind: {{ .secretStore.kind }} target: - name: {{ $poolName }}-infra-creds + name: {{ .name }}-infra-creds creationPolicy: Owner template: type: Opaque @@ -63,7 +87,7 @@ spec: cluster.open-cluster-management.io/credentials: "" cluster.open-cluster-management.io/type: aws data: - baseDomain: "{{ .baseDomain }}" + baseDomain: "{{ .context.baseDomain }}" pullSecret: |- {{ "{{ .openshiftPullSecret | toString }}" }} aws_access_key_id: |- @@ -78,7 +102,4 @@ spec: httpsProxy: "" noProxy: "" additionalTrustBundle: "" ---- -{{- end }} -{{- end }} -{{- end }} \ No newline at end of file +{{- end}} diff --git a/acm/templates/provision/secrets-azure.yaml b/acm/templates/provision/secrets-azure.yaml index 7fe6271b..21c9d482 100644 --- a/acm/templates/provision/secrets-azure.yaml +++ b/acm/templates/provision/secrets-azure.yaml @@ -3,58 +3,84 @@ {{- range .clusterPools }} {{- $poolName := print .name "-" $group.name }} {{- if .platform.azure }} +--- +{{- template "externalsecret.azure.creds" (dict "name" $poolName "context" . "secretStore" $.Values.secretStore) }} +--- +{{- template "externalsecret.azure.infra-creds" (dict "name" $poolName "context" . "secretStore" $.Values.secretStore) }} + +--- +{{- end }}{{- /* if .platform.azure */}} +{{- end }}{{- /* range .clusterPools */}} + +{{- range .clusterDeployments }} +{{- $deploymentName := print .name "-" $group.name }} +{{- if .platform.azure }} +--- +{{- template "externalsecret.azure.creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} +--- +{{- template "externalsecret.azure.infra-creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} + + +{{- end }}{{- /* if .platform.azure */}} +{{- end }}{{- /* range .clusterPools */}} + +{{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} + +{{- define "externalsecret.azure.creds" }} apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: - name: {{ $poolName }}-creds + name: {{ .name }}-creds spec: data: - secretKey: azureOsServicePrincipal remoteRef: - key: {{ default "secret/data/hub/azureOsServicePrincipal" .azureKeyPath }} + key: {{ default "secret/data/hub/azureOsServicePrincipal" .context.azureKeyPath }} property: content refreshInterval: 24h0m0s secretStoreRef: - name: {{ $.Values.secretStore.name }} - kind: {{ $.Values.secretStore.kind }} + name: {{ .secretStore.name }} + kind: {{ .secretStore.kind }} target: - name: {{ $poolName }}-creds + name: {{ .name }}-creds creationPolicy: Owner template: type: Opaque data: osServicePrincipal.json: |- {{ "{{ .azureOsServicePrincipal | toString }}" }} ---- +{{- end }} + +{{- define "externalsecret.azure.infra-creds"}} # For use when manually creating clusters with ACM apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: - name: {{ $poolName }}-infra-creds -spec: + name: {{ .name }}-infra-creds +spec: data: - secretKey: openshiftPullSecret remoteRef: - key: {{ default "secret/data/hub/openshiftPullSecret" .pullSecretKeyPath }} + key: {{ default "secret/data/hub/openshiftPullSecret" .context.pullSecretKeyPath }} property: content - secretKey: sshPublicKey remoteRef: - key: {{ default "secret/data/hub/publickey" .sshPublicKeyPath }} + key: {{ default "secret/data/hub/publickey" .context.sshPublicKeyPath }} property: content - secretKey: sshPrivateKey remoteRef: - key: {{ default "secret/data/hub/privatekey" .sshPrivateKeyPath }} + key: {{ default "secret/data/hub/privatekey" .context.sshPrivateKeyPath }} property: content - secretKey: azureOsServicePrincipal remoteRef: - key: {{ default "secret/data/hub/azureOsServicePrincipal" .azureKeyPath }} + key: {{ default "secret/data/hub/azureOsServicePrincipal" .context.azureKeyPath }} property: content refreshInterval: 24h0m0s - secretStoreRef: - name: {{ $.Values.secretStore.name }} - kind: {{ $.Values.secretStore.kind }} + secretStoreRef: + name: {{ .secretStore.name }} + kind: {{ .secretStore.kind }} target: - name: {{ $poolName }}-infra-creds + name: {{ .name }}-infra-creds creationPolicy: Owner template: type: Opaque @@ -66,8 +92,8 @@ spec: cloudName: AzurePublicCloud osServicePrincipal.json: |- {{ "{{ .azureOsServicePrincipal | toString }}" }} - baseDomain: "{{ .baseDomain }}" - baseDomainResourceGroupName: "{{ .platform.azure.baseDomainResourceGroupName | toString }}" + baseDomain: "{{ .context.baseDomain }}" + baseDomainResourceGroupName: "{{ .context.platform.azure.baseDomainResourceGroupName | toString }}" pullSecret: |- {{ "{{ .openshiftPullSecret | toString }}" }} ssh-privatekey: |- @@ -78,7 +104,4 @@ spec: httpsProxy: "" noProxy: "" additionalTrustBundle: "" ---- -{{- end }} -{{- end }} {{- end }} diff --git a/acm/templates/provision/secrets-common.yaml b/acm/templates/provision/secrets-common.yaml index 21a03b73..474347c6 100644 --- a/acm/templates/provision/secrets-common.yaml +++ b/acm/templates/provision/secrets-common.yaml @@ -1,61 +1,86 @@ {{- range .Values.clusterGroup.managedClusterGroups }} {{- $group := . }} + {{- range .clusterPools }} {{- $poolName := print .name "-" $group.name }} +--- +{{- template "secret.install-config" (dict "name" $poolName "context" .) }} +--- +{{- template "externalsecret.pull-secret" (dict "name" $poolName "context" . "secretStore" $.Values.secretStore) }} +--- +{{- template "externalsecret.ssh.private.key" (dict "name" $poolName "context" . "secretStore" $.Values.secretStore) }} +{{- end }}{{- /* range .clusterPools */}} + +{{- range .clusterDeployments }} +{{- $deploymentName := print .name "-" $group.name }} +--- +{{- template "secret.install-config" (dict "name" $deploymentName "context" .) }} +--- +{{- template "externalsecret.pull-secret" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} +--- +{{- template "externalsecret.ssh.private.key" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} +{{- end }}{{- /* range .clusterDeplyments */}} + +{{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} + +{{- define "secret.install-config"}} apiVersion: v1 kind: Secret metadata: - name: {{ $poolName }}-install-config + name: {{ .name }}-install-config data: # Base64 encoding of install-config yaml - install-config.yaml: {{ include "cluster.install-config" . | b64enc }} + install-config.yaml: {{ include "cluster.install-config" .context | b64enc }} type: Opaque ---- +{{- end }} + +{{- define "externalsecret.pull-secret" }} apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: - name: {{ $poolName }}-pull-secret -spec: + name: {{ .name }}-pull-secret +spec: data: - secretKey: openshiftPullSecret remoteRef: - key: {{ default "secret/data/hub/openshiftPullSecret" .pullSecretKeyPath }} + key: {{ default "secret/data/hub/openshiftPullSecret" .context.pullSecretKeyPath }} property: content refreshInterval: 24h0m0s secretStoreRef: - name: {{ $.Values.secretStore.name }} - kind: {{ $.Values.secretStore.kind }} + name: {{ .secretStore.name }} + kind: {{ .secretStore.kind }} target: - name: {{ $poolName }}-pull-secret + name: {{ .name }}-pull-secret creationPolicy: Owner template: type: kubernetes.io/dockerconfigjson data: .dockerconfigjson: |- {{ "{{ .openshiftPullSecret | toString }}" }} ---- +{{- end }} + + +{{- define "externalsecret.ssh.private.key" }} apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: - name: {{ $poolName }}-ssh-private-key + name: {{ .name }}-ssh-private-key spec: data: - secretKey: sshPrivateKey remoteRef: - key: {{ default "secret/data/hub/privatekey" .sshPrivateKeyPath }} + key: {{ default "secret/data/hub/privatekey" .context.sshPrivateKeyPath }} property: content refreshInterval: 24h0m0s secretStoreRef: - name: {{ $.Values.secretStore.name }} - kind: {{ $.Values.secretStore.kind }} + name: {{ .secretStore.name }} + kind: {{ .secretStore.kind }} target: - name: {{ $poolName }}-ssh-private-key + name: {{ .name }}-ssh-private-key creationPolicy: Owner template: type: Opaque data: ssh-privatekey: |- {{ "{{ .sshPrivateKey | toString }}" }} ---- -{{- end }} {{- end }} diff --git a/acm/values.yaml b/acm/values.yaml index fb7cb03a..54c84a2e 100644 --- a/acm/values.yaml +++ b/acm/values.yaml @@ -21,14 +21,29 @@ clusterGroup: # testPool: # name: spoke # openshiftVersion: 4.10.18 -# provider: -# region: ap-southeast-2 -# baseDomain: blueprints.rhecoeng.com +# baseDomain: blueprints.rhecoeng.com +# platform: +# aws: +# region: ap-southeast-2 # clusters: # - spoke1 # labels: # - name: clusterGroup # value: region-one +# testRegionTwo: +# name: region-two +# clusterDeployments: +# myFirstCluster: +# name: mcluster1 +# openshiftVersion: 4.10.18 +# baseDomain: blueprints.rhecoeng.com +# platform: +# azure: +# baseDomainResourceGroupName: dojo-dns-zones +# region: eastus +# labels: +# - name: clusterGroup +# value: region-two secretStore: name: vault-backend diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index cf14bf26..4b6190ae 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -741,6 +741,12 @@ "$ref": "#/definitions/ClusterPools" } }, + "clusterDeployments": { + "type": "object", + "items": { + "$ref": "#/definitions/ClusterDeployments" + } + }, "clusterSelector": { "type": "object", "additionalProperties": true @@ -788,6 +794,32 @@ ], "title": "ClusterPools" }, + "ClusterDeployments": { + "type": "object", + "additionalProperties": false, + "properties": { + "name": { + "type": "string" + }, + "openshiftVersion": { + "type": "string" + }, + "baseDomain": { + "type": "string" + }, + "platform": { + "type": "object", + "$ref": "#/definitions/ClusterPoolsPlatform" + } + }, + "required": [ + "name", + "openshiftVersion", + "baseDomain", + "platform" + ], + "title": "ClusterDeployments" + }, "ClusterPoolsPlatform": { "type": "object", "additionalProperties": false, From f9bf1f7842343181ee95c68d1126aa41087f6ee6 Mon Sep 17 00:00:00 2001 From: Tomer Figenblat Date: Tue, 16 Apr 2024 18:46:24 -0400 Subject: [PATCH 02/77] test: regenerated tests after clusterdeployment commit Co-authored-by: Alejandro Villegas Signed-off-by: Tomer Figenblat --- tests/acm-normal.expected.yaml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 1a3f6e72..e83a83a6 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -6,7 +6,7 @@ metadata: name: aws-ap-acm-provision-edge-install-config data: # Base64 encoding of install-config yaml - install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXdzLWFwJyAKYmFzZURvbWFpbjogYmx1ZXByaW50cy5yaGVjb2VuZy5jb20KY29udHJvbFBsYW5lOgogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIG5hbWU6IGNvbnRyb2xQbGFuZQogIHJlcGxpY2FzOiAxCiAgcGxhdGZvcm06CiAgICBhd3M6CiAgICAgIHR5cGU6IG01LnhsYXJnZQpjb21wdXRlOgotIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIG5hbWU6ICd3b3JrZXInCiAgcmVwbGljYXM6IDAKbmV0d29ya2luZzoKICBjbHVzdGVyTmV0d29yazoKICAtIGNpZHI6IDEwLjEyOC4wLjAvMTQKICAgIGhvc3RQcmVmaXg6IDIzCiAgbWFjaGluZU5ldHdvcms6CiAgLSBjaWRyOiAxMC4wLjAuMC8xNgogIG5ldHdvcmtUeXBlOiBPVk5LdWJlcm5ldGVzCiAgc2VydmljZU5ldHdvcms6CiAgLSAxNzIuMzAuMC4wLzE2CnBsYXRmb3JtOgogIGF3czoKICAgIHJlZ2lvbjogYXAtc291dGhlYXN0LTIKcHVsbFNlY3JldDogIiIgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cwpzc2hLZXk6ICIiICAgICAjIHNraXAsIGhpdmUgd2lsbCBpbmplY3QgYmFzZWQgb24gaXQncyBzZWNyZXRz + install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXdzLWFwJyAKYmFzZURvbWFpbjogYmx1ZXByaW50cy5yaGVjb2VuZy5jb20KY29udHJvbFBsYW5lOgogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIG5hbWU6IGNvbnRyb2xQbGFuZQogIHJlcGxpY2FzOiAxCiAgcGxhdGZvcm06CiAgICBhd3M6CiAgICAgIHR5cGU6IG01LnhsYXJnZQpjb21wdXRlOgotIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIG5hbWU6ICd3b3JrZXInCiAgcmVwbGljYXM6IDAKbmV0d29ya2luZzoKICBjbHVzdGVyTmV0d29yazoKICAtIGNpZHI6IDEwLjEyOC4wLjAvMTQKICAgIGhvc3RQcmVmaXg6IDIzCiAgbWFjaGluZU5ldHdvcms6CiAgLSBjaWRyOiAxMC4wLjAuMC8xNgogIG5ldHdvcmtUeXBlOiBPVk5LdWJlcm5ldGVzCiAgc2VydmljZU5ldHdvcms6CiAgLSAxNzIuMzAuMC4wLzE2CnBsYXRmb3JtOgogIGF3czoKICAgIHJlZ2lvbjogYXAtc291dGhlYXN0LTIKcHVsbFNlY3JldDogIiIgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cwpzc2hLZXk6ICIiICAgICAjIHNraXAsIGhpdmUgd2lsbCBpbmplY3QgYmFzZWQgb24gaXQncyBzZWNyZXRz type: Opaque --- # Source: acm/templates/provision/secrets-common.yaml @@ -16,7 +16,7 @@ metadata: name: azure-us-acm-provision-edge-install-config data: # Base64 encoding of install-config yaml - install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXp1cmUtdXMnIApiYXNlRG9tYWluOiBibHVlcHJpbnRzLnJoZWNvZW5nLmNvbQpjb250cm9sUGxhbmU6CiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgbmFtZTogY29udHJvbFBsYW5lCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF6dXJlOgogICAgICB0eXBlOiBTdGFuZGFyZF9EOHNfdjMKY29tcHV0ZToKLSBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBuYW1lOiAnd29ya2VyJwogIHJlcGxpY2FzOiAzCiAgcGxhdGZvcm06CiAgICBhenVyZToKICAgICAgdHlwZTogU3RhbmRhcmRfRDhzX3YzCm5ldHdvcmtpbmc6CiAgY2x1c3Rlck5ldHdvcms6CiAgLSBjaWRyOiAxMC4xMjguMC4wLzE0CiAgICBob3N0UHJlZml4OiAyMwogIG1hY2hpbmVOZXR3b3JrOgogIC0gY2lkcjogMTAuMC4wLjAvMTYKICBuZXR3b3JrVHlwZTogT1ZOS3ViZXJuZXRlcwogIHNlcnZpY2VOZXR3b3JrOgogIC0gMTcyLjMwLjAuMC8xNgpwbGF0Zm9ybToKICBhenVyZToKICAgIGJhc2VEb21haW5SZXNvdXJjZUdyb3VwTmFtZTogZG9qby1kbnMtem9uZXMKICAgIHJlZ2lvbjogZWFzdHVzCnB1bGxTZWNyZXQ6ICIiICMgc2tpcCwgaGl2ZSB3aWxsIGluamVjdCBiYXNlZCBvbiBpdCdzIHNlY3JldHMKc3NoS2V5OiAiIiAgICAgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cw== + install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXp1cmUtdXMnIApiYXNlRG9tYWluOiBibHVlcHJpbnRzLnJoZWNvZW5nLmNvbQpjb250cm9sUGxhbmU6CiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgbmFtZTogY29udHJvbFBsYW5lCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF6dXJlOgogICAgICB0eXBlOiBTdGFuZGFyZF9EOHNfdjMKY29tcHV0ZToKLSBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBuYW1lOiAnd29ya2VyJwogIHJlcGxpY2FzOiAzCiAgcGxhdGZvcm06CiAgICBhenVyZToKICAgICAgdHlwZTogU3RhbmRhcmRfRDhzX3YzCm5ldHdvcmtpbmc6CiAgY2x1c3Rlck5ldHdvcms6CiAgLSBjaWRyOiAxMC4xMjguMC4wLzE0CiAgICBob3N0UHJlZml4OiAyMwogIG1hY2hpbmVOZXR3b3JrOgogIC0gY2lkcjogMTAuMC4wLjAvMTYKICBuZXR3b3JrVHlwZTogT1ZOS3ViZXJuZXRlcwogIHNlcnZpY2VOZXR3b3JrOgogIC0gMTcyLjMwLjAuMC8xNgpwbGF0Zm9ybToKICBhenVyZToKICAgIGJhc2VEb21haW5SZXNvdXJjZUdyb3VwTmFtZTogZG9qby1kbnMtem9uZXMKICAgIHJlZ2lvbjogZWFzdHVzCnB1bGxTZWNyZXQ6ICIiICMgc2tpcCwgaGl2ZSB3aWxsIGluamVjdCBiYXNlZCBvbiBpdCdzIHNlY3JldHMKc3NoS2V5OiAiIiAgICAgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cw== type: Opaque --- # Source: acm/templates/policies/acm-hub-ca-policy.yaml @@ -79,7 +79,7 @@ spec: runningCount: 0 baseDomain: blueprints.rhecoeng.com installConfigSecretTemplateRef: - name: aws-ap-acm-provision-edge-install-config + name: aws-ap-acm-provision-edge-install-config imageSetRef: name: img4.10.18-multi-appsub pullSecretRef: @@ -109,7 +109,7 @@ spec: runningCount: 2 baseDomain: blueprints.rhecoeng.com installConfigSecretTemplateRef: - name: azure-us-acm-provision-edge-install-config + name: azure-us-acm-provision-edge-install-config imageSetRef: name: img4.10.18-multi-appsub pullSecretRef: @@ -147,7 +147,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-ap-acm-provision-edge-infra-creds -spec: +spec: data: - secretKey: openshiftPullSecret remoteRef: @@ -170,7 +170,7 @@ spec: key: secret/data/hub/privatekey property: content refreshInterval: 24h0m0s - secretStoreRef: + secretStoreRef: name: vault-backend kind: ClusterSecretStore target: @@ -229,7 +229,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: azure-us-acm-provision-edge-infra-creds -spec: +spec: data: - secretKey: openshiftPullSecret remoteRef: @@ -248,7 +248,7 @@ spec: key: secret/data/hub/azureOsServicePrincipal property: content refreshInterval: 24h0m0s - secretStoreRef: + secretStoreRef: name: vault-backend kind: ClusterSecretStore target: @@ -282,7 +282,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-ap-acm-provision-edge-pull-secret -spec: +spec: data: - secretKey: openshiftPullSecret remoteRef: @@ -330,7 +330,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: azure-us-acm-provision-edge-pull-secret -spec: +spec: data: - secretKey: openshiftPullSecret remoteRef: @@ -373,8 +373,8 @@ spec: ssh-privatekey: |- {{ .sshPrivateKey | toString }} --- -# Source: acm/templates/provision/clusterpool.yaml -apiVersion: cluster.open-cluster-management.io/v1beta1 +# Source: acm/templates/provision/managedclusterset.yaml +apiVersion: cluster.open-cluster-management.io/v1beta2 kind: ManagedClusterSet metadata: annotations: From 5b4e9038b1e9dca267137cccf5648b25c10c2665 Mon Sep 17 00:00:00 2001 From: Tomer Figenblat Date: Tue, 16 Apr 2024 20:03:57 -0400 Subject: [PATCH 03/77] test: updated test-cased and regeneated expectations Co-authored-by: Alejandro Villegas Signed-off-by: Tomer Figenblat --- examples/values-example.yaml | 23 +- tests/acm-normal.expected.yaml | 499 ++++++++++++++++++++++++ tests/clustergroup-normal.expected.yaml | 17 + 3 files changed, 536 insertions(+), 3 deletions(-) diff --git a/examples/values-example.yaml b/examples/values-example.yaml index 84682e20..b8b1dde9 100644 --- a/examples/values-example.yaml +++ b/examples/values-example.yaml @@ -15,7 +15,7 @@ clusterGroup: - /values/{{ .Values.global.clusterPlatform }}.yaml - /values/{{ .Values.global.clusterVersion }}.yaml - # + # # You can define namespaces using hashes and not as a list like so: # namespaces: # open-cluster-management: @@ -25,7 +25,7 @@ clusterGroup: # annotations: # openshift.io/cluster-monitoring: "true" # owner: "namespace owner" - # application-ci: + # application-ci: # You cannot mix list and hashes to define namespaces namespaces: - open-cluster-management: @@ -70,7 +70,7 @@ clusterGroup: name: openshift-pipelines-operator-rh csv: redhat-openshift-pipelines.v1.5.2 - # + # # You can define projects using hashes like so: # projects: # hub: @@ -159,9 +159,26 @@ clusterGroup: clusters: - Two - three + clusterDeployments: + myFirstCluster: + name: aws-cd-one-w-pool + openshiftVersion: 4.10.18 + baseDomain: blueprints.rhecoeng.com + platform: + aws: + region: ap-southeast-1 acmlabels: - name: clusterGroup value: region + - name: acm-provision-on-deploy + clusterDeployments: + mySecondCluster: + name: aws-cd-two-wo-pool + openshiftVersion: 4.10.18 + baseDomain: blueprints.rhecoeng.com + platform: + aws: + region: ap-southeast-3 - name: argo-edge hostedArgoSites: - name: perth diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index e83a83a6..1e63d2e7 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -1,4 +1,16 @@ --- +# Source: acm/templates/provision/clusterdeployment.yaml +apiVersion: v1 +kind: Namespace +metadata: + name: aws-cd-one-w-pool-acm-provision-edge +--- +# Source: acm/templates/provision/clusterdeployment.yaml +apiVersion: v1 +kind: Namespace +metadata: + name: aws-cd-two-wo-pool-acm-provision-on-deploy +--- # Source: acm/templates/provision/secrets-common.yaml apiVersion: v1 kind: Secret @@ -19,6 +31,26 @@ data: install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXp1cmUtdXMnIApiYXNlRG9tYWluOiBibHVlcHJpbnRzLnJoZWNvZW5nLmNvbQpjb250cm9sUGxhbmU6CiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgbmFtZTogY29udHJvbFBsYW5lCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF6dXJlOgogICAgICB0eXBlOiBTdGFuZGFyZF9EOHNfdjMKY29tcHV0ZToKLSBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBuYW1lOiAnd29ya2VyJwogIHJlcGxpY2FzOiAzCiAgcGxhdGZvcm06CiAgICBhenVyZToKICAgICAgdHlwZTogU3RhbmRhcmRfRDhzX3YzCm5ldHdvcmtpbmc6CiAgY2x1c3Rlck5ldHdvcms6CiAgLSBjaWRyOiAxMC4xMjguMC4wLzE0CiAgICBob3N0UHJlZml4OiAyMwogIG1hY2hpbmVOZXR3b3JrOgogIC0gY2lkcjogMTAuMC4wLjAvMTYKICBuZXR3b3JrVHlwZTogT1ZOS3ViZXJuZXRlcwogIHNlcnZpY2VOZXR3b3JrOgogIC0gMTcyLjMwLjAuMC8xNgpwbGF0Zm9ybToKICBhenVyZToKICAgIGJhc2VEb21haW5SZXNvdXJjZUdyb3VwTmFtZTogZG9qby1kbnMtem9uZXMKICAgIHJlZ2lvbjogZWFzdHVzCnB1bGxTZWNyZXQ6ICIiICMgc2tpcCwgaGl2ZSB3aWxsIGluamVjdCBiYXNlZCBvbiBpdCdzIHNlY3JldHMKc3NoS2V5OiAiIiAgICAgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cw== type: Opaque --- +# Source: acm/templates/provision/secrets-common.yaml +apiVersion: v1 +kind: Secret +metadata: + name: aws-cd-one-w-pool-acm-provision-edge-install-config +data: + # Base64 encoding of install-config yaml + install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXdzLWNkLW9uZS13LXBvb2wnIApiYXNlRG9tYWluOiBibHVlcHJpbnRzLnJoZWNvZW5nLmNvbQpjb250cm9sUGxhbmU6CiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgbmFtZTogY29udHJvbFBsYW5lCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF3czoKICAgICAgdHlwZTogbTUueGxhcmdlCmNvbXB1dGU6Ci0gaHlwZXJ0aHJlYWRpbmc6IEVuYWJsZWQKICBhcmNoaXRlY3R1cmU6IGFtZDY0CiAgbmFtZTogJ3dvcmtlcicKICByZXBsaWNhczogMwogIHBsYXRmb3JtOgogICAgYXdzOgogICAgICB0eXBlOiBtNS54bGFyZ2UKbmV0d29ya2luZzoKICBjbHVzdGVyTmV0d29yazoKICAtIGNpZHI6IDEwLjEyOC4wLjAvMTQKICAgIGhvc3RQcmVmaXg6IDIzCiAgbWFjaGluZU5ldHdvcms6CiAgLSBjaWRyOiAxMC4wLjAuMC8xNgogIG5ldHdvcmtUeXBlOiBPVk5LdWJlcm5ldGVzCiAgc2VydmljZU5ldHdvcms6CiAgLSAxNzIuMzAuMC4wLzE2CnBsYXRmb3JtOgogIGF3czoKICAgIHJlZ2lvbjogYXAtc291dGhlYXN0LTEKcHVsbFNlY3JldDogIiIgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cwpzc2hLZXk6ICIiICAgICAjIHNraXAsIGhpdmUgd2lsbCBpbmplY3QgYmFzZWQgb24gaXQncyBzZWNyZXRz +type: Opaque +--- +# Source: acm/templates/provision/secrets-common.yaml +apiVersion: v1 +kind: Secret +metadata: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-install-config +data: + # Base64 encoding of install-config yaml + install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXdzLWNkLXR3by13by1wb29sJyAKYmFzZURvbWFpbjogYmx1ZXByaW50cy5yaGVjb2VuZy5jb20KY29udHJvbFBsYW5lOgogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIG5hbWU6IGNvbnRyb2xQbGFuZQogIHJlcGxpY2FzOiAzCiAgcGxhdGZvcm06CiAgICBhd3M6CiAgICAgIHR5cGU6IG01LnhsYXJnZQpjb21wdXRlOgotIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIG5hbWU6ICd3b3JrZXInCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF3czoKICAgICAgdHlwZTogbTUueGxhcmdlCm5ldHdvcmtpbmc6CiAgY2x1c3Rlck5ldHdvcms6CiAgLSBjaWRyOiAxMC4xMjguMC4wLzE0CiAgICBob3N0UHJlZml4OiAyMwogIG1hY2hpbmVOZXR3b3JrOgogIC0gY2lkcjogMTAuMC4wLjAvMTYKICBuZXR3b3JrVHlwZTogT1ZOS3ViZXJuZXRlcwogIHNlcnZpY2VOZXR3b3JrOgogIC0gMTcyLjMwLjAuMC8xNgpwbGF0Zm9ybToKICBhd3M6CiAgICByZWdpb246IGFwLXNvdXRoZWFzdC0zCnB1bGxTZWNyZXQ6ICIiICMgc2tpcCwgaGl2ZSB3aWxsIGluamVjdCBiYXNlZCBvbiBpdCdzIHNlY3JldHMKc3NoS2V5OiAiIiAgICAgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cw== +type: Opaque +--- # Source: acm/templates/policies/acm-hub-ca-policy.yaml # This pushes out the HUB's Certificate Authorities on to the imported clusters --- @@ -61,6 +93,60 @@ metadata: spec: clusterPoolName: azure-us-acm-provision-edge --- +# Source: acm/templates/provision/clusterdeployment.yaml +apiVersion: hive.openshift.io/v1 +kind: ClusterDeployment +metadata: + name: aws-cd-one-w-pool-acm-provision-edge + namespace: aws-cd-one-w-pool-acm-provision-edge + labels: + vendor: OpenShift +spec: + baseDomain: blueprints.rhecoeng.com + clusterName: aws-cd-one-w-pool-acm-provision-edge + installAttemptsLimit: 1 + platform: + aws: + credentialsSecretRef: + name: aws-cd-one-w-pool-acm-provision-edge-creds + region: ap-southeast-1 + provisioning: + installConfigSecretRef: + name: aws-cd-one-w-pool-acm-provision-edge-install-config + sshPrivateKeySecretRef: + name: aws-cd-one-w-pool-acm-provision-edge-ssh-private-key + imageSetRef: + name: img4.10.18-multi-appsub + pullSecretRef: + name: aws-cd-one-w-pool-acm-provision-edge-pull-secret +--- +# Source: acm/templates/provision/clusterdeployment.yaml +apiVersion: hive.openshift.io/v1 +kind: ClusterDeployment +metadata: + name: aws-cd-two-wo-pool-acm-provision-on-deploy + namespace: aws-cd-two-wo-pool-acm-provision-on-deploy + labels: + vendor: OpenShift +spec: + baseDomain: blueprints.rhecoeng.com + clusterName: aws-cd-two-wo-pool-acm-provision-on-deploy + installAttemptsLimit: 1 + platform: + aws: + credentialsSecretRef: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-creds + region: ap-southeast-3 + provisioning: + installConfigSecretRef: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-install-config + sshPrivateKeySecretRef: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-ssh-private-key + imageSetRef: + name: img4.10.18-multi-appsub + pullSecretRef: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-pull-secret +--- # Source: acm/templates/provision/clusterpool.yaml apiVersion: hive.openshift.io/v1 kind: ClusterPool @@ -199,6 +285,162 @@ spec: noProxy: "" additionalTrustBundle: "" --- +# Source: acm/templates/provision/secrets-aws.yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-cd-one-w-pool-acm-provision-edge-creds +spec: + dataFrom: + - extract: + # Expects entries called: aws_access_key_id and aws_secret_access_key + key: secret/data/hub/aws + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-one-w-pool-acm-provision-edge-creds + creationPolicy: Owner + template: + type: Opaque +--- +# Source: acm/templates/provision/secrets-aws.yaml +# For use when manually creating clusters with ACM +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-cd-one-w-pool-acm-provision-edge-infra-creds +spec: + data: + - secretKey: openshiftPullSecret + remoteRef: + key: secret/data/hub/openshiftPullSecret + property: content + - secretKey: awsKeyId + remoteRef: + key: secret/data/hub/aws + property: aws_access_key_id + - secretKey: awsAccessKey + remoteRef: + key: secret/data/hub/aws + property: aws_secret_access_key + - secretKey: sshPublicKey + remoteRef: + key: secret/data/hub/publickey + property: content + - secretKey: sshPrivateKey + remoteRef: + key: secret/data/hub/privatekey + property: content + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-one-w-pool-acm-provision-edge-infra-creds + creationPolicy: Owner + template: + type: Opaque + metadata: + labels: + cluster.open-cluster-management.io/credentials: "" + cluster.open-cluster-management.io/type: aws + data: + baseDomain: "blueprints.rhecoeng.com" + pullSecret: |- + {{ .openshiftPullSecret | toString }} + aws_access_key_id: |- + {{ .awsKeyId | toString }} + aws_secret_access_key: |- + {{ .awsAccessKey | toString }} + ssh-privatekey: |- + {{ .sshPrivateKey | toString }} + ssh-publickey: |- + {{ .sshPublicKey | toString }} + httpProxy: "" + httpsProxy: "" + noProxy: "" + additionalTrustBundle: "" +--- +# Source: acm/templates/provision/secrets-aws.yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-creds +spec: + dataFrom: + - extract: + # Expects entries called: aws_access_key_id and aws_secret_access_key + key: secret/data/hub/aws + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-creds + creationPolicy: Owner + template: + type: Opaque +--- +# Source: acm/templates/provision/secrets-aws.yaml +# For use when manually creating clusters with ACM +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-infra-creds +spec: + data: + - secretKey: openshiftPullSecret + remoteRef: + key: secret/data/hub/openshiftPullSecret + property: content + - secretKey: awsKeyId + remoteRef: + key: secret/data/hub/aws + property: aws_access_key_id + - secretKey: awsAccessKey + remoteRef: + key: secret/data/hub/aws + property: aws_secret_access_key + - secretKey: sshPublicKey + remoteRef: + key: secret/data/hub/publickey + property: content + - secretKey: sshPrivateKey + remoteRef: + key: secret/data/hub/privatekey + property: content + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-infra-creds + creationPolicy: Owner + template: + type: Opaque + metadata: + labels: + cluster.open-cluster-management.io/credentials: "" + cluster.open-cluster-management.io/type: aws + data: + baseDomain: "blueprints.rhecoeng.com" + pullSecret: |- + {{ .openshiftPullSecret | toString }} + aws_access_key_id: |- + {{ .awsKeyId | toString }} + aws_secret_access_key: |- + {{ .awsAccessKey | toString }} + ssh-privatekey: |- + {{ .sshPrivateKey | toString }} + ssh-publickey: |- + {{ .sshPublicKey | toString }} + httpProxy: "" + httpsProxy: "" + noProxy: "" + additionalTrustBundle: "" +--- # Source: acm/templates/provision/secrets-azure.yaml apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret @@ -373,6 +615,124 @@ spec: ssh-privatekey: |- {{ .sshPrivateKey | toString }} --- +# Source: acm/templates/provision/secrets-common.yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-cd-one-w-pool-acm-provision-edge-pull-secret +spec: + data: + - secretKey: openshiftPullSecret + remoteRef: + key: secret/data/hub/openshiftPullSecret + property: content + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-one-w-pool-acm-provision-edge-pull-secret + creationPolicy: Owner + template: + type: kubernetes.io/dockerconfigjson + data: + .dockerconfigjson: |- + {{ .openshiftPullSecret | toString }} +--- +# Source: acm/templates/provision/secrets-common.yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-cd-one-w-pool-acm-provision-edge-ssh-private-key +spec: + data: + - secretKey: sshPrivateKey + remoteRef: + key: secret/data/hub/privatekey + property: content + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-one-w-pool-acm-provision-edge-ssh-private-key + creationPolicy: Owner + template: + type: Opaque + data: + ssh-privatekey: |- + {{ .sshPrivateKey | toString }} +--- +# Source: acm/templates/provision/secrets-common.yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-pull-secret +spec: + data: + - secretKey: openshiftPullSecret + remoteRef: + key: secret/data/hub/openshiftPullSecret + property: content + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-pull-secret + creationPolicy: Owner + template: + type: kubernetes.io/dockerconfigjson + data: + .dockerconfigjson: |- + {{ .openshiftPullSecret | toString }} +--- +# Source: acm/templates/provision/secrets-common.yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-ssh-private-key +spec: + data: + - secretKey: sshPrivateKey + remoteRef: + key: secret/data/hub/privatekey + property: content + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-ssh-private-key + creationPolicy: Owner + template: + type: Opaque + data: + ssh-privatekey: |- + {{ .sshPrivateKey | toString }} +--- +# Source: acm/templates/provision/clusterdeployment.yaml +apiVersion: cluster.open-cluster-management.io/v1 +kind: ManagedCluster +metadata: + labels: + cluster.open-cluster-management.io/clusterset: acm-provision-edge + clusterGroup: region + name: aws-cd-one-w-pool-acm-provision-edge +spec: + hubAcceptsClient: true +--- +# Source: acm/templates/provision/clusterdeployment.yaml +apiVersion: cluster.open-cluster-management.io/v1 +kind: ManagedCluster +metadata: + labels: + cluster.open-cluster-management.io/clusterset: acm-provision-on-deploy + clusterGroup: acm-provision-on-deploy + name: aws-cd-two-wo-pool-acm-provision-on-deploy +spec: + hubAcceptsClient: true +--- # Source: acm/templates/provision/managedclusterset.yaml apiVersion: cluster.open-cluster-management.io/v1beta2 kind: ManagedClusterSet @@ -385,6 +745,18 @@ spec: clusterSelector: selectorType: LegacyClusterSetLabel --- +# Source: acm/templates/provision/managedclusterset.yaml +apiVersion: cluster.open-cluster-management.io/v1beta2 +kind: ManagedClusterSet +metadata: + annotations: + cluster.open-cluster-management.io/submariner-broker-ns: acm-provision-on-deploy-broker + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + name: acm-provision-on-deploy +spec: + clusterSelector: + selectorType: LegacyClusterSetLabel +--- # Source: acm/templates/multiclusterhub.yaml apiVersion: operator.open-cluster-management.io/v1 kind: MultiClusterHub @@ -444,6 +816,22 @@ subjects: kind: Policy apiGroup: policy.open-cluster-management.io --- +# Source: acm/templates/policies/application-policies.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: acm-provision-on-deploy-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: acm-provision-on-deploy-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: acm-provision-on-deploy-clustergroup-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- # Source: acm/templates/policies/ocp-gitops-policy.yaml apiVersion: policy.open-cluster-management.io/v1 kind: PlacementBinding @@ -508,6 +896,21 @@ spec: matchLabels: clusterGroup: region --- +# Source: acm/templates/policies/application-policies.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: acm-provision-on-deploy-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchLabels: + clusterGroup: acm-provision-on-deploy +--- # Source: acm/templates/policies/ocp-gitops-policy.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule @@ -763,6 +1166,102 @@ spec: jsonPointers: - /status --- +# Source: acm/templates/policies/application-policies.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: acm-provision-on-deploy-clustergroup-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: acm-provision-on-deploy-clustergroup-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + apiVersion: argoproj.io/v1alpha1 + kind: Application + metadata: + name: mypattern-acm-provision-on-deploy + namespace: openshift-gitops + finalizers: + - resources-finalizer.argocd.argoproj.io/foreground + spec: + project: default + source: + repoURL: https://github.com/pattern-clone/mypattern + targetRevision: main + path: common/clustergroup + helm: + ignoreMissingValueFiles: true + valueFiles: + - "/values-global.yaml" + - "/values-acm-provision-on-deploy.yaml" + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-provision-on-deploy.yaml' + # We cannot use $.Values.global.clusterVersion because that gets resolved to the + # hub's cluster version, whereas we want to include the spoke cluster version + - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + parameters: + - name: global.repoURL + value: https://github.com/pattern-clone/mypattern + - name: global.targetRevision + value: main + - name: global.namespace + value: $ARGOCD_APP_NAMESPACE + - name: global.pattern + value: mypattern + - name: global.hubClusterDomain + value: apps.hub.example.com + - name: global.localClusterDomain + value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}' + # Requires ACM 2.6 or higher + - name: global.clusterDomain + value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}' + # Requires ACM 2.6 or higher (I could not come up with something less terrible to get maj.min) + - name: global.clusterVersion + value: '{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}' + - name: global.localClusterName + value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' + - name: global.clusterPlatform + value: aws + - name: clusterGroup.name + value: acm-provision-on-deploy + - name: global.experimentalCapabilities + value: + destination: + server: https://kubernetes.default.svc + namespace: mypattern-acm-provision-on-deploy + syncPolicy: + automated: + prune: false + selfHeal: true + retry: + limit: 20 + ignoreDifferences: + - group: apps + kind: Deployment + jsonPointers: + - /spec/replicas + - group: route.openshift.io + kind: Route + jsonPointers: + - /status +--- # Source: acm/templates/policies/ocp-gitops-policy.yaml apiVersion: policy.open-cluster-management.io/v1 kind: Policy diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index 8d3d4d51..e449dd9c 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -160,6 +160,14 @@ data: - acmlabels: - name: clusterGroup value: region + clusterDeployments: + myFirstCluster: + baseDomain: blueprints.rhecoeng.com + name: aws-cd-one-w-pool + openshiftVersion: 4.10.18 + platform: + aws: + region: ap-southeast-1 clusterPools: exampleAWSPool: baseDomain: blueprints.rhecoeng.com @@ -192,6 +200,15 @@ data: value: "false" name: acm-provision-edge targetRevision: main + - clusterDeployments: + mySecondCluster: + baseDomain: blueprints.rhecoeng.com + name: aws-cd-two-wo-pool + openshiftVersion: 4.10.18 + platform: + aws: + region: ap-southeast-3 + name: acm-provision-on-deploy - helmOverrides: - name: clusterGroup.isHubCluster value: "false" From a073b8c4c8101c42cc7f8c52b81b3c2a5324a667 Mon Sep 17 00:00:00 2001 From: Tomer Figenblat Date: Tue, 23 Apr 2024 17:07:47 -0400 Subject: [PATCH 04/77] chore: added annotations controling gitops and fail for missing meta for clusterdeployments Signed-off-by: Tomer Figenblat --- acm/templates/provision/clusterdeployment.yaml | 12 ++++++++++++ tests/acm-normal.expected.yaml | 8 ++++++++ 2 files changed, 20 insertions(+) diff --git a/acm/templates/provision/clusterdeployment.yaml b/acm/templates/provision/clusterdeployment.yaml index cc37c161..f7f71a52 100644 --- a/acm/templates/provision/clusterdeployment.yaml +++ b/acm/templates/provision/clusterdeployment.yaml @@ -3,6 +3,14 @@ {{- range $group.clusterDeployments}} {{ $cluster := . }} + +{{- if (eq $cluster.name nil) }} +{{- fail (printf "managedClusterGroup clusterDeployment cluster name is empty: %s" $cluster) }} +{{- end }} +{{- if (eq $group.name nil) }} +{{- fail (printf "managedClusterGroup clusterDeployment group name is empty: %s" $cluster) }} +{{- end }} + {{- $deploymentName := print $cluster.name "-" $group.name }} {{- $cloud := "None" }} @@ -30,6 +38,8 @@ metadata: namespace: {{ $deploymentName }} labels: vendor: OpenShift + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true spec: baseDomain: {{ $cluster.baseDomain }} clusterName: {{ $deploymentName }} @@ -65,6 +75,8 @@ metadata: {{- end }} {{- end }} name: {{ $deploymentName }} + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true spec: hubAcceptsClient: true {{- end }}{{- /* range $group.clusterDeployments */}} diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 1e63d2e7..b3627634 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -101,6 +101,8 @@ metadata: namespace: aws-cd-one-w-pool-acm-provision-edge labels: vendor: OpenShift + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true spec: baseDomain: blueprints.rhecoeng.com clusterName: aws-cd-one-w-pool-acm-provision-edge @@ -128,6 +130,8 @@ metadata: namespace: aws-cd-two-wo-pool-acm-provision-on-deploy labels: vendor: OpenShift + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true spec: baseDomain: blueprints.rhecoeng.com clusterName: aws-cd-two-wo-pool-acm-provision-on-deploy @@ -719,6 +723,8 @@ metadata: cluster.open-cluster-management.io/clusterset: acm-provision-edge clusterGroup: region name: aws-cd-one-w-pool-acm-provision-edge + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true spec: hubAcceptsClient: true --- @@ -730,6 +736,8 @@ metadata: cluster.open-cluster-management.io/clusterset: acm-provision-on-deploy clusterGroup: acm-provision-on-deploy name: aws-cd-two-wo-pool-acm-provision-on-deploy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true spec: hubAcceptsClient: true --- From c6ffd0ecdab72ff98f3cf89271ab4c5433c9f5bf Mon Sep 17 00:00:00 2001 From: Tomer Figenblat Date: Fri, 26 Apr 2024 11:05:33 -0400 Subject: [PATCH 05/77] chore: removed managedclusterset spec Signed-off-by: Tomer Figenblat --- acm/templates/provision/managedclusterset.yaml | 3 --- tests/acm-normal.expected.yaml | 6 ------ 2 files changed, 9 deletions(-) diff --git a/acm/templates/provision/managedclusterset.yaml b/acm/templates/provision/managedclusterset.yaml index dce01f73..2c8eaffa 100644 --- a/acm/templates/provision/managedclusterset.yaml +++ b/acm/templates/provision/managedclusterset.yaml @@ -8,9 +8,6 @@ metadata: cluster.open-cluster-management.io/submariner-broker-ns: {{ .name }}-broker argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true name: {{ .name }} -spec: - clusterSelector: - selectorType: LegacyClusterSetLabel {{- end }}{{- /* if .clusterPools) */}} {{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index b3627634..3e6fbc74 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -749,9 +749,6 @@ metadata: cluster.open-cluster-management.io/submariner-broker-ns: acm-provision-edge-broker argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true name: acm-provision-edge -spec: - clusterSelector: - selectorType: LegacyClusterSetLabel --- # Source: acm/templates/provision/managedclusterset.yaml apiVersion: cluster.open-cluster-management.io/v1beta2 @@ -761,9 +758,6 @@ metadata: cluster.open-cluster-management.io/submariner-broker-ns: acm-provision-on-deploy-broker argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true name: acm-provision-on-deploy -spec: - clusterSelector: - selectorType: LegacyClusterSetLabel --- # Source: acm/templates/multiclusterhub.yaml apiVersion: operator.open-cluster-management.io/v1 From ff3147addcd49eaec6dee2de8bcc1ab4d676830b Mon Sep 17 00:00:00 2001 From: Lester Claudio Date: Thu, 2 May 2024 09:02:59 -0600 Subject: [PATCH 06/77] New global scope argocdServer section for values-global.yaml - Added new section for to configure the ArgoCD server to support tls argocdServer: route: tls: insecureEdgeTerminationPolicy: Redirect termination: reencrypt - Default for ArgoCD is to create route with the following: route: enabled tls: insecureEdgeTerminationPolicy: Redirect termination: passthrough For more information please refer to https://issues.redhat.com/browse/GITOPS-3918. - Changed default value for termination --- acm/templates/policies/ocp-gitops-policy.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/acm/templates/policies/ocp-gitops-policy.yaml b/acm/templates/policies/ocp-gitops-policy.yaml index bec5b343..399f52a9 100644 --- a/acm/templates/policies/ocp-gitops-policy.yaml +++ b/acm/templates/policies/ocp-gitops-policy.yaml @@ -195,6 +195,11 @@ spec: memory: 128Mi route: enabled: true + {{- if and (.Values.global.argocdServer) (.Values.global.argocdServer.route) (.Values.global.argocdServer.route.tls) }} + tls: + insecureEdgeTerminationPolicy: {{ default "Redirect" .Values.global.argocdServer.route.tls.insecureEdgeTerminationPolicy }} + termination: {{ default "reencrypt" .Values.global.argocdServer.route.tls.termination }} + {{- end }} service: type: "" sso: From aa0b9699874de5fa5796c8957914525ea62fabf8 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 3 May 2024 13:49:49 +0200 Subject: [PATCH 07/77] Improve readme for ACM IIB --- ansible/roles/iib_ci/README.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/ansible/roles/iib_ci/README.md b/ansible/roles/iib_ci/README.md index 36784ed5..8c654dbb 100644 --- a/ansible/roles/iib_ci/README.md +++ b/ansible/roles/iib_ci/README.md @@ -52,12 +52,17 @@ make EXTRA_HELM_OPTS="--set main.gitops.operatorSource=iib-${IIB} --set main.git The advanced-cluster-management operator is a little bit more complex than the others because it also installes another operator called MCE multicluster-engine. So to install ACM you typically need two IIBs (one for acm and one for mce). With those two at hand, do the following (the ordering must be -consistent: the first IIB corresponds to the first OPERATOR, etc). +consistent: the first IIB corresponds to the first OPERATOR, etc). The following operation needs to be done +on both hub *and* spokes: ```sh -export OPERATOR=advanced-cluster-management,multicluster-engine -export INDEX_IMAGES=registry-proxy.engineering.redhat.com/rh-osbs/iib:713808,registry-proxy.engineering.redhat.com/rh-osbs/iib:718034 -make load-iib +for i in hub-kubeconfig-file spoke-kubeconfig-file; do + export KUBECONFIG="${i}" + export KUBEADMINPASS="11111-22222-33333-44444" + export OPERATOR=advanced-cluster-management,multicluster-engine + export INDEX_IMAGES=registry-proxy.engineering.redhat.com/rh-osbs/iib:713808,registry-proxy.engineering.redhat.com/rh-osbs/iib:718034 + make load-iib +done ``` Once the IIBs are loaded into the cluster we need to run the following steps: From 23614a40ae0fa1cbad3e6b69b1aae97da27279fe Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 3 May 2024 15:16:03 +0200 Subject: [PATCH 08/77] Drop gitopsspec from pattern's CR We drive this from the patterns-operator-config configmap these days, which makes more sense (it is a clusterwide setting and not really a per pattern one). --- operator-install/templates/pattern.yaml | 3 --- tests/operator-install-industrial-edge-factory.expected.yaml | 3 --- tests/operator-install-industrial-edge-hub.expected.yaml | 3 --- tests/operator-install-medical-diagnosis-hub.expected.yaml | 3 --- tests/operator-install-naked.expected.yaml | 3 --- tests/operator-install-normal.expected.yaml | 3 --- 6 files changed, 18 deletions(-) diff --git a/operator-install/templates/pattern.yaml b/operator-install/templates/pattern.yaml index ca3234f8..728726f0 100644 --- a/operator-install/templates/pattern.yaml +++ b/operator-install/templates/pattern.yaml @@ -12,9 +12,6 @@ spec: tokenSecret: {{ .Values.main.tokenSecret }} tokenSecretNamespace: {{ .Values.main.tokenSecretNamespace }} {{- end }} {{/* if and .Values.main.tokenSecret .Values.main.tokenSecretNamespace */}} - gitOpsSpec: - operatorChannel: {{ default "gitops-1.12" .Values.main.gitops.channel }} - operatorSource: {{ default "redhat-operators" .Values.main.gitops.operatorSource }} multiSourceConfig: enabled: {{ .Values.main.multiSourceConfig.enabled }} {{- if .Values.main.analyticsUUID }} diff --git a/tests/operator-install-industrial-edge-factory.expected.yaml b/tests/operator-install-industrial-edge-factory.expected.yaml index 018eb4c5..5e4aa02e 100644 --- a/tests/operator-install-industrial-edge-factory.expected.yaml +++ b/tests/operator-install-industrial-edge-factory.expected.yaml @@ -25,9 +25,6 @@ spec: gitSpec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main - gitOpsSpec: - operatorChannel: gitops-1.12 - operatorSource: redhat-operators multiSourceConfig: enabled: false --- diff --git a/tests/operator-install-industrial-edge-hub.expected.yaml b/tests/operator-install-industrial-edge-hub.expected.yaml index 018eb4c5..5e4aa02e 100644 --- a/tests/operator-install-industrial-edge-hub.expected.yaml +++ b/tests/operator-install-industrial-edge-hub.expected.yaml @@ -25,9 +25,6 @@ spec: gitSpec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main - gitOpsSpec: - operatorChannel: gitops-1.12 - operatorSource: redhat-operators multiSourceConfig: enabled: false --- diff --git a/tests/operator-install-medical-diagnosis-hub.expected.yaml b/tests/operator-install-medical-diagnosis-hub.expected.yaml index 018eb4c5..5e4aa02e 100644 --- a/tests/operator-install-medical-diagnosis-hub.expected.yaml +++ b/tests/operator-install-medical-diagnosis-hub.expected.yaml @@ -25,9 +25,6 @@ spec: gitSpec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main - gitOpsSpec: - operatorChannel: gitops-1.12 - operatorSource: redhat-operators multiSourceConfig: enabled: false --- diff --git a/tests/operator-install-naked.expected.yaml b/tests/operator-install-naked.expected.yaml index fc0d7699..3d58b474 100644 --- a/tests/operator-install-naked.expected.yaml +++ b/tests/operator-install-naked.expected.yaml @@ -25,9 +25,6 @@ spec: gitSpec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main - gitOpsSpec: - operatorChannel: gitops-1.12 - operatorSource: redhat-operators multiSourceConfig: enabled: false --- diff --git a/tests/operator-install-normal.expected.yaml b/tests/operator-install-normal.expected.yaml index 018eb4c5..5e4aa02e 100644 --- a/tests/operator-install-normal.expected.yaml +++ b/tests/operator-install-normal.expected.yaml @@ -25,9 +25,6 @@ spec: gitSpec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main - gitOpsSpec: - operatorChannel: gitops-1.12 - operatorSource: redhat-operators multiSourceConfig: enabled: false --- From d9c7350f1bb700dbcf93d3421322da575f73ddf5 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 3 May 2024 15:39:40 +0200 Subject: [PATCH 09/77] Allow customizing the VP operator subscription MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tested with: ❯ helm template operator-install --show-only templates/subscription.yaml --set main.patternsOperator.installPlanApproval=Manual --- apiVersion: operators.coreos.com/v1alpha1 kind: Subscription metadata: name: patterns-operator namespace: openshift-operators labels: operators.coreos.com/patterns-operator.openshift-operators: "" spec: channel: fast installPlanApproval: Manual name: patterns-operator source: community-operators sourceNamespace: openshift-marketplace ❯ helm template operator-install --show-only templates/subscription.yaml --set main.patternsOperator.installPlanApproval=Manual --set main.patternsOperator.startingCSV=1.2.3 --- apiVersion: operators.coreos.com/v1alpha1 kind: Subscription metadata: name: patterns-operator namespace: openshift-operators labels: operators.coreos.com/patterns-operator.openshift-operators: "" spec: channel: fast installPlanApproval: Manual name: patterns-operator source: community-operators sourceNamespace: openshift-marketplace startingCSV: 1.2.3 --- operator-install/templates/subscription.yaml | 7 +++++-- operator-install/values.yaml | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/operator-install/templates/subscription.yaml b/operator-install/templates/subscription.yaml index 41d0d211..e8285cae 100644 --- a/operator-install/templates/subscription.yaml +++ b/operator-install/templates/subscription.yaml @@ -7,7 +7,10 @@ metadata: operators.coreos.com/patterns-operator.openshift-operators: "" spec: channel: {{ .Values.main.patternsOperator.channel }} - installPlanApproval: Automatic + installPlanApproval: {{ .Values.main.patternsOperator.installPlanApproval }} name: patterns-operator source: {{ .Values.main.patternsOperator.source }} - sourceNamespace: openshift-marketplace + sourceNamespace: {{ .Values.main.patternsOperator.sourceNamespace }} + {{- if .Values.main.patternsOperator.startingCSV }} + startingCSV: {{ .Values.main.patternsOperator.startingCSV }} + {{- end }} diff --git a/operator-install/values.yaml b/operator-install/values.yaml index 8ce7fe67..a46cca2e 100644 --- a/operator-install/values.yaml +++ b/operator-install/values.yaml @@ -20,6 +20,9 @@ main: patternsOperator: channel: fast source: community-operators + installPlanApproval: Automatic + sourceNamespace: openshift-marketplace + startingCSV: null clusterGroupName: default From 258af6b8a9d58a9cadeadf5fba2e91ff60eca629 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 6 May 2024 09:43:01 +0200 Subject: [PATCH 10/77] Add retries when checking oc version --- ansible/roles/iib_ci/tasks/main.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ansible/roles/iib_ci/tasks/main.yml b/ansible/roles/iib_ci/tasks/main.yml index fcaad76a..4e8df11f 100644 --- a/ansible/roles/iib_ci/tasks/main.yml +++ b/ansible/roles/iib_ci/tasks/main.yml @@ -17,6 +17,9 @@ ansible.builtin.shell: | oc get openshiftcontrollermanager/cluster -o yaml -o jsonpath='{.status.version}' register: oc_version_raw + retries: 10 + delay: 10 + until: oc_version_raw is not failed changed_when: false - name: Is OCP pre OCP 4.13? (aka registry supports v2 manifests) From 1cbcc9806685f3bc0ab5600659132022d8dfbc36 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 23 Apr 2024 11:35:18 +0200 Subject: [PATCH 11/77] Add an imperative-admin-sa service account --- .../templates/imperative/clusterrole.yaml | 16 ++++++++ clustergroup/templates/imperative/rbac.yaml | 21 +++++++++- .../templates/imperative/serviceaccount.yaml | 10 ++++- clustergroup/values.schema.json | 9 ++++ clustergroup/values.yaml | 4 ++ ...roup-industrial-edge-factory.expected.yaml | 41 ++++++++++++++++++- ...tergroup-industrial-edge-hub.expected.yaml | 41 ++++++++++++++++++- ...rgroup-medical-diagnosis-hub.expected.yaml | 41 ++++++++++++++++++- tests/clustergroup-naked.expected.yaml | 41 ++++++++++++++++++- tests/clustergroup-normal.expected.yaml | 41 ++++++++++++++++++- 10 files changed, 252 insertions(+), 13 deletions(-) diff --git a/clustergroup/templates/imperative/clusterrole.yaml b/clustergroup/templates/imperative/clusterrole.yaml index e3646917..0ad8ff64 100644 --- a/clustergroup/templates/imperative/clusterrole.yaml +++ b/clustergroup/templates/imperative/clusterrole.yaml @@ -1,5 +1,6 @@ {{- if not (eq .Values.enabled "plumbing") }} {{/* This is always defined as we always unseal the cluster with an imperative job */}} +{{- if $.Values.clusterGroup.imperative.serviceAccountCreate }} --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -18,4 +19,19 @@ rules: - list - watch {{- end }} +{{- end }} {{/* if $.Values.clusterGroup.imperative.serviceAccountCreate */}} +{{- if $.Values.clusterGroup.imperative.adminServiceAccountCreate }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ $.Values.clusterGroup.imperative.adminClusterRoleName }} +rules: + - apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +{{- end }} {{/* if $.Values.clusterGroup.imperative.adminServiceAccountCreate */}} {{- end }} diff --git a/clustergroup/templates/imperative/rbac.yaml b/clustergroup/templates/imperative/rbac.yaml index 1a4b3e2b..8bfad5b3 100644 --- a/clustergroup/templates/imperative/rbac.yaml +++ b/clustergroup/templates/imperative/rbac.yaml @@ -1,10 +1,11 @@ {{- if not (eq .Values.enabled "plumbing") }} {{/* This is always defined as we always unseal the cluster with an imperative job */}} +{{- if $.Values.clusterGroup.imperative.serviceAccountCreate -}} --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: {{ $.Values.clusterGroup.imperative.namespace }}-cluster-admin-rolebinding + name: {{ $.Values.clusterGroup.imperative.namespace }}-cluster-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -17,7 +18,7 @@ subjects: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: {{ $.Values.clusterGroup.imperative.namespace }}-admin-rolebinding + name: {{ $.Values.clusterGroup.imperative.namespace }}-rolebinding namespace: {{ $.Values.clusterGroup.imperative.namespace }} roleRef: apiGroup: rbac.authorization.k8s.io @@ -28,3 +29,19 @@ subjects: name: {{ $.Values.clusterGroup.imperative.serviceAccountName }} namespace: {{ $.Values.clusterGroup.imperative.namespace }} {{- end }} +{{- if $.Values.clusterGroup.imperative.adminServiceAccountCreate }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ $.Values.clusterGroup.imperative.namespace }}-admin-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ $.Values.clusterGroup.imperative.adminClusterRoleName }} +subjects: + - kind: ServiceAccount + name: {{ $.Values.clusterGroup.imperative.adminServiceAccountName }} + namespace: {{ $.Values.clusterGroup.imperative.namespace }} +{{- end }} +{{- end }} diff --git a/clustergroup/templates/imperative/serviceaccount.yaml b/clustergroup/templates/imperative/serviceaccount.yaml index ac051348..a171d300 100644 --- a/clustergroup/templates/imperative/serviceaccount.yaml +++ b/clustergroup/templates/imperative/serviceaccount.yaml @@ -1,10 +1,18 @@ {{- if not (eq .Values.enabled "plumbing") }} {{/* This is always defined as we always unseal the cluster with an imperative job */}} -{{- if $.Values.clusterGroup.imperative.serviceAccountCreate -}} +{{- if $.Values.clusterGroup.imperative.serviceAccountCreate }} apiVersion: v1 kind: ServiceAccount metadata: name: {{ $.Values.clusterGroup.imperative.serviceAccountName }} namespace: {{ $.Values.clusterGroup.imperative.namespace }} {{- end }} +{{- if $.Values.clusterGroup.imperative.adminServiceAccountCreate }} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ $.Values.clusterGroup.imperative.adminServiceAccountName }} + namespace: {{ $.Values.clusterGroup.imperative.namespace }} +{{- end }} {{- end }} diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index 071805fe..8d206957 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -677,6 +677,15 @@ }, "roleYaml": { "type": "string" + }, + "adminServiceAccountCreate": { + "type": "boolean" + }, + "adminServiceAccountName": { + "type": "string" + }, + "adminClusterRoleName": { + "type": "string" } }, "required": [ diff --git a/clustergroup/values.yaml b/clustergroup/values.yaml index c74db48c..c3611241 100644 --- a/clustergroup/values.yaml +++ b/clustergroup/values.yaml @@ -51,6 +51,10 @@ clusterGroup: clusterRoleYaml: "" roleName: imperative-role roleYaml: "" + adminServiceAccountCreate: true + adminServiceAccountName: imperative-admin-sa + adminClusterRoleName: imperative-admin-cluster-role + managedClusterGroups: {} namespaces: [] # - name: factory diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index f34b5f18..c3eabd83 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -64,6 +64,13 @@ metadata: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/imperative/configmap.yaml apiVersion: v1 kind: ConfigMap @@ -116,6 +123,9 @@ data: initContainers: [] imperative: activeDeadlineSeconds: 3600 + adminClusterRoleName: imperative-admin-cluster-role + adminServiceAccountCreate: true + adminServiceAccountName: imperative-admin-sa clusterRoleName: imperative-cluster-role clusterRoleYaml: "" cronJobName: imperative-cronjob @@ -264,11 +274,24 @@ rules: - list - watch --- +# Source: clustergroup/templates/imperative/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: imperative-admin-cluster-role +rules: + - apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +--- # Source: clustergroup/templates/imperative/rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: imperative-cluster-admin-rolebinding + name: imperative-cluster-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -278,6 +301,20 @@ subjects: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: imperative-admin-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: imperative-admin-cluster-role +subjects: + - kind: ServiceAccount + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/plumbing/argocd-super-role.yaml # WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS apiVersion: rbac.authorization.k8s.io/v1 @@ -340,7 +377,7 @@ rules: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: imperative-admin-rolebinding + name: imperative-rolebinding namespace: imperative roleRef: apiGroup: rbac.authorization.k8s.io diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 6641ff73..393e530c 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -109,6 +109,13 @@ metadata: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/imperative/configmap.yaml apiVersion: v1 kind: ConfigMap @@ -237,6 +244,9 @@ data: initContainers: [] imperative: activeDeadlineSeconds: 3600 + adminClusterRoleName: imperative-admin-cluster-role + adminServiceAccountCreate: true + adminServiceAccountName: imperative-admin-sa clusterRoleName: imperative-cluster-role clusterRoleYaml: "" cronJobName: imperative-cronjob @@ -425,11 +435,24 @@ rules: - list - watch --- +# Source: clustergroup/templates/imperative/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: imperative-admin-cluster-role +rules: + - apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +--- # Source: clustergroup/templates/imperative/rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: imperative-cluster-admin-rolebinding + name: imperative-cluster-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -439,6 +462,20 @@ subjects: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: imperative-admin-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: imperative-admin-cluster-role +subjects: + - kind: ServiceAccount + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/plumbing/argocd-super-role.yaml # WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS apiVersion: rbac.authorization.k8s.io/v1 @@ -501,7 +538,7 @@ rules: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: imperative-admin-rolebinding + name: imperative-rolebinding namespace: imperative roleRef: apiGroup: rbac.authorization.k8s.io diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index a61ce547..f4933c53 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -109,6 +109,13 @@ metadata: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/imperative/configmap.yaml apiVersion: v1 kind: ConfigMap @@ -220,6 +227,9 @@ data: initContainers: [] imperative: activeDeadlineSeconds: 3600 + adminClusterRoleName: imperative-admin-cluster-role + adminServiceAccountCreate: true + adminServiceAccountName: imperative-admin-sa clusterRoleName: imperative-cluster-role clusterRoleYaml: "" cronJobName: imperative-cronjob @@ -352,11 +362,24 @@ rules: - list - watch --- +# Source: clustergroup/templates/imperative/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: imperative-admin-cluster-role +rules: + - apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +--- # Source: clustergroup/templates/imperative/rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: imperative-cluster-admin-rolebinding + name: imperative-cluster-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -366,6 +389,20 @@ subjects: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: imperative-admin-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: imperative-admin-cluster-role +subjects: + - kind: ServiceAccount + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/plumbing/argocd-super-role.yaml # WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS apiVersion: rbac.authorization.k8s.io/v1 @@ -428,7 +465,7 @@ rules: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: imperative-admin-rolebinding + name: imperative-rolebinding namespace: imperative roleRef: apiGroup: rbac.authorization.k8s.io diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index fdaf4293..6f1c6b2e 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -28,6 +28,13 @@ metadata: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/imperative/configmap.yaml apiVersion: v1 kind: ConfigMap @@ -43,6 +50,9 @@ data: initContainers: [] imperative: activeDeadlineSeconds: 3600 + adminClusterRoleName: imperative-admin-cluster-role + adminServiceAccountCreate: true + adminServiceAccountName: imperative-admin-sa clusterRoleName: imperative-cluster-role clusterRoleYaml: "" cronJobName: imperative-cronjob @@ -117,11 +127,24 @@ rules: - list - watch --- +# Source: clustergroup/templates/imperative/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: imperative-admin-cluster-role +rules: + - apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +--- # Source: clustergroup/templates/imperative/rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: imperative-cluster-admin-rolebinding + name: imperative-cluster-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -131,6 +154,20 @@ subjects: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: imperative-admin-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: imperative-admin-cluster-role +subjects: + - kind: ServiceAccount + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/plumbing/argocd-super-role.yaml # WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS apiVersion: rbac.authorization.k8s.io/v1 @@ -193,7 +230,7 @@ rules: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: imperative-admin-rolebinding + name: imperative-rolebinding namespace: imperative roleRef: apiGroup: rbac.authorization.k8s.io diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index 93f6892a..baad3fd0 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -96,6 +96,13 @@ metadata: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/imperative/configmap.yaml apiVersion: v1 kind: ConfigMap @@ -128,6 +135,9 @@ data: initContainers: [] imperative: activeDeadlineSeconds: 3600 + adminClusterRoleName: imperative-admin-cluster-role + adminServiceAccountCreate: true + adminServiceAccountName: imperative-admin-sa clusterRoleName: imperative-cluster-role clusterRoleYaml: "" cronJobName: imperative-cronjob @@ -314,11 +324,24 @@ rules: - list - watch --- +# Source: clustergroup/templates/imperative/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: imperative-admin-cluster-role +rules: + - apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +--- # Source: clustergroup/templates/imperative/rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: imperative-cluster-admin-rolebinding + name: imperative-cluster-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -328,6 +351,20 @@ subjects: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: imperative-admin-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: imperative-admin-cluster-role +subjects: + - kind: ServiceAccount + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/plumbing/argocd-super-role.yaml # WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS apiVersion: rbac.authorization.k8s.io/v1 @@ -390,7 +427,7 @@ rules: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: imperative-admin-rolebinding + name: imperative-rolebinding namespace: imperative roleRef: apiGroup: rbac.authorization.k8s.io From 308d708f922e86383f8b4b8e1708a87d8625ff42 Mon Sep 17 00:00:00 2001 From: "Sergio G." Date: Thu, 9 May 2024 22:17:44 +0200 Subject: [PATCH 12/77] Added support to enable user workloads in control plane nodes --- clustergroup/templates/core/scheduler.yaml | 8 ++++++++ clustergroup/values.schema.json | 4 ++++ clustergroup/values.yaml | 2 ++ examples/values-example.yaml | 2 ++ tests/clustergroup-industrial-edge-factory.expected.yaml | 9 +++++++++ tests/clustergroup-industrial-edge-hub.expected.yaml | 9 +++++++++ tests/clustergroup-medical-diagnosis-hub.expected.yaml | 9 +++++++++ tests/clustergroup-naked.expected.yaml | 9 +++++++++ tests/clustergroup-normal.expected.yaml | 9 +++++++++ 9 files changed, 61 insertions(+) create mode 100644 clustergroup/templates/core/scheduler.yaml diff --git a/clustergroup/templates/core/scheduler.yaml b/clustergroup/templates/core/scheduler.yaml new file mode 100644 index 00000000..fd2cdb67 --- /dev/null +++ b/clustergroup/templates/core/scheduler.yaml @@ -0,0 +1,8 @@ +{{- if not (eq .Values.enabled "plumbing") }} +apiVersion: config.openshift.io/v1 +kind: Scheduler +metadata: + name: cluster +spec: + mastersSchedulable: {{ $.Values.clusterGroup.mastersSchedulable }} +{{- end -}} diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index 8d206957..8b6bfea6 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -257,6 +257,10 @@ "type": "array", "description": "Templated value file paths." }, + "mastersSchedulable": { + "type": "boolean", + "description": "if set to true, the control plane nodes will be marked as schedulable for user workloads also." + }, "namespaces": { "anyOf": [ { diff --git a/clustergroup/values.yaml b/clustergroup/values.yaml index c3611241..2b1018da 100644 --- a/clustergroup/values.yaml +++ b/clustergroup/values.yaml @@ -20,6 +20,8 @@ clusterGroup: targetCluster: in-cluster sharedValueFiles: [] + mastersSchedulable: false + argoCD: initContainers: [] configManagementPlugins: [] diff --git a/examples/values-example.yaml b/examples/values-example.yaml index 84682e20..d5b45f71 100644 --- a/examples/values-example.yaml +++ b/examples/values-example.yaml @@ -15,6 +15,8 @@ clusterGroup: - /values/{{ .Values.global.clusterPlatform }}.yaml - /values/{{ .Values.global.clusterVersion }}.yaml + mastersSchedulable: true + # # You can define namespaces using hashes and not as a list like so: # namespaces: diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index c3eabd83..727a2b4f 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -146,6 +146,7 @@ data: verbosity: "" isHubCluster: false managedClusterGroups: {} + mastersSchedulable: false name: factory namespaces: - manuela-stormshift-line-dashboard @@ -774,6 +775,14 @@ spec: targetNamespaces: - manuela-stormshift-messaging --- +# Source: clustergroup/templates/core/scheduler.yaml +apiVersion: config.openshift.io/v1 +kind: Scheduler +metadata: + name: cluster +spec: + mastersSchedulable: false +--- # Source: clustergroup/templates/core/subscriptions.yaml apiVersion: operators.coreos.com/v1alpha1 kind: Subscription diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 393e530c..cf2e69ea 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -280,6 +280,7 @@ data: - name: clusterGroup.isHubCluster value: "false" name: factory + mastersSchedulable: false name: datacenter namespaces: - golang-external-secrets @@ -1547,6 +1548,14 @@ spec: targetNamespaces: - vault --- +# Source: clustergroup/templates/core/scheduler.yaml +apiVersion: config.openshift.io/v1 +kind: Scheduler +metadata: + name: cluster +spec: + mastersSchedulable: false +--- # Source: clustergroup/templates/core/subscriptions.yaml apiVersion: operators.coreos.com/v1alpha1 kind: Subscription diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index f4933c53..3226ebd7 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -259,6 +259,7 @@ data: - name: clusterGroup.isHubCluster value: false name: region-one + mastersSchedulable: false name: hub namespaces: - open-cluster-management @@ -1705,6 +1706,14 @@ spec: targetNamespaces: - golang-external-secrets --- +# Source: clustergroup/templates/core/scheduler.yaml +apiVersion: config.openshift.io/v1 +kind: Scheduler +metadata: + name: cluster +spec: + mastersSchedulable: false +--- # Source: clustergroup/templates/core/subscriptions.yaml apiVersion: operators.coreos.com/v1alpha1 kind: Subscription diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index 6f1c6b2e..5ab214b9 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -71,6 +71,7 @@ data: verbosity: "" isHubCluster: true managedClusterGroups: {} + mastersSchedulable: false name: example namespaces: [] projects: [] @@ -463,3 +464,11 @@ spec: href: 'https://example-gitops-server-common-example.' location: ApplicationMenu text: 'Example ArgoCD' +--- +# Source: clustergroup/templates/core/scheduler.yaml +apiVersion: config.openshift.io/v1 +kind: Scheduler +metadata: + name: cluster +spec: + mastersSchedulable: false diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index baad3fd0..18f43d52 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -211,6 +211,7 @@ data: - domain: syd.beekhof.net name: sydney name: argo-edge + mastersSchedulable: true name: example namespaces: - open-cluster-management: @@ -1217,6 +1218,14 @@ spec: targetNamespaces: - include-default-og --- +# Source: clustergroup/templates/core/scheduler.yaml +apiVersion: config.openshift.io/v1 +kind: Scheduler +metadata: + name: cluster +spec: + mastersSchedulable: true +--- # Source: clustergroup/templates/core/subscriptions.yaml apiVersion: operators.coreos.com/v1alpha1 kind: Subscription From 0123fc78e1de0ba539ef968b71a58d696038f0a6 Mon Sep 17 00:00:00 2001 From: "Sergio G." Date: Fri, 10 May 2024 00:04:09 +0200 Subject: [PATCH 13/77] Added full support for the scheduler --- clustergroup/templates/core/scheduler.yaml | 5 ++++- clustergroup/values.schema.json | 6 +++--- clustergroup/values.yaml | 5 ++++- examples/values-example.yaml | 3 ++- tests/clustergroup-industrial-edge-factory.expected.yaml | 9 --------- tests/clustergroup-industrial-edge-hub.expected.yaml | 9 --------- tests/clustergroup-medical-diagnosis-hub.expected.yaml | 9 --------- tests/clustergroup-naked.expected.yaml | 9 --------- tests/clustergroup-normal.expected.yaml | 3 ++- 9 files changed, 15 insertions(+), 43 deletions(-) diff --git a/clustergroup/templates/core/scheduler.yaml b/clustergroup/templates/core/scheduler.yaml index fd2cdb67..5061065e 100644 --- a/clustergroup/templates/core/scheduler.yaml +++ b/clustergroup/templates/core/scheduler.yaml @@ -1,8 +1,11 @@ {{- if not (eq .Values.enabled "plumbing") }} +{{- if hasKey .Values.clusterGroup "scheduler" }} apiVersion: config.openshift.io/v1 kind: Scheduler metadata: name: cluster spec: - mastersSchedulable: {{ $.Values.clusterGroup.mastersSchedulable }} +{{- toYaml .Values.clusterGroup.scheduler | nindent 2 }} {{- end -}} +{{- end -}} + diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index 8b6bfea6..c4f97634 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -257,9 +257,9 @@ "type": "array", "description": "Templated value file paths." }, - "mastersSchedulable": { - "type": "boolean", - "description": "if set to true, the control plane nodes will be marked as schedulable for user workloads also." + "scheduler": { + "type": "object", + "description": "If set, it will become the spec of the scheduler/cluster in the managed cluster." }, "namespaces": { "anyOf": [ diff --git a/clustergroup/values.yaml b/clustergroup/values.yaml index 2b1018da..bb149567 100644 --- a/clustergroup/values.yaml +++ b/clustergroup/values.yaml @@ -20,7 +20,10 @@ clusterGroup: targetCluster: in-cluster sharedValueFiles: [] - mastersSchedulable: false +# scheduler: +# mastersSchedulable: true +# defaultNodeSelector: type=user-node,region=east +# profile: HighNodeUtilization argoCD: initContainers: [] diff --git a/examples/values-example.yaml b/examples/values-example.yaml index d5b45f71..0226efe7 100644 --- a/examples/values-example.yaml +++ b/examples/values-example.yaml @@ -15,7 +15,8 @@ clusterGroup: - /values/{{ .Values.global.clusterPlatform }}.yaml - /values/{{ .Values.global.clusterVersion }}.yaml - mastersSchedulable: true + scheduler: + mastersSchedulable: true # # You can define namespaces using hashes and not as a list like so: diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index 727a2b4f..c3eabd83 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -146,7 +146,6 @@ data: verbosity: "" isHubCluster: false managedClusterGroups: {} - mastersSchedulable: false name: factory namespaces: - manuela-stormshift-line-dashboard @@ -775,14 +774,6 @@ spec: targetNamespaces: - manuela-stormshift-messaging --- -# Source: clustergroup/templates/core/scheduler.yaml -apiVersion: config.openshift.io/v1 -kind: Scheduler -metadata: - name: cluster -spec: - mastersSchedulable: false ---- # Source: clustergroup/templates/core/subscriptions.yaml apiVersion: operators.coreos.com/v1alpha1 kind: Subscription diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index cf2e69ea..393e530c 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -280,7 +280,6 @@ data: - name: clusterGroup.isHubCluster value: "false" name: factory - mastersSchedulable: false name: datacenter namespaces: - golang-external-secrets @@ -1548,14 +1547,6 @@ spec: targetNamespaces: - vault --- -# Source: clustergroup/templates/core/scheduler.yaml -apiVersion: config.openshift.io/v1 -kind: Scheduler -metadata: - name: cluster -spec: - mastersSchedulable: false ---- # Source: clustergroup/templates/core/subscriptions.yaml apiVersion: operators.coreos.com/v1alpha1 kind: Subscription diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 3226ebd7..f4933c53 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -259,7 +259,6 @@ data: - name: clusterGroup.isHubCluster value: false name: region-one - mastersSchedulable: false name: hub namespaces: - open-cluster-management @@ -1706,14 +1705,6 @@ spec: targetNamespaces: - golang-external-secrets --- -# Source: clustergroup/templates/core/scheduler.yaml -apiVersion: config.openshift.io/v1 -kind: Scheduler -metadata: - name: cluster -spec: - mastersSchedulable: false ---- # Source: clustergroup/templates/core/subscriptions.yaml apiVersion: operators.coreos.com/v1alpha1 kind: Subscription diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index 5ab214b9..6f1c6b2e 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -71,7 +71,6 @@ data: verbosity: "" isHubCluster: true managedClusterGroups: {} - mastersSchedulable: false name: example namespaces: [] projects: [] @@ -464,11 +463,3 @@ spec: href: 'https://example-gitops-server-common-example.' location: ApplicationMenu text: 'Example ArgoCD' ---- -# Source: clustergroup/templates/core/scheduler.yaml -apiVersion: config.openshift.io/v1 -kind: Scheduler -metadata: - name: cluster -spec: - mastersSchedulable: false diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index 18f43d52..3e2e2849 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -211,7 +211,6 @@ data: - domain: syd.beekhof.net name: sydney name: argo-edge - mastersSchedulable: true name: example namespaces: - open-cluster-management: @@ -239,6 +238,8 @@ data: - exclude-og projects: - datacenter + scheduler: + mastersSchedulable: true sharedValueFiles: - /values/aws.yaml - /values/4.12.yaml From 48b584e59c7129d104fa4b53b27cec11729cf09b Mon Sep 17 00:00:00 2001 From: "Sergio G." Date: Fri, 10 May 2024 00:21:37 +0200 Subject: [PATCH 14/77] Simplified PR for auto approve install plans --- .../auto-approve-installplans.yaml | 40 ++++++++++++++ .../imperative/auto-approve-installplans.yaml | 52 +++++++++++++++++++ clustergroup/values.schema.json | 4 ++ 3 files changed, 96 insertions(+) create mode 100644 ansible/playbooks/auto-approve-installplans/auto-approve-installplans.yaml create mode 100644 clustergroup/templates/imperative/auto-approve-installplans.yaml diff --git a/ansible/playbooks/auto-approve-installplans/auto-approve-installplans.yaml b/ansible/playbooks/auto-approve-installplans/auto-approve-installplans.yaml new file mode 100644 index 00000000..6b6802d4 --- /dev/null +++ b/ansible/playbooks/auto-approve-installplans/auto-approve-installplans.yaml @@ -0,0 +1,40 @@ +# This playbook will watch for pending install plans of managed operators +# if they are in Manual and there's a startingCSV that must be installed +--- +- name: InstallPlan Auto-Approver + hosts: localhost + connection: local + gather_facts: false + become: false + + tasks: + - name: Get all installPlans from OpenShift + kubernetes.core.k8s_info: + api_version: operators.coreos.com/v1alpha1 + kind: InstallPlan + register: installplans + + - name: Get required CSVs from clusterGroup data + ansible.builtin.set_fact: + expected_csv: "{{ expected_csv | default([]) + [item.csv] }}" + when: item.csv | default(false) and + ((item.installPlanApproval | default("") == "Manual") or + (item.installPlanApproval | default("") == "" and global.options.installPlanApproval | default("") == "Manual")) + with_items: "{{ clusterGroup.subscriptions.values() }}" + + # TODO: loop over clusterGroup.subscriptions instead of installplans + # to allow certain control on the order of approvals + # IDEA: allow adding a per-installplan delay after the approval before + # moving forward to the next one + - name: Approve the missing installPlans + kubernetes.core.k8s_json_patch: + api_version: operators.coreos.com/v1alpha1 + kind: InstallPlan + name: "{{ item.metadata.name }}" + namespace: "{{ item.metadata.namespace }}" + patch: + - op: replace + path: /spec/approved + value: true + when: (item.spec.clusterServiceVersionNames | intersect(expected_csv | default([]))) | length > 0 + loop: "{{ installplans.resources }}" diff --git a/clustergroup/templates/imperative/auto-approve-installplans.yaml b/clustergroup/templates/imperative/auto-approve-installplans.yaml new file mode 100644 index 00000000..e6ebf26c --- /dev/null +++ b/clustergroup/templates/imperative/auto-approve-installplans.yaml @@ -0,0 +1,52 @@ +{{- if $.Values.global.options.autoApproveManualInstallPlans }} +--- +apiVersion: batch/v1 +kind: CronJob +metadata: + name: auto-approve-installplans-cronjob + namespace: {{ $.Values.clusterGroup.imperative.namespace}} +spec: + schedule: "*/5 * * * *" + # if previous Job is still running, skip execution of a new Job + concurrencyPolicy: Forbid + jobTemplate: + spec: + activeDeadlineSeconds: {{ $.Values.clusterGroup.imperative.activeDeadlineSeconds }} + template: + metadata: + name: auto-approve-installplans-job + spec: + serviceAccountName: {{ $.Values.clusterGroup.imperative.serviceAccountName }} + initContainers: + # git init happens in /git/repo so that we can set the folder to 0770 permissions + # reason for that is ansible refuses to create temporary folders in there + {{- include "imperative.initcontainers.gitinit" . | indent 12 }} + - name: auto-approve-installplans + image: {{ $.Values.clusterGroup.imperative.image }} + imagePullPolicy: {{ $.Values.clusterGroup.imperative.imagePullPolicy }} + env: + - name: HOME + value: /git/home + workingDir: /git/repo + command: + - timeout + - {{ .timeout | default "600" | quote }} + - ansible-playbook + {{- if $.Values.clusterGroup.imperative.verbosity }} + - {{ $.Values.clusterGroup.imperative.verbosity }} + {{- end }} + - -e + - "@/values/values.yaml" + - common/ansible/playbooks/auto-approve-installplans/auto-approve-installplans.yaml + volumeMounts: + {{- include "imperative.volumemounts" . | indent 16 }} + containers: + {{- include "imperative.containers.done" . | indent 12 }} + volumes: + - name: git + emptyDir: {} + - name: values-volume + configMap: + name: {{ $.Values.clusterGroup.imperative.valuesConfigMap }}-{{ $.Values.clusterGroup.name }} + restartPolicy: Never +{{- end }} diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index 8d206957..9c3a3651 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -226,6 +226,10 @@ "deprecated": true, "description": "This is used to approval strategy for the subscriptions of OpenShift Operators being installed. You can choose Automatic or Manual updates. NOTE: This setting is now available in the subcriptions description in the values file." }, + "autoApproveManualInstallPlans": { + "type": "boolean", + "description": "This is used to approve automatically those subscriptions of OpenShift Operators that are in Manual with a startingCSV version. You can choose True or False. Defaults: False." + }, "applicationRetryLimit": { "type": "integer", "description": "Number of failed sync attempt retries; unlimited number of attempts if less than 0" From 04a6d6dbb3a04f40d879bdbfed8c2a9e47a15e32 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 13 May 2024 23:09:15 +0200 Subject: [PATCH 15/77] Switch to registry.redhat.io for the initContainer image This makes the registry url more consistent with what we already use (e.g. in the imperative templates) --- acm/templates/policies/ocp-gitops-policy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acm/templates/policies/ocp-gitops-policy.yaml b/acm/templates/policies/ocp-gitops-policy.yaml index 399f52a9..e72434ae 100644 --- a/acm/templates/policies/ocp-gitops-policy.yaml +++ b/acm/templates/policies/ocp-gitops-policy.yaml @@ -140,7 +140,7 @@ spec: - -c - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true - image: registry.access.redhat.com/ubi9/ubi-minimal:latest + image: registry.redhat.io/ubi9/ubi-minimal:latest name: fetch-ca resources: {} volumeMounts: From f6c7a47c1b6e8637339bb5678bd785648a8ad3c1 Mon Sep 17 00:00:00 2001 From: Lester Claudio Date: Tue, 14 May 2024 14:42:27 -0600 Subject: [PATCH 16/77] Update for ACM chart to application-policies.yaml - If statement was checking for .Values.global.extraValueFiles. - We now checking at the .extraValueFiles in the managedClusterGroups section. managedClusterGroups: aro-prod: name: innovation acmlabels: - name: clusterGroup value: innovation extraValueFiles: - '/overrides/values-common-capabilities.yaml' helmOverrides: - name: clusterGroup.isHubCluster value: "false" --- acm/templates/policies/application-policies.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acm/templates/policies/application-policies.yaml b/acm/templates/policies/application-policies.yaml index 131f4f3e..0194d6bb 100644 --- a/acm/templates/policies/application-policies.yaml +++ b/acm/templates/policies/application-policies.yaml @@ -45,7 +45,7 @@ spec: ignoreMissingValueFiles: true valueFiles: {{- include "acm.app.policies.valuefiles" . | nindent 22 }} - {{- range $valueFile := $.Values.global.extraValueFiles }} + {{- range $valueFile := .extraValueFiles }} - {{ $valueFile | quote }} {{- end }} parameters: From 4d422a4e7e3d78fba1f0420790e586f01461ad03 Mon Sep 17 00:00:00 2001 From: Lester Claudio Date: Wed, 15 May 2024 17:12:30 -0600 Subject: [PATCH 17/77] Add extraParameters to values.schema.json - Problem Statement The current **clustergroup** schema does not allow the definition of **extraParameters** under the **main** section of a values file. - Caveat The user defined variables in the **extraParameters** section would only be applied if the user deploys the pattern via the command, using `./pattern.sh make install` or `./pattern.sh make operator-deploy` and not via the OpenShift Validated Patterns Operator UI. - Fix Description Add the **extraParameters** to the definition of **Main.properties** in the values.schema.json: "extraParameters": { "type": "array", "description": "Pass in extra Helm parameters to all ArgoCD Applications and the framework." }, - This will allow users to define extra parameters that will be added by the framework to the ArgoCD applications it creates. - For more information see https://github.com/validatedpatterns/common/issues/510 --- clustergroup/values.schema.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index 8d206957..ea115f2a 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -65,6 +65,10 @@ "clusterGroupName": { "type": "string" }, + "extraParameters": { + "type": "array", + "description": "Pass in extra Helm parameters to all ArgoCD Applications and the framework." + }, "experimentalCapabilities": { "type": "string", "description": "String to enable certain experimental capabilities in the operator and the framework." From ab630bb7953a1fcf84945e923a21e537e899a3ee Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 17 May 2024 10:28:49 +0200 Subject: [PATCH 18/77] Update ESO to 0.9.18 --- golang-external-secrets/Chart.yaml | 2 +- .../charts/external-secrets-0.9.16.tgz | Bin 102068 -> 0 bytes .../charts/external-secrets-0.9.18.tgz | Bin 0 -> 76336 bytes golang-external-secrets/values.yaml | 6 +- ...rets-industrial-edge-factory.expected.yaml | 159 +++++++++++------- ...-secrets-industrial-edge-hub.expected.yaml | 159 +++++++++++------- ...ecrets-medical-diagnosis-hub.expected.yaml | 159 +++++++++++------- ...olang-external-secrets-naked.expected.yaml | 159 +++++++++++------- ...lang-external-secrets-normal.expected.yaml | 159 +++++++++++------- 9 files changed, 514 insertions(+), 289 deletions(-) delete mode 100644 golang-external-secrets/charts/external-secrets-0.9.16.tgz create mode 100644 golang-external-secrets/charts/external-secrets-0.9.18.tgz diff --git a/golang-external-secrets/Chart.yaml b/golang-external-secrets/Chart.yaml index 961f3b29..4aef19aa 100644 --- a/golang-external-secrets/Chart.yaml +++ b/golang-external-secrets/Chart.yaml @@ -6,6 +6,6 @@ name: golang-external-secrets version: 0.0.3 dependencies: - name: external-secrets - version: "0.9.16" + version: "0.9.18" repository: "https://charts.external-secrets.io" #"https://external-secrets.github.io/kubernetes-external-secrets" diff --git a/golang-external-secrets/charts/external-secrets-0.9.16.tgz b/golang-external-secrets/charts/external-secrets-0.9.16.tgz deleted file mode 100644 index ca268d8459d75ca2b82392618d1bda98327bb264..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 102068 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
q0j)i=a#pu1jU+b_58*02a$>ktMv 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 literal 0 HcmV?d00001 diff --git a/golang-external-secrets/values.yaml b/golang-external-secrets/values.yaml index 8d30c3df..e3d14148 100644 --- a/golang-external-secrets/values.yaml +++ b/golang-external-secrets/values.yaml @@ -37,10 +37,10 @@ clusterGroup: external-secrets: image: - tag: v0.9.16-ubi + tag: v0.9.18-ubi webhook: image: - tag: v0.9.16-ubi + tag: v0.9.18-ubi certController: image: - tag: v0.9.16-ubi + tag: v0.9.18-ubi diff --git a/tests/golang-external-secrets-industrial-edge-factory.expected.yaml b/tests/golang-external-secrets-industrial-edge-factory.expected.yaml index f0969200..712ec247 100644 --- a/tests/golang-external-secrets-industrial-edge-factory.expected.yaml +++ b/tests/golang-external-secrets-industrial-edge-factory.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -263,7 +263,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -780,11 +780,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -827,11 +829,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -844,7 +848,7 @@ spec: x-kubernetes-map-type: atomic type: array namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelector ends up choosing. + description: Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing. items: type: string type: array @@ -916,7 +920,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2484,11 +2488,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -2921,6 +2927,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -5079,7 +5102,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -5246,7 +5269,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -6051,7 +6074,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6127,7 +6150,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6255,7 +6278,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: githubaccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6357,7 +6380,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6455,7 +6478,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -6586,11 +6609,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6831,7 +6856,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -8399,11 +8424,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8836,6 +8863,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -10994,7 +11038,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11686,7 +11730,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: webhooks.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11834,10 +11878,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11901,10 +11945,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12012,10 +12056,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -12054,10 +12098,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -12100,10 +12144,10 @@ metadata: name: golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12121,10 +12165,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12141,10 +12185,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12177,10 +12221,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12216,10 +12260,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12237,10 +12281,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -12261,10 +12305,10 @@ metadata: name: golang-external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12276,10 +12320,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: external-secrets-cert-controller @@ -12294,7 +12338,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - certcontroller @@ -12324,10 +12368,10 @@ metadata: name: golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12339,10 +12383,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: golang-external-secrets @@ -12357,7 +12401,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -12366,6 +12410,7 @@ spec: - containerPort: 8080 protocol: TCP name: metrics + dnsPolicy: ClusterFirst --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml apiVersion: apps/v1 @@ -12374,10 +12419,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12389,10 +12434,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: hostNetwork: false @@ -12407,7 +12452,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - webhook diff --git a/tests/golang-external-secrets-industrial-edge-hub.expected.yaml b/tests/golang-external-secrets-industrial-edge-hub.expected.yaml index 0ecbf649..08528096 100644 --- a/tests/golang-external-secrets-industrial-edge-hub.expected.yaml +++ b/tests/golang-external-secrets-industrial-edge-hub.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -263,7 +263,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -780,11 +780,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -827,11 +829,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -844,7 +848,7 @@ spec: x-kubernetes-map-type: atomic type: array namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelector ends up choosing. + description: Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing. items: type: string type: array @@ -916,7 +920,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2484,11 +2488,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -2921,6 +2927,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -5079,7 +5102,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -5246,7 +5269,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -6051,7 +6074,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6127,7 +6150,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6255,7 +6278,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: githubaccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6357,7 +6380,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6455,7 +6478,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -6586,11 +6609,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6831,7 +6856,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -8399,11 +8424,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8836,6 +8863,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -10994,7 +11038,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11686,7 +11730,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: webhooks.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11834,10 +11878,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11901,10 +11945,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12012,10 +12056,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -12054,10 +12098,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -12100,10 +12144,10 @@ metadata: name: golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12121,10 +12165,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12141,10 +12185,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12177,10 +12221,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12216,10 +12260,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12237,10 +12281,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -12261,10 +12305,10 @@ metadata: name: golang-external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12276,10 +12320,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: external-secrets-cert-controller @@ -12294,7 +12338,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - certcontroller @@ -12324,10 +12368,10 @@ metadata: name: golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12339,10 +12383,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: golang-external-secrets @@ -12357,7 +12401,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -12366,6 +12410,7 @@ spec: - containerPort: 8080 protocol: TCP name: metrics + dnsPolicy: ClusterFirst --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml apiVersion: apps/v1 @@ -12374,10 +12419,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12389,10 +12434,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: hostNetwork: false @@ -12407,7 +12452,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - webhook diff --git a/tests/golang-external-secrets-medical-diagnosis-hub.expected.yaml b/tests/golang-external-secrets-medical-diagnosis-hub.expected.yaml index 0ecbf649..08528096 100644 --- a/tests/golang-external-secrets-medical-diagnosis-hub.expected.yaml +++ b/tests/golang-external-secrets-medical-diagnosis-hub.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -263,7 +263,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -780,11 +780,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -827,11 +829,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -844,7 +848,7 @@ spec: x-kubernetes-map-type: atomic type: array namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelector ends up choosing. + description: Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing. items: type: string type: array @@ -916,7 +920,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2484,11 +2488,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -2921,6 +2927,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -5079,7 +5102,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -5246,7 +5269,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -6051,7 +6074,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6127,7 +6150,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6255,7 +6278,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: githubaccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6357,7 +6380,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6455,7 +6478,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -6586,11 +6609,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6831,7 +6856,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -8399,11 +8424,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8836,6 +8863,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -10994,7 +11038,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11686,7 +11730,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: webhooks.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11834,10 +11878,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11901,10 +11945,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12012,10 +12056,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -12054,10 +12098,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -12100,10 +12144,10 @@ metadata: name: golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12121,10 +12165,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12141,10 +12185,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12177,10 +12221,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12216,10 +12260,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12237,10 +12281,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -12261,10 +12305,10 @@ metadata: name: golang-external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12276,10 +12320,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: external-secrets-cert-controller @@ -12294,7 +12338,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - certcontroller @@ -12324,10 +12368,10 @@ metadata: name: golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12339,10 +12383,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: golang-external-secrets @@ -12357,7 +12401,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -12366,6 +12410,7 @@ spec: - containerPort: 8080 protocol: TCP name: metrics + dnsPolicy: ClusterFirst --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml apiVersion: apps/v1 @@ -12374,10 +12419,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12389,10 +12434,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: hostNetwork: false @@ -12407,7 +12452,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - webhook diff --git a/tests/golang-external-secrets-naked.expected.yaml b/tests/golang-external-secrets-naked.expected.yaml index 55750256..c4f6c22f 100644 --- a/tests/golang-external-secrets-naked.expected.yaml +++ b/tests/golang-external-secrets-naked.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -263,7 +263,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -780,11 +780,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -827,11 +829,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -844,7 +848,7 @@ spec: x-kubernetes-map-type: atomic type: array namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelector ends up choosing. + description: Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing. items: type: string type: array @@ -916,7 +920,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2484,11 +2488,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -2921,6 +2927,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -5079,7 +5102,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -5246,7 +5269,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -6051,7 +6074,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6127,7 +6150,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6255,7 +6278,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: githubaccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6357,7 +6380,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6455,7 +6478,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -6586,11 +6609,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6831,7 +6856,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -8399,11 +8424,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8836,6 +8863,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -10994,7 +11038,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11686,7 +11730,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: webhooks.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11834,10 +11878,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11901,10 +11945,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12012,10 +12056,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -12054,10 +12098,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -12100,10 +12144,10 @@ metadata: name: golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12121,10 +12165,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12141,10 +12185,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12177,10 +12221,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12216,10 +12260,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12237,10 +12281,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -12261,10 +12305,10 @@ metadata: name: golang-external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12276,10 +12320,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: external-secrets-cert-controller @@ -12294,7 +12338,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - certcontroller @@ -12324,10 +12368,10 @@ metadata: name: golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12339,10 +12383,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: golang-external-secrets @@ -12357,7 +12401,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -12366,6 +12410,7 @@ spec: - containerPort: 8080 protocol: TCP name: metrics + dnsPolicy: ClusterFirst --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml apiVersion: apps/v1 @@ -12374,10 +12419,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12389,10 +12434,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: hostNetwork: false @@ -12407,7 +12452,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - webhook diff --git a/tests/golang-external-secrets-normal.expected.yaml b/tests/golang-external-secrets-normal.expected.yaml index 0ecbf649..08528096 100644 --- a/tests/golang-external-secrets-normal.expected.yaml +++ b/tests/golang-external-secrets-normal.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -263,7 +263,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -780,11 +780,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -827,11 +829,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -844,7 +848,7 @@ spec: x-kubernetes-map-type: atomic type: array namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelector ends up choosing. + description: Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing. items: type: string type: array @@ -916,7 +920,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2484,11 +2488,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -2921,6 +2927,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -5079,7 +5102,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -5246,7 +5269,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -6051,7 +6074,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6127,7 +6150,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6255,7 +6278,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: githubaccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6357,7 +6380,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6455,7 +6478,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -6586,11 +6609,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6831,7 +6856,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -8399,11 +8424,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8836,6 +8863,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -10994,7 +11038,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11686,7 +11730,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: webhooks.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11834,10 +11878,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11901,10 +11945,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12012,10 +12056,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -12054,10 +12098,10 @@ kind: ClusterRole metadata: name: golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -12100,10 +12144,10 @@ metadata: name: golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12121,10 +12165,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12141,10 +12185,10 @@ kind: ClusterRoleBinding metadata: name: golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12177,10 +12221,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12216,10 +12260,10 @@ metadata: name: golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12237,10 +12281,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -12261,10 +12305,10 @@ metadata: name: golang-external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12276,10 +12320,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: external-secrets-cert-controller @@ -12294,7 +12338,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - certcontroller @@ -12324,10 +12368,10 @@ metadata: name: golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12339,10 +12383,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: golang-external-secrets @@ -12357,7 +12401,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - --concurrent=1 @@ -12366,6 +12410,7 @@ spec: - containerPort: 8080 protocol: TCP name: metrics + dnsPolicy: ClusterFirst --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml apiVersion: apps/v1 @@ -12374,10 +12419,10 @@ metadata: name: golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12389,10 +12434,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.18 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.18" app.kubernetes.io/managed-by: Helm spec: hostNetwork: false @@ -12407,7 +12452,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.18-ubi imagePullPolicy: IfNotPresent args: - webhook From 7d147b241dfa3b9feaa449eef23a3df8b037454f Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 17 May 2024 12:28:40 +0200 Subject: [PATCH 19/77] Update vault to 1.16.2 --- hashicorp-vault/values.yaml | 2 +- tests/hashicorp-vault-industrial-edge-factory.expected.yaml | 4 ++-- tests/hashicorp-vault-industrial-edge-hub.expected.yaml | 4 ++-- tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml | 4 ++-- tests/hashicorp-vault-naked.expected.yaml | 4 ++-- tests/hashicorp-vault-normal.expected.yaml | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/hashicorp-vault/values.yaml b/hashicorp-vault/values.yaml index fa73a060..691f7094 100644 --- a/hashicorp-vault/values.yaml +++ b/hashicorp-vault/values.yaml @@ -48,4 +48,4 @@ vault: termination: "reencrypt" image: repository: "registry.connect.redhat.com/hashicorp/vault" - tag: "1.16.1-ubi" + tag: "1.16.2-ubi" diff --git a/tests/hashicorp-vault-industrial-edge-factory.expected.yaml b/tests/hashicorp-vault-industrial-edge-factory.expected.yaml index 74212ee2..8156e2af 100644 --- a/tests/hashicorp-vault-industrial-edge-factory.expected.yaml +++ b/tests/hashicorp-vault-industrial-edge-factory.expected.yaml @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-industrial-edge-hub.expected.yaml b/tests/hashicorp-vault-industrial-edge-hub.expected.yaml index 74212ee2..8156e2af 100644 --- a/tests/hashicorp-vault-industrial-edge-hub.expected.yaml +++ b/tests/hashicorp-vault-industrial-edge-hub.expected.yaml @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml b/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml index 74212ee2..8156e2af 100644 --- a/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml +++ b/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-naked.expected.yaml b/tests/hashicorp-vault-naked.expected.yaml index 1fe2cd90..8727ef0e 100644 --- a/tests/hashicorp-vault-naked.expected.yaml +++ b/tests/hashicorp-vault-naked.expected.yaml @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-normal.expected.yaml b/tests/hashicorp-vault-normal.expected.yaml index 74212ee2..8156e2af 100644 --- a/tests/hashicorp-vault-normal.expected.yaml +++ b/tests/hashicorp-vault-normal.expected.yaml @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR From 4eeb69ba01e2227d060946d9a8632c36d2d8b3de Mon Sep 17 00:00:00 2001 From: Lester Claudio Date: Fri, 17 May 2024 10:24:44 -0600 Subject: [PATCH 20/77] Feat: Followup to definition of extraParameters under the main section of a values file. - The operator adds these extraParameters to the extraParametersNested section as key/value pairs in the Cluster Wide ArgoCD Application created by the Validated Patterns operator. - This update will add the user defined extra parameters on the ArgoCD Applications on the Spoke Clusters. efinition of extraParameters under the main --- .../policies/application-policies.yaml | 9 +++++++ .../templates/plumbing/applications.yaml | 10 +++++++ tests/acm-industrial-edge-hub.expected.yaml | 2 ++ tests/acm-medical-diagnosis-hub.expected.yaml | 2 ++ tests/acm-normal.expected.yaml | 4 +++ ...roup-industrial-edge-factory.expected.yaml | 2 ++ ...tergroup-industrial-edge-hub.expected.yaml | 14 ++++++++++ ...rgroup-medical-diagnosis-hub.expected.yaml | 26 +++++++++++++++++++ tests/clustergroup-normal.expected.yaml | 4 +++ 9 files changed, 73 insertions(+) diff --git a/acm/templates/policies/application-policies.yaml b/acm/templates/policies/application-policies.yaml index 0194d6bb..2a815913 100644 --- a/acm/templates/policies/application-policies.yaml +++ b/acm/templates/policies/application-policies.yaml @@ -43,6 +43,11 @@ spec: path: {{ default "common/clustergroup" .path }} helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: + {{- range $k, $v := $.Values.extraParametersNested }} + {{ $k }}: {{ printf "%s" $v | quote }} + {{- end }} valueFiles: {{- include "acm.app.policies.valuefiles" . | nindent 22 }} {{- range $valueFile := .extraValueFiles }} @@ -73,6 +78,10 @@ spec: value: {{ $group.name }} - name: global.experimentalCapabilities value: {{ $.Values.global.experimentalCapabilities }} + {{- range $k, $v := $.Values.extraParametersNested }} + - name: {{ $k }} + value: {{ printf "%s" $v | quote }} + {{- end }} {{- range .helmOverrides }} - name: {{ .name }} value: {{ .value | quote }} diff --git a/clustergroup/templates/plumbing/applications.yaml b/clustergroup/templates/plumbing/applications.yaml index 29db6f39..870babe3 100644 --- a/clustergroup/templates/plumbing/applications.yaml +++ b/clustergroup/templates/plumbing/applications.yaml @@ -149,6 +149,11 @@ spec: {{- else }} helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: + {{- range $k, $v := $.Values.extraParametersNested }} + {{ $k }}: {{ printf "%s" $v | quote }} + {{- end }} valueFiles: {{- include "clustergroup.app.globalvalues.prefixedvaluefiles" $ | nindent 8 }} {{- range $valueFile := $.Values.clusterGroup.sharedValueFiles }} @@ -216,6 +221,11 @@ spec: {{- else if not .kustomize }} helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: + {{- range $k, $v := $.Values.extraParametersNested }} + {{ $k }}: {{ printf "%s" $v | quote }} + {{- end }} valueFiles: {{- include "clustergroup.app.globalvalues.valuefiles" $ | nindent 6 }} {{- range $valueFile := $.Values.clusterGroup.sharedValueFiles }} diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml index 453e8a9e..eb1df26f 100644 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ b/tests/acm-industrial-edge-hub.expected.yaml @@ -214,6 +214,8 @@ spec: path: common/clustergroup helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-factory.yaml" diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml index 8b50de7a..6a99a29c 100644 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ b/tests/acm-medical-diagnosis-hub.expected.yaml @@ -205,6 +205,8 @@ spec: path: common/clustergroup helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-region-one.yaml" diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 66f1c590..d29937be 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -608,6 +608,8 @@ spec: path: common/clustergroup helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-acm-edge.yaml" @@ -704,6 +706,8 @@ spec: path: common/clustergroup helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-acm-provision-edge.yaml" diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index c3eabd83..356b7e7e 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -559,6 +559,8 @@ spec: path: charts/datacenter/opendatahub helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-factory.yaml" diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 393e530c..3291aeb2 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -857,6 +857,8 @@ spec: path: common/acm helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-datacenter.yaml" @@ -922,6 +924,8 @@ spec: path: charts/datacenter/opendatahub helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-datacenter.yaml" @@ -978,6 +982,8 @@ spec: path: charts/datacenter/pipelines helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-datacenter.yaml" @@ -1034,6 +1040,8 @@ spec: path: charts/datacenter/manuela-data-lake helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-datacenter.yaml" @@ -1120,6 +1128,8 @@ spec: path: charts/datacenter/external-secrets helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-datacenter.yaml" @@ -1176,6 +1186,8 @@ spec: path: common/golang-external-secrets helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-datacenter.yaml" @@ -1259,6 +1271,8 @@ spec: chart: vault helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-datacenter.yaml" diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index f4933c53..6e300fc3 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -742,6 +742,8 @@ spec: path: common/golang-external-secrets helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -798,6 +800,8 @@ spec: path: charts/all/kafdrop helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -854,6 +858,8 @@ spec: path: charts/all/kafka helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -910,6 +916,8 @@ spec: path: charts/all/opendatahub helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -966,6 +974,8 @@ spec: path: charts/all/openshift-data-foundations helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1022,6 +1032,8 @@ spec: path: charts/all/openshift-serverless helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1078,6 +1090,8 @@ spec: path: charts/all/medical-diagnosis/service-account helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1134,6 +1148,8 @@ spec: chart: vault helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1208,6 +1224,8 @@ spec: path: charts/all/medical-diagnosis/database helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1264,6 +1282,8 @@ spec: path: charts/all/medical-diagnosis/grafana helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1320,6 +1340,8 @@ spec: path: charts/all/medical-diagnosis/image-generator helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1385,6 +1407,8 @@ spec: path: charts/all/medical-diagnosis/image-server helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1450,6 +1474,8 @@ spec: path: charts/all/medical-diagnosis/xray-init helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index baad3fd0..41eb68b8 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -707,6 +707,8 @@ spec: path: common/acm helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-example.yaml" @@ -774,6 +776,8 @@ spec: path: charts/datacenter/pipelines helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-example.yaml" From e23fea077bd59d7a2291acfa512825ed2a90de01 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 17 May 2024 17:37:51 +0200 Subject: [PATCH 21/77] Use golang-external-secrets for the acm hub-ca bits We'd like to make the imperative namespace optional, so let's use the golang-external-secrets one, which is probably more correct anyways since the acm hub ca is tied to ESO anyways. --- acm/templates/policies/acm-hub-ca-policy.yaml | 2 +- golang-external-secrets/values.yaml | 2 +- tests/acm-industrial-edge-hub.expected.yaml | 2 +- tests/acm-medical-diagnosis-hub.expected.yaml | 2 +- tests/acm-normal.expected.yaml | 2 +- ...olang-external-secrets-industrial-edge-factory.expected.yaml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/acm/templates/policies/acm-hub-ca-policy.yaml b/acm/templates/policies/acm-hub-ca-policy.yaml index 890e6bae..3d02d62f 100644 --- a/acm/templates/policies/acm-hub-ca-policy.yaml +++ b/acm/templates/policies/acm-hub-ca-policy.yaml @@ -31,7 +31,7 @@ spec: type: Opaque metadata: name: hub-ca - namespace: imperative + namespace: golang-external-secrets data: hub-kube-root-ca.crt: '{{ `{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}` }}' hub-openshift-service-ca.crt: '{{ `{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}` }}' diff --git a/golang-external-secrets/values.yaml b/golang-external-secrets/values.yaml index e3d14148..8c1cab77 100644 --- a/golang-external-secrets/values.yaml +++ b/golang-external-secrets/values.yaml @@ -23,7 +23,7 @@ golangExternalSecrets: type: Secret name: hub-ca key: hub-kube-root-ca.crt - namespace: imperative + namespace: golang-external-secrets global: hubClusterDomain: hub.example.com diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml index 453e8a9e..620591a2 100644 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ b/tests/acm-industrial-edge-hub.expected.yaml @@ -167,7 +167,7 @@ spec: type: Opaque metadata: name: hub-ca - namespace: imperative + namespace: golang-external-secrets data: hub-kube-root-ca.crt: '{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}' hub-openshift-service-ca.crt: '{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}' diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml index 8b50de7a..18a2f921 100644 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ b/tests/acm-medical-diagnosis-hub.expected.yaml @@ -158,7 +158,7 @@ spec: type: Opaque metadata: name: hub-ca - namespace: imperative + namespace: golang-external-secrets data: hub-kube-root-ca.crt: '{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}' hub-openshift-service-ca.crt: '{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}' diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 66f1c590..28c5eea7 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -561,7 +561,7 @@ spec: type: Opaque metadata: name: hub-ca - namespace: imperative + namespace: golang-external-secrets data: hub-kube-root-ca.crt: '{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}' hub-openshift-service-ca.crt: '{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}' diff --git a/tests/golang-external-secrets-industrial-edge-factory.expected.yaml b/tests/golang-external-secrets-industrial-edge-factory.expected.yaml index 712ec247..f7aee2c2 100644 --- a/tests/golang-external-secrets-industrial-edge-factory.expected.yaml +++ b/tests/golang-external-secrets-industrial-edge-factory.expected.yaml @@ -12502,7 +12502,7 @@ spec: type: Secret name: hub-ca key: hub-kube-root-ca.crt - namespace: imperative + namespace: golang-external-secrets auth: kubernetes: From f6734917fc9094cb597e01521c1888bbbff4756c Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 17 May 2024 18:17:06 +0200 Subject: [PATCH 22/77] Only do the acm hub ca policy when vault is the backend The acm hub ca is needed for ESO on spokes to connect to the vault on the hub, there is no need for this when vault is not used, so let's drop it in that case --- acm/templates/policies/acm-hub-ca-policy.yaml | 7 ++++--- acm/values.yaml | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/acm/templates/policies/acm-hub-ca-policy.yaml b/acm/templates/policies/acm-hub-ca-policy.yaml index 3d02d62f..ef15b136 100644 --- a/acm/templates/policies/acm-hub-ca-policy.yaml +++ b/acm/templates/policies/acm-hub-ca-policy.yaml @@ -1,5 +1,6 @@ # This pushes out the HUB's Certificate Authorities on to the imported clusters -{{ if .Values.clusterGroup.isHubCluster }} +{{- if .Values.clusterGroup.isHubCluster }} +{{- if (eq (((.Values.global).secretStore).backend) "vault") }} --- apiVersion: policy.open-cluster-management.io/v1 kind: Policy @@ -67,5 +68,5 @@ spec: operator: NotIn values: - 'true' -{{ end }} - +{{- end }} +{{- end }} diff --git a/acm/values.yaml b/acm/values.yaml index c5f222c9..6919b419 100644 --- a/acm/values.yaml +++ b/acm/values.yaml @@ -9,6 +9,8 @@ global: targetRevision: main options: applicationRetryLimit: 20 + secretStore: + backend: "vault" clusterGroup: subscriptions: From 6cd4e85d5bf7955b172b935dd05cd360fd0c4443 Mon Sep 17 00:00:00 2001 From: Tomer Figenblat Date: Tue, 28 May 2024 13:36:43 -0400 Subject: [PATCH 23/77] fix: when using clusterdeployments, secrets should exist in the cluster-namespace Co-authored-by: Michele Baldessari Co-authored-by: Alejandro Villegas Signed-off-by: Tomer Figenblat --- acm/templates/provision/secrets-aws.yaml | 10 ++++++++-- acm/templates/provision/secrets-azure.yaml | 10 ++++++++-- acm/templates/provision/secrets-common.yaml | 15 ++++++++++++--- tests/acm-normal.expected.yaml | 10 ++++++++++ 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/acm/templates/provision/secrets-aws.yaml b/acm/templates/provision/secrets-aws.yaml index a671638d..911aff4a 100644 --- a/acm/templates/provision/secrets-aws.yaml +++ b/acm/templates/provision/secrets-aws.yaml @@ -15,9 +15,9 @@ {{- $deploymentName := print .name "-" $group.name }} {{- if .platform.aws }} --- -{{- template "externalsecret.aws.creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} +{{- template "externalsecret.aws.creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore "namespaced" true) }} --- -{{- template "externalsecret.aws.infra-creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} +{{- template "externalsecret.aws.infra-creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore "namespaced" true) }} {{- end }}{{- /* if .platform.aws */}} {{- end }}{{- /* range .clusterDeployments */}} @@ -29,6 +29,9 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: {{ .name }}-creds + {{- if .namespaced }} + namespace: {{ .name }} + {{- end }} spec: dataFrom: - extract: @@ -51,6 +54,9 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: {{ .name }}-infra-creds + {{- if .namespaced }} + namespace: {{ .name }} + {{- end }} spec: data: - secretKey: openshiftPullSecret diff --git a/acm/templates/provision/secrets-azure.yaml b/acm/templates/provision/secrets-azure.yaml index 21c9d482..1ef5842c 100644 --- a/acm/templates/provision/secrets-azure.yaml +++ b/acm/templates/provision/secrets-azure.yaml @@ -16,9 +16,9 @@ {{- $deploymentName := print .name "-" $group.name }} {{- if .platform.azure }} --- -{{- template "externalsecret.azure.creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} +{{- template "externalsecret.azure.creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore "namespaced" true) }} --- -{{- template "externalsecret.azure.infra-creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} +{{- template "externalsecret.azure.infra-creds" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore "namespaced" true) }} {{- end }}{{- /* if .platform.azure */}} @@ -31,6 +31,9 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: {{ .name }}-creds + {{- if .namespaced }} + namespace: {{ .name }} + {{- end }} spec: data: - secretKey: azureOsServicePrincipal @@ -57,6 +60,9 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: {{ .name }}-infra-creds + {{- if .namespaced }} + namespace: {{ .name }} + {{- end }} spec: data: - secretKey: openshiftPullSecret diff --git a/acm/templates/provision/secrets-common.yaml b/acm/templates/provision/secrets-common.yaml index 474347c6..6901c79c 100644 --- a/acm/templates/provision/secrets-common.yaml +++ b/acm/templates/provision/secrets-common.yaml @@ -14,11 +14,11 @@ {{- range .clusterDeployments }} {{- $deploymentName := print .name "-" $group.name }} --- -{{- template "secret.install-config" (dict "name" $deploymentName "context" .) }} +{{- template "secret.install-config" (dict "name" $deploymentName "context" . "namespaced" true) }} --- -{{- template "externalsecret.pull-secret" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} +{{- template "externalsecret.pull-secret" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore "namespaced" true) }} --- -{{- template "externalsecret.ssh.private.key" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore) }} +{{- template "externalsecret.ssh.private.key" (dict "name" $deploymentName "context" . "secretStore" $.Values.secretStore "namespaced" true) }} {{- end }}{{- /* range .clusterDeplyments */}} {{- end }}{{- /* range .Values.clusterGroup.managedClusterGroups */}} @@ -28,6 +28,9 @@ apiVersion: v1 kind: Secret metadata: name: {{ .name }}-install-config + {{- if .namespaced }} + namespace: {{ .name }} + {{- end }} data: # Base64 encoding of install-config yaml install-config.yaml: {{ include "cluster.install-config" .context | b64enc }} @@ -39,6 +42,9 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: {{ .name }}-pull-secret + {{- if .namespaced }} + namespace: {{ .name }} + {{- end }} spec: data: - secretKey: openshiftPullSecret @@ -65,6 +71,9 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: {{ .name }}-ssh-private-key + {{- if .namespaced }} + namespace: {{ .name }} + {{- end }} spec: data: - secretKey: sshPrivateKey diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 3e6fbc74..7969434f 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -36,6 +36,7 @@ apiVersion: v1 kind: Secret metadata: name: aws-cd-one-w-pool-acm-provision-edge-install-config + namespace: aws-cd-one-w-pool-acm-provision-edge data: # Base64 encoding of install-config yaml install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXdzLWNkLW9uZS13LXBvb2wnIApiYXNlRG9tYWluOiBibHVlcHJpbnRzLnJoZWNvZW5nLmNvbQpjb250cm9sUGxhbmU6CiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgbmFtZTogY29udHJvbFBsYW5lCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF3czoKICAgICAgdHlwZTogbTUueGxhcmdlCmNvbXB1dGU6Ci0gaHlwZXJ0aHJlYWRpbmc6IEVuYWJsZWQKICBhcmNoaXRlY3R1cmU6IGFtZDY0CiAgbmFtZTogJ3dvcmtlcicKICByZXBsaWNhczogMwogIHBsYXRmb3JtOgogICAgYXdzOgogICAgICB0eXBlOiBtNS54bGFyZ2UKbmV0d29ya2luZzoKICBjbHVzdGVyTmV0d29yazoKICAtIGNpZHI6IDEwLjEyOC4wLjAvMTQKICAgIGhvc3RQcmVmaXg6IDIzCiAgbWFjaGluZU5ldHdvcms6CiAgLSBjaWRyOiAxMC4wLjAuMC8xNgogIG5ldHdvcmtUeXBlOiBPVk5LdWJlcm5ldGVzCiAgc2VydmljZU5ldHdvcms6CiAgLSAxNzIuMzAuMC4wLzE2CnBsYXRmb3JtOgogIGF3czoKICAgIHJlZ2lvbjogYXAtc291dGhlYXN0LTEKcHVsbFNlY3JldDogIiIgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cwpzc2hLZXk6ICIiICAgICAjIHNraXAsIGhpdmUgd2lsbCBpbmplY3QgYmFzZWQgb24gaXQncyBzZWNyZXRz @@ -46,6 +47,7 @@ apiVersion: v1 kind: Secret metadata: name: aws-cd-two-wo-pool-acm-provision-on-deploy-install-config + namespace: aws-cd-two-wo-pool-acm-provision-on-deploy data: # Base64 encoding of install-config yaml install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXdzLWNkLXR3by13by1wb29sJyAKYmFzZURvbWFpbjogYmx1ZXByaW50cy5yaGVjb2VuZy5jb20KY29udHJvbFBsYW5lOgogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIG5hbWU6IGNvbnRyb2xQbGFuZQogIHJlcGxpY2FzOiAzCiAgcGxhdGZvcm06CiAgICBhd3M6CiAgICAgIHR5cGU6IG01LnhsYXJnZQpjb21wdXRlOgotIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIG5hbWU6ICd3b3JrZXInCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF3czoKICAgICAgdHlwZTogbTUueGxhcmdlCm5ldHdvcmtpbmc6CiAgY2x1c3Rlck5ldHdvcms6CiAgLSBjaWRyOiAxMC4xMjguMC4wLzE0CiAgICBob3N0UHJlZml4OiAyMwogIG1hY2hpbmVOZXR3b3JrOgogIC0gY2lkcjogMTAuMC4wLjAvMTYKICBuZXR3b3JrVHlwZTogT1ZOS3ViZXJuZXRlcwogIHNlcnZpY2VOZXR3b3JrOgogIC0gMTcyLjMwLjAuMC8xNgpwbGF0Zm9ybToKICBhd3M6CiAgICByZWdpb246IGFwLXNvdXRoZWFzdC0zCnB1bGxTZWNyZXQ6ICIiICMgc2tpcCwgaGl2ZSB3aWxsIGluamVjdCBiYXNlZCBvbiBpdCdzIHNlY3JldHMKc3NoS2V5OiAiIiAgICAgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cw== @@ -294,6 +296,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-cd-one-w-pool-acm-provision-edge-creds + namespace: aws-cd-one-w-pool-acm-provision-edge spec: dataFrom: - extract: @@ -315,6 +318,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-cd-one-w-pool-acm-provision-edge-infra-creds + namespace: aws-cd-one-w-pool-acm-provision-edge spec: data: - secretKey: openshiftPullSecret @@ -372,6 +376,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-cd-two-wo-pool-acm-provision-on-deploy-creds + namespace: aws-cd-two-wo-pool-acm-provision-on-deploy spec: dataFrom: - extract: @@ -393,6 +398,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-cd-two-wo-pool-acm-provision-on-deploy-infra-creds + namespace: aws-cd-two-wo-pool-acm-provision-on-deploy spec: data: - secretKey: openshiftPullSecret @@ -624,6 +630,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-cd-one-w-pool-acm-provision-edge-pull-secret + namespace: aws-cd-one-w-pool-acm-provision-edge spec: data: - secretKey: openshiftPullSecret @@ -648,6 +655,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-cd-one-w-pool-acm-provision-edge-ssh-private-key + namespace: aws-cd-one-w-pool-acm-provision-edge spec: data: - secretKey: sshPrivateKey @@ -672,6 +680,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-cd-two-wo-pool-acm-provision-on-deploy-pull-secret + namespace: aws-cd-two-wo-pool-acm-provision-on-deploy spec: data: - secretKey: openshiftPullSecret @@ -696,6 +705,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-cd-two-wo-pool-acm-provision-on-deploy-ssh-private-key + namespace: aws-cd-two-wo-pool-acm-provision-on-deploy spec: data: - secretKey: sshPrivateKey From ff40ddc8cc1e85ba5bd6d54654c572d07ae12f1c Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 30 May 2024 10:03:47 +0200 Subject: [PATCH 24/77] Force rolebindings as early as possible This is important because in some situations (we've observed this on the clusterwide argo instance on spokes) the permissions are not there yet when argo tries to create service accounts for the imperative SAs. This means that the very first sync works up to the service account creation which then fails due to lacking RBACs. This triggers a gitops issue where selfheal never retries because the previous run failed and so the app is in a stuck loop forever Co-Authored-By: Jonny Rickard Closes: GITOPS-4677 --- clustergroup/templates/plumbing/argocd-super-role.yaml | 8 ++++++++ tests/clustergroup-industrial-edge-factory.expected.yaml | 8 ++++++++ tests/clustergroup-industrial-edge-hub.expected.yaml | 8 ++++++++ tests/clustergroup-medical-diagnosis-hub.expected.yaml | 8 ++++++++ tests/clustergroup-naked.expected.yaml | 8 ++++++++ tests/clustergroup-normal.expected.yaml | 8 ++++++++ 6 files changed, 48 insertions(+) diff --git a/clustergroup/templates/plumbing/argocd-super-role.yaml b/clustergroup/templates/plumbing/argocd-super-role.yaml index 2d5f8f76..11366a0b 100644 --- a/clustergroup/templates/plumbing/argocd-super-role.yaml +++ b/clustergroup/templates/plumbing/argocd-super-role.yaml @@ -4,6 +4,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: openshift-gitops-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -22,6 +26,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: {{ $.Values.global.pattern }}-{{ .Values.clusterGroup.name }}-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index 356b7e7e..4e18f8cb 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -321,6 +321,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: openshift-gitops-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -340,6 +344,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: mypattern-factory-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 3291aeb2..1af3211d 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -482,6 +482,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: openshift-gitops-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -501,6 +505,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: mypattern-datacenter-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 6e300fc3..2d9a4d36 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -409,6 +409,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: openshift-gitops-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -428,6 +432,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: mypattern-hub-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index 6f1c6b2e..a7fee415 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -174,6 +174,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: openshift-gitops-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -193,6 +197,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: common-example-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index 41eb68b8..7bb75394 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -371,6 +371,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: openshift-gitops-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -390,6 +394,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: mypattern-example-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole From 113a9076b64ac070866050c31e692c2da62b3cdd Mon Sep 17 00:00:00 2001 From: Lester Claudio Date: Wed, 29 May 2024 14:06:55 -0600 Subject: [PATCH 25/77] bug: Invalid OperatorGroup generated when ommitting targetNamespaces Problem Statement: When setting a namespace like this: - openshift-distributed-tracing: operatorGroup: true targetNamespaces: [] The chart generates the following yaml: ```yaml apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: name: openshift-distributed-tracing-operator-group namespace: openshift-distributed-tracing spec: targetNamespaces: ``` Which k8s rejects the targetNamespaces key as invalid when it attempts to apply it and removes it since it doesn't have a value, which just so happens to have the desired result of not setting the targetNamespaces (or a selector) to enable it for All Namespaces. --- clustergroup/templates/_helpers.tpl | 12 +++++++++--- clustergroup/templates/core/operatorgroup.yaml | 10 +++++++--- clustergroup/templates/plumbing/applications.yaml | 2 +- tests/clustergroup-normal.expected.yaml | 2 -- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/clustergroup/templates/_helpers.tpl b/clustergroup/templates/_helpers.tpl index 5001a06e..c6d14d08 100644 --- a/clustergroup/templates/_helpers.tpl +++ b/clustergroup/templates/_helpers.tpl @@ -202,13 +202,19 @@ kind: OperatorGroup metadata: name: {{ $k }}-operator-group namespace: {{ $k }} + {{- if (hasKey $v "targetNamespaces") }} + {{- if $v.targetNamespaces }} + {{- if (len $v.targetNamespaces) }} spec: targetNamespaces: - {{- if (hasKey $v "targetNamespaces") }} - {{- range $v.targetNamespaces }}{{- /* We loop through the list of tergetnamespaces */}} + {{- range $v.targetNamespaces }}{{- /* We loop through the list of tergetnamespaces */}} - {{ . }} - {{- end }}{{- /* End range targetNamespaces */}} + {{- end }}{{- /* End range targetNamespaces */}} + {{- end }}{{- /* End if (len $v.targetNamespaces) */}} + {{- end }}{{- /* End $v.targetNamespaces */}} {{- else }} +spec: + targetNamespaces: - {{ $k }} {{- end }}{{- /* End of if hasKey $v "targetNamespaces" */}} {{- end }}{{- /* End if $v.operatorGroup */}} diff --git a/clustergroup/templates/core/operatorgroup.yaml b/clustergroup/templates/core/operatorgroup.yaml index 4d8c3014..6adfef47 100644 --- a/clustergroup/templates/core/operatorgroup.yaml +++ b/clustergroup/templates/core/operatorgroup.yaml @@ -21,15 +21,19 @@ kind: OperatorGroup metadata: name: {{ $k }}-operator-group namespace: {{ $k }} + {{- if (hasKey $v "targetNamespaces") }} + {{- if $v.targetNamespaces }} spec: targetNamespaces: - {{- if (hasKey $v "targetNamespaces") }} {{- range $v.targetNamespaces }}{{- /* We loop through the list of tergetnamespaces */}} - {{ . }} {{- end }}{{- /* End range targetNamespaces */}} - {{- else }} + {{- end }}{{- /* End if $v.targetNamespaces */}} + {{- else }} +spec: + targetNamespaces: - {{ $k }} - {{- end }}{{- /* End of if operatorGroup */}} + {{- end }}{{- /* End of if (hasKey $v "targetNamespaces") */}} {{- end }}{{- /* range $k, $v := $ns */}} {{- end }}{{- /* End of if operatorGroup */}} {{- else if kindIs "string" $ns }} diff --git a/clustergroup/templates/plumbing/applications.yaml b/clustergroup/templates/plumbing/applications.yaml index 870babe3..0b9f4eda 100644 --- a/clustergroup/templates/plumbing/applications.yaml +++ b/clustergroup/templates/plumbing/applications.yaml @@ -78,7 +78,7 @@ spec: - name: global.namespace value: {{ $.Values.global.namespace }} - name: clusterGroup.name - value: {{ .Values.clusterGroup.name }} + value: {{ $.Values.clusterGroup.name }} {{- range .extraHubClusterDomainFields }} - name: {{ . }} value: {{ $.Values.global.hubClusterDomain }} diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index 41eb68b8..c594b65e 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -1197,8 +1197,6 @@ kind: OperatorGroup metadata: name: exclude-targetns-operator-group namespace: exclude-targetns -spec: - targetNamespaces: --- # Source: clustergroup/templates/core/operatorgroup.yaml --- From ad87c84b9643b66e3994215dcd6cb830fcefad52 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 30 May 2024 17:26:23 +0200 Subject: [PATCH 26/77] Fix CI issue --- tests/acm-normal.expected.yaml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 8abd52ef..8e78a98f 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -1219,15 +1219,17 @@ spec: path: common/clustergroup helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - - "/values-global.yaml" - - "/values-acm-provision-on-deploy.yaml" - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' - - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-provision-on-deploy.yaml' - # We cannot use $.Values.global.clusterVersion because that gets resolved to the - # hub's cluster version, whereas we want to include the spoke cluster version - - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - "/values-global.yaml" + - "/values-acm-provision-on-deploy.yaml" + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-provision-on-deploy.yaml' + # We cannot use $.Values.global.clusterVersion because that gets resolved to the + # hub's cluster version, whereas we want to include the spoke cluster version + - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' parameters: - name: global.repoURL value: https://github.com/pattern-clone/mypattern @@ -1241,10 +1243,8 @@ spec: value: apps.hub.example.com - name: global.localClusterDomain value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}' - # Requires ACM 2.6 or higher - name: global.clusterDomain value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}' - # Requires ACM 2.6 or higher (I could not come up with something less terrible to get maj.min) - name: global.clusterVersion value: '{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}' - name: global.localClusterName From beb71a1ba529dc6f50454ff947e2f8e547ae1cae Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 3 Jun 2024 19:09:52 +0200 Subject: [PATCH 27/77] Actually use adminServiceAccountName for the auto approve job --- .../templates/imperative/auto-approve-installplans.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustergroup/templates/imperative/auto-approve-installplans.yaml b/clustergroup/templates/imperative/auto-approve-installplans.yaml index e6ebf26c..23e6b133 100644 --- a/clustergroup/templates/imperative/auto-approve-installplans.yaml +++ b/clustergroup/templates/imperative/auto-approve-installplans.yaml @@ -16,7 +16,7 @@ spec: metadata: name: auto-approve-installplans-job spec: - serviceAccountName: {{ $.Values.clusterGroup.imperative.serviceAccountName }} + serviceAccountName: {{ $.Values.clusterGroup.imperative.adminServiceAccountName }} initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there From 39addf213792aa75d323f83c618fe49fa77c9819 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 4 Jun 2024 10:39:39 +0200 Subject: [PATCH 28/77] Make sure that the if condition on chart split is not always true This should fix the fact that jobs are triggered on unrelated changes --- .github/workflows/chart-branches.yml | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/.github/workflows/chart-branches.yml b/.github/workflows/chart-branches.yml index 1a4fb455..4fb784f0 100644 --- a/.github/workflows/chart-branches.yml +++ b/.github/workflows/chart-branches.yml @@ -49,9 +49,7 @@ jobs: acm: needs: changes - if: | - ${{ needs.changes.outputs.acm == 'true' }} && - github.repository == 'validatedpatterns/common' + if: ${{ (needs.changes.outputs.acm == 'true') && (github.repository == 'validatedpatterns/common') }} uses: validatedpatterns/common/.github/workflows/chart-split.yml@main permissions: actions: write @@ -63,9 +61,7 @@ jobs: golang-external-secrets: needs: changes - if: | - ${{ needs.changes.outputs.golang-external-secrets == 'true' }} && - github.repository == 'validatedpatterns/common' + if: ${{ (needs.changes.outputs.golang-external-secrets == 'true') && (github.repository == 'validatedpatterns/common') }} uses: validatedpatterns/common/.github/workflows/chart-split.yml@main permissions: actions: write @@ -77,9 +73,7 @@ jobs: hashicorp-vault: needs: changes - if: | - ${{ needs.changes.outputs.hashicorp-vault == 'true' }} && - github.repository == 'validatedpatterns/common' + if: ${{ (needs.changes.outputs.hashicorp-vault == 'true') && (github.repository == 'validatedpatterns/common') }} uses: validatedpatterns/common/.github/workflows/chart-split.yml@main permissions: actions: write @@ -91,9 +85,7 @@ jobs: letsencrypt: needs: changes - if: | - ${{ needs.changes.outputs.letsencrypt == 'true' }} && - github.repository == 'validatedpatterns/common' + if: ${{ (needs.changes.outputs.letsencrypt == 'true') && (github.repository == 'validatedpatterns/common') }} uses: validatedpatterns/common/.github/workflows/chart-split.yml@main permissions: actions: write @@ -105,9 +97,7 @@ jobs: clustergroup: needs: changes - if: | - ${{ needs.changes.outputs.clustergroup == 'true' }} && - github.repository == 'validatedpatterns/common' + if: ${{ (needs.changes.outputs.clustergroup == 'true') && (github.repository == 'validatedpatterns/common') }} uses: validatedpatterns/common/.github/workflows/chart-split.yml@main permissions: actions: write From 10b06654858958f9af5ddb7adbf7fafd65cd9b99 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 4 Jun 2024 10:49:05 +0200 Subject: [PATCH 29/77] Bump super-linter from 5 to 6 --- .github/workflows/superlinter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/superlinter.yml b/.github/workflows/superlinter.yml index 7430db09..ca6daab0 100644 --- a/.github/workflows/superlinter.yml +++ b/.github/workflows/superlinter.yml @@ -21,7 +21,7 @@ jobs: # Run Linter against code base # ################################ - name: Lint Code Base - uses: github/super-linter/slim@v5 + uses: github/super-linter/slim@v6 env: VALIDATE_ALL_CODEBASE: true DEFAULT_BRANCH: main From c85ada60e6d5be2478a5ab2941a9ceddfbe6eb3a Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 4 Jun 2024 10:53:41 +0200 Subject: [PATCH 30/77] Drop some validations for now --- .github/workflows/superlinter.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/superlinter.yml b/.github/workflows/superlinter.yml index ca6daab0..55acbdb0 100644 --- a/.github/workflows/superlinter.yml +++ b/.github/workflows/superlinter.yml @@ -29,8 +29,11 @@ jobs: # These are the validation we disable atm VALIDATE_ANSIBLE: false VALIDATE_BASH: false + VALIDATE_CHECKOV: false VALIDATE_JSCPD: false VALIDATE_KUBERNETES_KUBECONFORM: false + VALIDATE_PYTHON_PYLINT: false + VALIDATE_SHELL_SHFMT: false VALIDATE_YAML: false # VALIDATE_DOCKERFILE_HADOLINT: false # VALIDATE_MARKDOWN: false From a232db50c15ca3e3d450e8d5cdb7b4a5ed83c48a Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 4 Jun 2024 11:05:24 +0200 Subject: [PATCH 31/77] Add some debugging to the chart split action --- .github/workflows/chart-split.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/chart-split.yml b/.github/workflows/chart-split.yml index 2792d6ad..ad356e61 100644 --- a/.github/workflows/chart-split.yml +++ b/.github/workflows/chart-split.yml @@ -31,8 +31,10 @@ jobs: set -e N="${{ inputs.chart_name }}" B="${N}-main-single-chart" + echo "Running subtree split for ${B}" git push origin -d "${B}" || /bin/true git subtree split -P "${N}" -b "${B}" + git remote -v git push -f -u origin "${B}" #git clone https://validatedpatterns:${GITHUB_TOKEN}@github.com/validatedpatterns/common.git -b "acm-main-single-chart" --single-branch git push --force https://validatedpatterns:"${GITHUB_TOKEN}"@github.com/${{ inputs.target_repository }}.git "${B}:main" From 821727ad13f3b779d47efd1444bb5fcda7dc4738 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 4 Jun 2024 16:01:46 +0200 Subject: [PATCH 32/77] Use a specific git version when running git subtree split Otherwise we will get errors during the command as git subtree has regressed since v2.44.0 --- .github/workflows/chart-split.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/chart-split.yml b/.github/workflows/chart-split.yml index ad356e61..39ee9c01 100644 --- a/.github/workflows/chart-split.yml +++ b/.github/workflows/chart-split.yml @@ -31,10 +31,12 @@ jobs: set -e N="${{ inputs.chart_name }}" B="${N}-main-single-chart" + GITIMG="quay.io/hybridcloudpatterns/gitsubtree-container:2.40.1" + sudo apt-get update -y && apt-get install -y podman echo "Running subtree split for ${B}" + podman pull "${GITIMG}" git push origin -d "${B}" || /bin/true - git subtree split -P "${N}" -b "${B}" - git remote -v - git push -f -u origin "${B}" + # Git subtree got broken on recent versions of git hence this container + podman run --net=host --rm -t -v .:/git "${GITIMG}" subtree split -P "${N}" -b "${B}" #git clone https://validatedpatterns:${GITHUB_TOKEN}@github.com/validatedpatterns/common.git -b "acm-main-single-chart" --single-branch git push --force https://validatedpatterns:"${GITHUB_TOKEN}"@github.com/${{ inputs.target_repository }}.git "${B}:main" From 3061644432685ff5b77276d194739e1af71c4d3b Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 4 Jun 2024 16:17:00 +0200 Subject: [PATCH 33/77] Release clustergroup v0.8.6 --- clustergroup/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustergroup/Chart.yaml b/clustergroup/Chart.yaml index e2d4f98b..2ddd15ba 100644 --- a/clustergroup/Chart.yaml +++ b/clustergroup/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to create per-clustergroup ArgoCD applications and any keywords: - pattern name: clustergroup -version: 0.8.5 +version: 0.8.6 From ae14cd2bfab2a3fc7fe8cb83941b52c87c97547a Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 4 Jun 2024 16:22:57 +0200 Subject: [PATCH 34/77] Add a sudo to apt-get command --- .github/workflows/chart-split.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/chart-split.yml b/.github/workflows/chart-split.yml index 39ee9c01..150e419b 100644 --- a/.github/workflows/chart-split.yml +++ b/.github/workflows/chart-split.yml @@ -32,7 +32,7 @@ jobs: N="${{ inputs.chart_name }}" B="${N}-main-single-chart" GITIMG="quay.io/hybridcloudpatterns/gitsubtree-container:2.40.1" - sudo apt-get update -y && apt-get install -y podman + sudo apt-get update -y && sudo apt-get install -y podman echo "Running subtree split for ${B}" podman pull "${GITIMG}" git push origin -d "${B}" || /bin/true From 17325d65776a7508c89f84ebbec9eebf37f04ad7 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 6 Jun 2024 08:52:27 +0200 Subject: [PATCH 35/77] Add some READMEs in the individual charts --- acm/README.md | 5 +++++ clustergroup/README.md | 5 +++++ golang-external-secrets/README.md | 4 ++++ hashicorp-vault/README.md | 4 ++++ letsencrypt/README.md | 4 ++++ 5 files changed, 22 insertions(+) create mode 100644 acm/README.md create mode 100644 clustergroup/README.md diff --git a/acm/README.md b/acm/README.md new file mode 100644 index 00000000..c8c67635 --- /dev/null +++ b/acm/README.md @@ -0,0 +1,5 @@ +# Validated Patterns ACM chart + +This chart is used to set up ACM in Validated Patterns https://validatedpatterns.io + +Please send PRs to https://github.com/validatedpatterns/common diff --git a/clustergroup/README.md b/clustergroup/README.md new file mode 100644 index 00000000..8983ddf9 --- /dev/null +++ b/clustergroup/README.md @@ -0,0 +1,5 @@ +# Validated Patterns ClusterGroup chart + +This chart is used to set up the basic building blocks in Validated Patterns https://validatedpatterns.io + +Please send PRs to https://github.com/validatedpatterns/common diff --git a/golang-external-secrets/README.md b/golang-external-secrets/README.md index e12d58f1..6d9e0f41 100644 --- a/golang-external-secrets/README.md +++ b/golang-external-secrets/README.md @@ -12,3 +12,7 @@ we just override the tag with the version + "-ubi" 4. Tweak `values.yaml` with the new image versions 5. Run `make test` 6. Commit to git + +## PRs + +Please send PRs to https://github.com/validatedpatterns/common diff --git a/hashicorp-vault/README.md b/hashicorp-vault/README.md index 26252b7e..6d5fefd6 100644 --- a/hashicorp-vault/README.md +++ b/hashicorp-vault/README.md @@ -1,5 +1,9 @@ # VP hashicorp-vault +## PRs + +Please send PRs to https://github.com/validatedpatterns/common + ## Updating the chart 1. Edit Chart.yaml with the new version diff --git a/letsencrypt/README.md b/letsencrypt/README.md index d277abaa..549e44e8 100644 --- a/letsencrypt/README.md +++ b/letsencrypt/README.md @@ -22,6 +22,10 @@ In order to enable this chart in your patterns, please add and edit the followin Once the above is enabled in a pattern, a certain amount of time (~15/20 minutes or so) is needed for all the cluster operators to settle, all the HTTPS routes will have a wildcard certificate signed by letsencrypt. By default also the API endpoint will use a certificate signed by letsencrypt. +## PRs + +Please send PRs to https://github.com/validatedpatterns/common + ## Limitations Please be aware of the following gotchas when using this chart: From 55230973793444aa5d0e43088ef9b637d17f8e33 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 6 Jun 2024 09:01:37 +0200 Subject: [PATCH 36/77] Fix super-linter issues and upgrade local super-linter target --- Makefile | 11 +++++++---- acm/README.md | 4 ++-- clustergroup/README.md | 4 ++-- golang-external-secrets/README.md | 2 +- hashicorp-vault/README.md | 2 +- letsencrypt/README.md | 2 +- 6 files changed, 14 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index 86cb5177..f9b00e57 100644 --- a/Makefile +++ b/Makefile @@ -230,17 +230,20 @@ kubeconform: ## run helm kubeconform super-linter: ## Runs super linter locally rm -rf .mypy_cache podman run -e RUN_LOCAL=true -e USE_FIND_ALGORITHM=true \ + -e VALIDATE_ANSIBLE=false \ -e VALIDATE_BASH=false \ + -e VALIDATE_CHECKOV=false \ + -e VALIDATE_DOCKERFILE_HADOLINT=false \ -e VALIDATE_JSCPD=false \ -e VALIDATE_KUBERNETES_KUBECONFORM=false \ - -e VALIDATE_YAML=false \ - -e VALIDATE_ANSIBLE=false \ - -e VALIDATE_DOCKERFILE_HADOLINT=false \ + -e VALIDATE_PYTHON_PYLINT=false \ + -e VALIDATE_SHELL_SHFMT=false \ -e VALIDATE_TEKTON=false \ + -e VALIDATE_YAML=false \ $(DISABLE_LINTERS) \ -v $(PWD):/tmp/lint:rw,z \ -w /tmp/lint \ - docker.io/github/super-linter:slim-v5 + ghcr.io/super-linter/super-linter:slim-v6 .PHONY: ansible-lint ansible-lint: ## run ansible lint on ansible/ folder diff --git a/acm/README.md b/acm/README.md index c8c67635..56b39ae3 100644 --- a/acm/README.md +++ b/acm/README.md @@ -1,5 +1,5 @@ # Validated Patterns ACM chart -This chart is used to set up ACM in Validated Patterns https://validatedpatterns.io +This chart is used to set up ACM in [Validated Patterns](https://validatedpatterns.io) -Please send PRs to https://github.com/validatedpatterns/common +Please send PRs [here](https://github.com/validatedpatterns/common) diff --git a/clustergroup/README.md b/clustergroup/README.md index 8983ddf9..bb522d12 100644 --- a/clustergroup/README.md +++ b/clustergroup/README.md @@ -1,5 +1,5 @@ # Validated Patterns ClusterGroup chart -This chart is used to set up the basic building blocks in Validated Patterns https://validatedpatterns.io +This chart is used to set up the basic building blocks in [Validated Patterns](https://validatedpatterns.io) -Please send PRs to https://github.com/validatedpatterns/common +Please send PRs [here](https://github.com/validatedpatterns/common) diff --git a/golang-external-secrets/README.md b/golang-external-secrets/README.md index 6d9e0f41..4316d3a1 100644 --- a/golang-external-secrets/README.md +++ b/golang-external-secrets/README.md @@ -15,4 +15,4 @@ we just override the tag with the version + "-ubi" ## PRs -Please send PRs to https://github.com/validatedpatterns/common +Please send PRs [here](https://github.com/validatedpatterns/common) diff --git a/hashicorp-vault/README.md b/hashicorp-vault/README.md index 6d5fefd6..28362080 100644 --- a/hashicorp-vault/README.md +++ b/hashicorp-vault/README.md @@ -2,7 +2,7 @@ ## PRs -Please send PRs to https://github.com/validatedpatterns/common +Please send PRs [here](https://github.com/validatedpatterns/common) ## Updating the chart diff --git a/letsencrypt/README.md b/letsencrypt/README.md index 549e44e8..ded97205 100644 --- a/letsencrypt/README.md +++ b/letsencrypt/README.md @@ -24,7 +24,7 @@ Once the above is enabled in a pattern, a certain amount of time (~15/20 minutes ## PRs -Please send PRs to https://github.com/validatedpatterns/common +Please send PRs [here](https://github.com/validatedpatterns/common) ## Limitations From e3babbbaeea77385cc9f6423b4433fce15a15781 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 6 Jun 2024 10:41:00 +0200 Subject: [PATCH 37/77] Skip unreachable spokes when setting up vault MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When setting up vault we loop through all the managed clusters and set up the token so ESO can fetch certain paths in vault. This happens in the unseal vault ansible job and will fail if one of the managed clusters is unreachable. This is undesirable because a cluster might have been shut down on purpose or might be temporarily not reachable and this is no reason to stop the configuration of vault. Tested as follows: 1. Deployed mcg on sno1 and sno2. All green. 2. Shut off sno2 so it is unreachable. observed unseal-cronjob fail (took a while but eventually failed with: ``` TASK [vault_utils : Fetch remote ansible to remote cluster] ******************** ok: [localhost] => (item=local-cluster) An exception occurred during task execution. To see the full traceback, use -vvv. The error was: urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='api.sno2.ocplab.ocp', port=6443): Max retries exceeded with url: /version (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 110] Connection timed out')) failed: [localhost] (item=sno2) => {"ansible_loop_var": "item", "changed": false, "item": {"key": "sno2", "value": {"bearerToken": "eyJhbGciOiJSUzI1... ``` 3. Imported sno3 into the hub on sno1. observed unseal-cronjob still fail: ``` TASK [vault_utils : Fetch remote ansible to remote cluster] ******************** ok: [localhost] => (item=local-cluster) An exception occurred during task execution. To see the full traceback, use -vvv. The error was: urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='api.sno2.ocplab.ocp', port=6443): Max retries exceeded with url: /version (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 110] Connection timed out')) failed: [localhost] (item=sno2) => {"ansible_loop_var": "item", "changed": false, "item": {"key": "sno2", "value": {"bearerToken": "ey... ok: [localhost] => (item=sno3) PLAY RECAP ********************************************************************* localhost : ok=37 changed=11 unreachable=0 failed=1 skipped=13 rescued=0 ignored=0 ``` 4. After the ignore_errors patch: ``` TASK [vault_utils : Fetch remote ansible to remote cluster] ******************** ok: [localhost] => (item=local-cluster) An exception occurred during task execution. To see the full traceback, use -vvv. The error was: urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='api.sno2.ocplab.ocp', port=6443): Max retries exceeded with url: /version (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 110] Connection timed out')) failed: [localhost] (item=sno2) => {"ansible_loop_var": "item", "changed": false, "item": {"key": "sno2", "value": {"bearerToken": "eyJhb.... ok: [localhost] => (item=sno3) ...ignoring # sno2 correctly gets skipped in the subsequent tasks ``` sno3 did manage to login to the vault and everything just worked Reported-by: François Charette --- ansible/roles/vault_utils/tasks/vault_spokes_init.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml b/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml index e930252a..92000b90 100644 --- a/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml +++ b/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml @@ -72,6 +72,11 @@ api_version: v1 validate_certs: "{{ validate_certs_api_endpoint }}" register: remote_external_secrets_sa + # We are allowed to ignore errors here because a spoke might be down or unreachable + # if a spoke is not reachable then its ['token'] field will not be set which + # will leave the ['esoToken'] field empty in the dict which will make it so that + # the spoke gets skipped + ignore_errors: true when: - clusters_info[item.key]['bearerToken'] is defined - clusters_info[item.key]['server_api'] is defined From 3ec1839635f24172ab6d1ebda88cf6983b3724a5 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 7 Jun 2024 09:28:55 +0200 Subject: [PATCH 38/77] Add no_log to spokes initialization task --- ansible/roles/vault_utils/tasks/vault_spokes_init.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml b/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml index 92000b90..060378bc 100644 --- a/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml +++ b/ansible/roles/vault_utils/tasks/vault_spokes_init.yaml @@ -77,6 +77,11 @@ # will leave the ['esoToken'] field empty in the dict which will make it so that # the spoke gets skipped ignore_errors: true + # We add no_log: true here because in case of a remote failure secret bits might + # end up in the log. Unfortunately ansible is currently not easily able to control + # output in a loop (see + # https://serverfault.com/questions/1059530/how-to-not-print-items-in-an-ansible-loop-error-without-no-log) + no_log: true when: - clusters_info[item.key]['bearerToken'] is defined - clusters_info[item.key]['server_api'] is defined From 9809c86af214c3d383afc2ce2bbe03f396a688e4 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Thu, 6 Jun 2024 17:48:15 +0200 Subject: [PATCH 39/77] Drop initContainers variable and make it the default This will allow us to work with external CAs out of the box and also it will allow the framework to be able use internal gitea instances out of the box. Tested as follows: 1. Deployed stock MCG with no changes 2. Changed the MCG repo to one with this patch 3. Observed initContainers to show up on: A. namespaced argo on hub B. clusterwide argo on spoke C. namespaced argo on spoke 4. All applications still worked 5. Deployed mcg from scratch using a branch with this patch (with multisource set to false so we're sure we're testing the right common bits in the branch) --- acm/templates/policies/application-policies.yaml | 1 - acm/templates/policies/ocp-gitops-policy.yaml | 3 --- .../imperative/auto-approve-installplans.yaml | 11 ++++------- clustergroup/templates/imperative/job.yaml | 14 -------------- clustergroup/templates/imperative/unsealjob.yaml | 15 --------------- clustergroup/templates/plumbing/argocd.yaml | 7 ------- 6 files changed, 4 insertions(+), 47 deletions(-) diff --git a/acm/templates/policies/application-policies.yaml b/acm/templates/policies/application-policies.yaml index 2a815913..01073bd4 100644 --- a/acm/templates/policies/application-policies.yaml +++ b/acm/templates/policies/application-policies.yaml @@ -1,5 +1,4 @@ # TODO: Also create a GitOpsCluster.apps.open-cluster-management.io -{{- $hasInitContainerCapability := and (.Values.global.experimentalCapabilities) (has "initcontainers" (splitList "," .Values.global.experimentalCapabilities)) }} {{- range .Values.clusterGroup.managedClusterGroups }} {{- $group := . }} {{- if not .hostedArgoSites }} diff --git a/acm/templates/policies/ocp-gitops-policy.yaml b/acm/templates/policies/ocp-gitops-policy.yaml index e72434ae..29204254 100644 --- a/acm/templates/policies/ocp-gitops-policy.yaml +++ b/acm/templates/policies/ocp-gitops-policy.yaml @@ -1,4 +1,3 @@ -{{- $hasInitContainerCapability := and (.Values.global.experimentalCapabilities) (has "initcontainers" (splitList "," .Values.global.experimentalCapabilities)) }} apiVersion: policy.open-cluster-management.io/v1 kind: Policy metadata: @@ -54,7 +53,6 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" -{{- if $hasInitContainerCapability }} - complianceType: mustonlyhave objectDefinition: apiVersion: argoproj.io/v1beta1 @@ -215,7 +213,6 @@ spec: provider: dex tls: ca: {} -{{- end }}{{/* if hasInitContainerCapability */}} --- apiVersion: policy.open-cluster-management.io/v1 kind: PlacementBinding diff --git a/clustergroup/templates/imperative/auto-approve-installplans.yaml b/clustergroup/templates/imperative/auto-approve-installplans.yaml index 23e6b133..7b935e77 100644 --- a/clustergroup/templates/imperative/auto-approve-installplans.yaml +++ b/clustergroup/templates/imperative/auto-approve-installplans.yaml @@ -20,7 +20,8 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there - {{- include "imperative.initcontainers.gitinit" . | indent 12 }} + {{- include "imperative.initcontainers.fetch-ca" . | indent 12 }} + {{- include "imperative.initcontainers.gitinit-ca" . | indent 12 }} - name: auto-approve-installplans image: {{ $.Values.clusterGroup.imperative.image }} imagePullPolicy: {{ $.Values.clusterGroup.imperative.imagePullPolicy }} @@ -39,14 +40,10 @@ spec: - "@/values/values.yaml" - common/ansible/playbooks/auto-approve-installplans/auto-approve-installplans.yaml volumeMounts: - {{- include "imperative.volumemounts" . | indent 16 }} + {{- include "imperative.volumemounts_ca" . | indent 16 }} containers: {{- include "imperative.containers.done" . | indent 12 }} volumes: - - name: git - emptyDir: {} - - name: values-volume - configMap: - name: {{ $.Values.clusterGroup.imperative.valuesConfigMap }}-{{ $.Values.clusterGroup.name }} + {{- include "imperative.volumes_ca" . | indent 12 }} restartPolicy: Never {{- end }} diff --git a/clustergroup/templates/imperative/job.yaml b/clustergroup/templates/imperative/job.yaml index 0b82d47c..55400e8c 100644 --- a/clustergroup/templates/imperative/job.yaml +++ b/clustergroup/templates/imperative/job.yaml @@ -1,5 +1,3 @@ -{{- $hasInitContainerCapability := and (.Values.global.experimentalCapabilities) (has "initcontainers" (splitList "," .Values.global.experimentalCapabilities)) }} - {{- if not (eq .Values.enabled "plumbing") }} {{/* Define this if needed (jobs defined */}} {{- if (and $.Values.clusterGroup.imperative (gt (len $.Values.clusterGroup.imperative.jobs) 0)) -}} @@ -24,12 +22,8 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there -{{- if $hasInitContainerCapability }} {{- include "imperative.initcontainers.fetch-ca" . | indent 12 }} {{- include "imperative.initcontainers.gitinit-ca" . | indent 12 }} -{{- else }} - {{- include "imperative.initcontainers.gitinit" . | indent 12 }} -{{- end }} {{- range $.Values.clusterGroup.imperative.jobs }} {{- if ne (.disabled | default "false" | toString | lower ) "true" }} - name: {{ .name }} @@ -60,21 +54,13 @@ spec: {{- end }} - {{ .playbook }} volumeMounts: -{{- if $hasInitContainerCapability }} {{- include "imperative.volumemounts_ca" . | indent 16 }} -{{- else }} - {{- include "imperative.volumemounts" . | indent 16 }} -{{- end }} {{- end }} {{- end }} containers: {{- include "imperative.containers.done" . | indent 12 }} volumes: -{{- if $hasInitContainerCapability }} {{- include "imperative.volumes_ca" . | indent 12 }} -{{- else }} - {{- include "imperative.volumes" . | indent 12 }} -{{- end }} restartPolicy: Never {{- end }} {{- end }} diff --git a/clustergroup/templates/imperative/unsealjob.yaml b/clustergroup/templates/imperative/unsealjob.yaml index e0ff2c78..a7553da8 100644 --- a/clustergroup/templates/imperative/unsealjob.yaml +++ b/clustergroup/templates/imperative/unsealjob.yaml @@ -1,5 +1,3 @@ -{{- $hasInitContainerCapability := and (.Values.global.experimentalCapabilities) (has "initcontainers" (splitList "," .Values.global.experimentalCapabilities)) }} - {{/* If the backend is not set at all we default to "vault". See https://www.github.com/helm/helm/issues/3308 why we avoid using the default function */}} {{- if or (eq .Values.global.secretStore.backend "vault") (not (hasKey .Values.global.secretStore "backend")) }} @@ -26,13 +24,8 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there -{{- if $hasInitContainerCapability }} - {{- include "imperative.initcontainers.fetch-ca" . | indent 12 }} {{- include "imperative.initcontainers.gitinit-ca" . | indent 12 }} -{{- else }} - {{- include "imperative.initcontainers.gitinit" . | indent 12 }} -{{- end }} - name: unseal-playbook image: {{ $.Values.clusterGroup.imperative.image }} imagePullPolicy: {{ $.Values.clusterGroup.imperative.imagePullPolicy }} @@ -55,19 +48,11 @@ spec: - 'vault_init,vault_unseal,vault_secrets_init,vault_spokes_init' - "common/ansible/playbooks/vault/vault.yaml" volumeMounts: -{{- if $hasInitContainerCapability }} {{- include "imperative.volumemounts_ca" . | indent 16 }} -{{- else }} - {{- include "imperative.volumemounts" . | indent 16 }} -{{- end }} containers: {{- include "imperative.containers.done" . | indent 12 }} volumes: -{{- if $hasInitContainerCapability }} {{- include "imperative.volumes_ca" . | indent 12 }} -{{- else }} - {{- include "imperative.volumes" . | indent 12 }} -{{- end }} restartPolicy: Never {{- end }} {{- end }} diff --git a/clustergroup/templates/plumbing/argocd.yaml b/clustergroup/templates/plumbing/argocd.yaml index dcce1b4b..7d42ec36 100644 --- a/clustergroup/templates/plumbing/argocd.yaml +++ b/clustergroup/templates/plumbing/argocd.yaml @@ -1,4 +1,3 @@ -{{- $hasInitContainerCapability := and (.Values.global.experimentalCapabilities) (has "initcontainers" (splitList "," .Values.global.experimentalCapabilities)) }} {{- if (eq .Values.enabled "all") }} {{- $namespace := print $.Values.global.pattern "-" $.Values.clusterGroup.name }} @@ -70,7 +69,6 @@ spec: rbac: defaultPolicy: role:admin repo: -{{- if $hasInitContainerCapability }} initContainers: - command: - bash @@ -109,11 +107,6 @@ spec: {{- if len $.Values.clusterGroup.argoCD.initContainers }} {{ $.Values.clusterGroup.argoCD.initContainers | toPrettyJson }} {{- end }} -{{- else }} -{{- if len $.Values.clusterGroup.argoCD.initContainers }} - initContainers: {{ $.Values.clusterGroup.argoCD.initContainers | toPrettyJson }} -{{- end }} -{{- end }}{{/* if $hasInitContainerCapability */}} {{- if len $.Values.clusterGroup.argoCD.configManagementPlugins }} sidecarContainers: {{- range $cmp := $.Values.clusterGroup.argoCD.configManagementPlugins }} From 75f8385c1ea3c7743b52d4c13378504f8ce668a8 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 7 Jun 2024 10:19:23 +0200 Subject: [PATCH 40/77] Update tests after dropping initContainers --- .../acm-industrial-edge-factory.expected.yaml | 155 ++++++++++++++++++ tests/acm-industrial-edge-hub.expected.yaml | 155 ++++++++++++++++++ tests/acm-medical-diagnosis-hub.expected.yaml | 155 ++++++++++++++++++ tests/acm-naked.expected.yaml | 155 ++++++++++++++++++ tests/acm-normal.expected.yaml | 155 ++++++++++++++++++ ...roup-industrial-edge-factory.expected.yaml | 71 ++++++++ ...tergroup-industrial-edge-hub.expected.yaml | 107 ++++++++++++ ...rgroup-medical-diagnosis-hub.expected.yaml | 107 ++++++++++++ tests/clustergroup-naked.expected.yaml | 71 ++++++++ tests/clustergroup-normal.expected.yaml | 107 ++++++++++++ 10 files changed, 1238 insertions(+) diff --git a/tests/acm-industrial-edge-factory.expected.yaml b/tests/acm-industrial-edge-factory.expected.yaml index 561fbd7b..fa867edd 100644 --- a/tests/acm-industrial-edge-factory.expected.yaml +++ b/tests/acm-industrial-edge-factory.expected.yaml @@ -119,3 +119,158 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + apiVersion: argoproj.io/v1beta1 + kind: ArgoCD + metadata: + name: openshift-gitops + namespace: openshift-gitops + spec: + applicationSet: + resources: + limits: + cpu: "2" + memory: 1Gi + requests: + cpu: 250m + memory: 512Mi + webhookServer: + ingress: + enabled: false + route: + enabled: false + controller: + processors: {} + resources: + limits: + cpu: "2" + memory: 2Gi + requests: + cpu: 250m + memory: 1Gi + sharding: {} + grafana: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + route: + enabled: false + ha: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + initialSSHKnownHosts: {} + monitoring: + enabled: false + notifications: + enabled: false + prometheus: + enabled: false + ingress: + enabled: false + route: + enabled: false + rbac: + defaultPolicy: "" + policy: |- + g, system:cluster-admins, role:admin + g, cluster-admins, role:admin + scopes: '[groups]' + redis: + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + || true + image: registry.redhat.io/ubi9/ubi-minimal:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - emptyDir: {} + name: ca-bundles + resourceExclusions: |- + - apiGroups: + - tekton.dev + clusters: + - '*' + kinds: + - TaskRun + - PipelineRun + server: + autoscale: + enabled: false + grpc: + ingress: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 125m + memory: 128Mi + route: + enabled: true + service: + type: "" + sso: + dex: + openShiftOAuth: true + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + provider: dex + tls: + ca: {} diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml index 4199ba03..d715989d 100644 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ b/tests/acm-industrial-edge-hub.expected.yaml @@ -327,3 +327,158 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + apiVersion: argoproj.io/v1beta1 + kind: ArgoCD + metadata: + name: openshift-gitops + namespace: openshift-gitops + spec: + applicationSet: + resources: + limits: + cpu: "2" + memory: 1Gi + requests: + cpu: 250m + memory: 512Mi + webhookServer: + ingress: + enabled: false + route: + enabled: false + controller: + processors: {} + resources: + limits: + cpu: "2" + memory: 2Gi + requests: + cpu: 250m + memory: 1Gi + sharding: {} + grafana: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + route: + enabled: false + ha: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + initialSSHKnownHosts: {} + monitoring: + enabled: false + notifications: + enabled: false + prometheus: + enabled: false + ingress: + enabled: false + route: + enabled: false + rbac: + defaultPolicy: "" + policy: |- + g, system:cluster-admins, role:admin + g, cluster-admins, role:admin + scopes: '[groups]' + redis: + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + || true + image: registry.redhat.io/ubi9/ubi-minimal:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - emptyDir: {} + name: ca-bundles + resourceExclusions: |- + - apiGroups: + - tekton.dev + clusters: + - '*' + kinds: + - TaskRun + - PipelineRun + server: + autoscale: + enabled: false + grpc: + ingress: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 125m + memory: 128Mi + route: + enabled: true + service: + type: "" + sso: + dex: + openShiftOAuth: true + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + provider: dex + tls: + ca: {} diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml index f2a8fdd6..2fd25e75 100644 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ b/tests/acm-medical-diagnosis-hub.expected.yaml @@ -318,3 +318,158 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + apiVersion: argoproj.io/v1beta1 + kind: ArgoCD + metadata: + name: openshift-gitops + namespace: openshift-gitops + spec: + applicationSet: + resources: + limits: + cpu: "2" + memory: 1Gi + requests: + cpu: 250m + memory: 512Mi + webhookServer: + ingress: + enabled: false + route: + enabled: false + controller: + processors: {} + resources: + limits: + cpu: "2" + memory: 2Gi + requests: + cpu: 250m + memory: 1Gi + sharding: {} + grafana: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + route: + enabled: false + ha: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + initialSSHKnownHosts: {} + monitoring: + enabled: false + notifications: + enabled: false + prometheus: + enabled: false + ingress: + enabled: false + route: + enabled: false + rbac: + defaultPolicy: "" + policy: |- + g, system:cluster-admins, role:admin + g, cluster-admins, role:admin + scopes: '[groups]' + redis: + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + || true + image: registry.redhat.io/ubi9/ubi-minimal:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - emptyDir: {} + name: ca-bundles + resourceExclusions: |- + - apiGroups: + - tekton.dev + clusters: + - '*' + kinds: + - TaskRun + - PipelineRun + server: + autoscale: + enabled: false + grpc: + ingress: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 125m + memory: 128Mi + route: + enabled: true + service: + type: "" + sso: + dex: + openShiftOAuth: true + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + provider: dex + tls: + ca: {} diff --git a/tests/acm-naked.expected.yaml b/tests/acm-naked.expected.yaml index 561fbd7b..fa867edd 100644 --- a/tests/acm-naked.expected.yaml +++ b/tests/acm-naked.expected.yaml @@ -119,3 +119,158 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + apiVersion: argoproj.io/v1beta1 + kind: ArgoCD + metadata: + name: openshift-gitops + namespace: openshift-gitops + spec: + applicationSet: + resources: + limits: + cpu: "2" + memory: 1Gi + requests: + cpu: 250m + memory: 512Mi + webhookServer: + ingress: + enabled: false + route: + enabled: false + controller: + processors: {} + resources: + limits: + cpu: "2" + memory: 2Gi + requests: + cpu: 250m + memory: 1Gi + sharding: {} + grafana: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + route: + enabled: false + ha: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + initialSSHKnownHosts: {} + monitoring: + enabled: false + notifications: + enabled: false + prometheus: + enabled: false + ingress: + enabled: false + route: + enabled: false + rbac: + defaultPolicy: "" + policy: |- + g, system:cluster-admins, role:admin + g, cluster-admins, role:admin + scopes: '[groups]' + redis: + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + || true + image: registry.redhat.io/ubi9/ubi-minimal:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - emptyDir: {} + name: ca-bundles + resourceExclusions: |- + - apiGroups: + - tekton.dev + clusters: + - '*' + kinds: + - TaskRun + - PipelineRun + server: + autoscale: + enabled: false + grpc: + ingress: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 125m + memory: 128Mi + route: + enabled: true + service: + type: "" + sso: + dex: + openShiftOAuth: true + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + provider: dex + tls: + ca: {} diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 8e78a98f..356d0658 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -1330,3 +1330,158 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + apiVersion: argoproj.io/v1beta1 + kind: ArgoCD + metadata: + name: openshift-gitops + namespace: openshift-gitops + spec: + applicationSet: + resources: + limits: + cpu: "2" + memory: 1Gi + requests: + cpu: 250m + memory: 512Mi + webhookServer: + ingress: + enabled: false + route: + enabled: false + controller: + processors: {} + resources: + limits: + cpu: "2" + memory: 2Gi + requests: + cpu: 250m + memory: 1Gi + sharding: {} + grafana: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + route: + enabled: false + ha: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + initialSSHKnownHosts: {} + monitoring: + enabled: false + notifications: + enabled: false + prometheus: + enabled: false + ingress: + enabled: false + route: + enabled: false + rbac: + defaultPolicy: "" + policy: |- + g, system:cluster-admins, role:admin + g, cluster-admins, role:admin + scopes: '[groups]' + redis: + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + || true + image: registry.redhat.io/ubi9/ubi-minimal:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - emptyDir: {} + name: ca-bundles + resourceExclusions: |- + - apiGroups: + - tekton.dev + clusters: + - '*' + kinds: + - TaskRun + - PipelineRun + server: + autoscale: + enabled: false + grpc: + ingress: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 125m + memory: 128Mi + route: + enabled: true + service: + type: "" + sso: + dex: + openShiftOAuth: true + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + provider: dex + tls: + ca: {} diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index 4e18f8cb..2242f75d 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -417,6 +417,25 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -426,6 +445,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -477,6 +498,12 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -493,6 +520,15 @@ spec: - name: values-volume configMap: name: helm-values-configmap-factory + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/core/subscriptions.yaml @@ -673,6 +709,41 @@ spec: rbac: defaultPolicy: role:admin repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - emptyDir: {} + name: ca-bundles sidecarContainers: - name: helm-with-kustomize command: [/var/run/argocd/argocd-cmp-server] diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 1af3211d..5e64dc60 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -578,6 +578,25 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -587,6 +606,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -638,6 +659,12 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -654,6 +681,15 @@ spec: - name: values-volume configMap: name: helm-values-configmap-datacenter + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/imperative/unsealjob.yaml @@ -677,6 +713,25 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -686,6 +741,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -739,6 +796,12 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -755,6 +818,15 @@ spec: - name: values-volume configMap: name: helm-values-configmap-datacenter + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/core/subscriptions.yaml @@ -1403,6 +1475,41 @@ spec: rbac: defaultPolicy: role:admin repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - emptyDir: {} + name: ca-bundles sidecarContainers: - name: helm-with-kustomize command: [/var/run/argocd/argocd-cmp-server] diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 2d9a4d36..1ea53dc6 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -505,6 +505,25 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -514,6 +533,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -565,6 +586,12 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -581,6 +608,15 @@ spec: - name: values-volume configMap: name: helm-values-configmap-hub + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/imperative/unsealjob.yaml @@ -604,6 +640,25 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -613,6 +668,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -666,6 +723,12 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -682,6 +745,15 @@ spec: - name: values-volume configMap: name: helm-values-configmap-hub + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/core/subscriptions.yaml @@ -1588,6 +1660,41 @@ spec: rbac: defaultPolicy: role:admin repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - emptyDir: {} + name: ca-bundles resources: limits: cpu: "1" diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index a7fee415..bd89773a 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -270,6 +270,25 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -279,6 +298,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -332,6 +353,12 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -348,6 +375,15 @@ spec: - name: values-volume configMap: name: helm-values-configmap-example + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/plumbing/argocd.yaml @@ -419,6 +455,41 @@ spec: rbac: defaultPolicy: role:admin repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - emptyDir: {} + name: ca-bundles resources: limits: cpu: "1" diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index bc04b88e..13daced6 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -486,6 +486,25 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -495,6 +514,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -546,6 +567,12 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -562,6 +589,15 @@ spec: - name: values-volume configMap: name: helm-values-configmap-example + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/imperative/unsealjob.yaml @@ -585,6 +621,25 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -594,6 +649,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -647,6 +704,12 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -663,6 +726,15 @@ spec: - name: values-volume configMap: name: helm-values-configmap-example + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/core/operatorgroup.yaml @@ -1152,6 +1224,41 @@ spec: rbac: defaultPolicy: role:admin repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - emptyDir: {} + name: ca-bundles resources: limits: cpu: "1" From b489135f33510dc1c489e246c8c9248151a57d52 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 7 Jun 2024 11:14:41 +0200 Subject: [PATCH 41/77] Release clustergroup v0.8.7 --- clustergroup/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustergroup/Chart.yaml b/clustergroup/Chart.yaml index 2ddd15ba..222a2482 100644 --- a/clustergroup/Chart.yaml +++ b/clustergroup/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to create per-clustergroup ArgoCD applications and any keywords: - pattern name: clustergroup -version: 0.8.6 +version: 0.8.7 From d846593fe8bd2a4be8537c93d5784afc818a27b5 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Fri, 7 Jun 2024 14:48:36 +0200 Subject: [PATCH 42/77] Upgrade ESO to v0.9.19 --- golang-external-secrets/Chart.yaml | 2 +- .../charts/external-secrets-0.9.18.tgz | Bin 76336 -> 0 bytes .../charts/external-secrets-0.9.19.tgz | Bin 0 -> 76457 bytes golang-external-secrets/values.yaml | 6 +- ...rets-industrial-edge-factory.expected.yaml | 100 ++++++++++-------- ...-secrets-industrial-edge-hub.expected.yaml | 100 ++++++++++-------- ...ecrets-medical-diagnosis-hub.expected.yaml | 100 ++++++++++-------- ...olang-external-secrets-naked.expected.yaml | 100 ++++++++++-------- ...lang-external-secrets-normal.expected.yaml | 100 ++++++++++-------- 9 files changed, 279 insertions(+), 229 deletions(-) delete mode 100644 golang-external-secrets/charts/external-secrets-0.9.18.tgz create mode 100644 golang-external-secrets/charts/external-secrets-0.9.19.tgz diff --git a/golang-external-secrets/Chart.yaml b/golang-external-secrets/Chart.yaml index 4aef19aa..afffe393 100644 --- a/golang-external-secrets/Chart.yaml +++ b/golang-external-secrets/Chart.yaml @@ -6,6 +6,6 @@ name: golang-external-secrets version: 0.0.3 dependencies: - name: external-secrets - version: "0.9.18" + version: "0.9.19" repository: "https://charts.external-secrets.io" #"https://external-secrets.github.io/kubernetes-external-secrets" diff --git a/golang-external-secrets/charts/external-secrets-0.9.18.tgz b/golang-external-secrets/charts/external-secrets-0.9.18.tgz deleted file mode 100644 index 7aa6d4505f93b7754cdc2f6c712ff8724153f85c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76336 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
q0j)i=a#pu1jU+b_58*02a$>ktMv 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 diff --git a/golang-external-secrets/charts/external-secrets-0.9.19.tgz b/golang-external-secrets/charts/external-secrets-0.9.19.tgz new file mode 100644 index 0000000000000000000000000000000000000000..66fffaa0b08d686867fc9e4307204eaae1e22964 GIT binary patch literal 76457 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

-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 Date: Fri, 7 Jun 2024 19:49:02 +0200 Subject: [PATCH 43/77] Update helm version in CI to 3.14.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's the version gitops 1.12 is using these days: ❯ oc exec -it -n openshift-gitops openshift-gitops-repo-server-66bf746964-926qk -c argocd-repo-server -- bash -c "helm version" version.BuildInfo{Version:"v3.14.0", GitCommit:"2a2fb3b98829f1e0be6fb18af2f6599e0f4e8243", GitTreeState:"", GoVersion:"go1.21.9 (Red Hat 1.21.9-1.module+el8.10.0+21671+b35c3b78)"} --- .github/workflows/linter.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index 39843f26..f82194ee 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -36,7 +36,7 @@ jobs: - name: Setup helm uses: azure/setup-helm@v4 with: - version: 'v3.13.2' + version: 'v3.14.0' ################################ From 429f55cea86954bbe92c4f36094751847d8930ee Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 10 Jun 2024 10:37:05 +0200 Subject: [PATCH 44/77] Drop imperative.initcontainers.gitinit Now that we switched to imperative.initcontainers.gitinit-ca, the older define is not used anywhere, so we can drop this. --- .../templates/imperative/_helpers.tpl | 42 ------------------- 1 file changed, 42 deletions(-) diff --git a/clustergroup/templates/imperative/_helpers.tpl b/clustergroup/templates/imperative/_helpers.tpl index d55220e4..18735dec 100644 --- a/clustergroup/templates/imperative/_helpers.tpl +++ b/clustergroup/templates/imperative/_helpers.tpl @@ -27,48 +27,6 @@ name: ca-bundles {{- end }} -{{/* git-init InitContainer */}} -{{- define "imperative.initcontainers.gitinit" }} -- name: git-init - image: {{ $.Values.clusterGroup.imperative.image }} - imagePullPolicy: {{ $.Values.clusterGroup.imperative.imagePullPolicy }} - env: - - name: HOME - value: /git/home - volumeMounts: - - name: git - mountPath: "/git" - command: - - 'sh' - - '-c' - - >- - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials &> /dev/null; then - URL="{{ $.Values.global.repoURL }}"; - else - if ! oc get secrets -n openshift-gitops vp-private-repo-credentials -o go-template='{{ `{{index .data.sshPrivateKey | base64decode}}` }}' &>/dev/null; then - U="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{ `{{index .data.username | base64decode }}` }}')"; - P="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{ `{{index .data.password | base64decode }}` }}')"; - URL=$(echo {{ $.Values.global.repoURL }} | sed -E "s/(https?:\/\/)/\1${U}:${P}@/"); - else - S="$(oc get secret -n openshift-gitops vp-private-repo-credentials -o go-template='{{ `{{index .data.sshPrivateKey | base64decode }}` }}')"; - mkdir -p --mode 0700 "${HOME}/.ssh"; - echo "${S}" > "${HOME}/.ssh/id_rsa"; - chmod 0600 "${HOME}/.ssh/id_rsa"; - URL=$(echo {{ $.Values.global.repoURL }} | sed -E "s/(https?:\/\/)/\1git@/"); - git config --global core.sshCommand "ssh -i "${HOME}/.ssh/id_rsa" -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no"; - fi; - fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export HTTP_PROXY="${OUT}"; fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.httpsProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; - OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; - if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; - mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch {{ $.Values.global.targetRevision }} --depth 1 -- "${URL}" /git/repo; - chmod 0770 /git/{repo,home}; -{{- end }} - {{/* git-init-ca InitContainer */}} {{- define "imperative.initcontainers.gitinit-ca" }} - name: git-init From e967b159b31dc839d894088c1b67893c1408ed57 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 10 Jun 2024 10:41:26 +0200 Subject: [PATCH 45/77] Have unseal work whenever we specifiy HEAD Otherwise if HEAD is specified we get the following: mkdir: cannot create directory '/git/home': File exists Cloning into '/git/repo'... warning: Could not find remote branch HEAD to clone. fatal: Remote branch HEAD not found in upstream origin --- clustergroup/templates/imperative/_helpers.tpl | 3 ++- tests/clustergroup-industrial-edge-factory.expected.yaml | 3 ++- tests/clustergroup-industrial-edge-hub.expected.yaml | 6 ++++-- tests/clustergroup-medical-diagnosis-hub.expected.yaml | 6 ++++-- tests/clustergroup-naked.expected.yaml | 3 ++- tests/clustergroup-normal.expected.yaml | 6 ++++-- 6 files changed, 18 insertions(+), 9 deletions(-) diff --git a/clustergroup/templates/imperative/_helpers.tpl b/clustergroup/templates/imperative/_helpers.tpl index 18735dec..c7f986e4 100644 --- a/clustergroup/templates/imperative/_helpers.tpl +++ b/clustergroup/templates/imperative/_helpers.tpl @@ -66,8 +66,9 @@ if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "{{ $.Values.global.targetRevision }}" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch {{ $.Values.global.targetRevision }}"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch {{ $.Values.global.targetRevision }} --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; {{- end }} {{/* Final done container */}} diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index 2242f75d..ccd2a52c 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -473,8 +473,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 5e64dc60..2486927b 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -634,8 +634,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -769,8 +770,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 1ea53dc6..908f526f 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -561,8 +561,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -696,8 +697,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index bd89773a..4a417d5d 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -326,8 +326,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index 13daced6..efb98493 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -542,8 +542,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -677,8 +678,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest From 85c3a9bec46378570b2e1df8aaa0c073151980af Mon Sep 17 00:00:00 2001 From: Trevor Royer Date: Wed, 5 Jun 2024 15:09:06 -0600 Subject: [PATCH 46/77] make resourceExclusion configurable --- clustergroup/templates/plumbing/argocd.yaml | 9 +++------ clustergroup/values.schema.json | 4 ++++ clustergroup/values.yaml | 6 ++++++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/clustergroup/templates/plumbing/argocd.yaml b/clustergroup/templates/plumbing/argocd.yaml index 7d42ec36..68b692ff 100644 --- a/clustergroup/templates/plumbing/argocd.yaml +++ b/clustergroup/templates/plumbing/argocd.yaml @@ -150,12 +150,9 @@ spec: requests: cpu: 250m memory: 256Mi - resourceExclusions: | - - apiGroups: - - tekton.dev - kinds: - - TaskRun - - PipelineRun +{{- if $.Values.clusterGroup.argoCD.resourceExclusions }} + resourceExclusions: {{- $.Values.clusterGroup.argoCD.resourceExclusions | toYaml | indent 2 }} +{{- end }} {{- if .Values.global.excludeESO }} - apiGroups: - external-secrets.io diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index 2955bf1a..e0331497 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -548,6 +548,10 @@ "initContainers": { "type": "array", "description": "A list of initContainers to add to the repo-server if needed" + }, + "resourceExclusions": { + "type": "string", + "description": "ResourceExclusions is used to completely ignore entire classes of resource group/kinds." } } }, diff --git a/clustergroup/values.yaml b/clustergroup/values.yaml index bb149567..94a01af9 100644 --- a/clustergroup/values.yaml +++ b/clustergroup/values.yaml @@ -28,6 +28,12 @@ clusterGroup: argoCD: initContainers: [] configManagementPlugins: [] + resourceExclusions: | + - apiGroups: + - tekton.dev + kinds: + - TaskRun + - PipelineRun imperative: jobs: [] From 05a876bf60fa5787cec1480394ce875dff3a5207 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 10 Jun 2024 16:57:23 +0200 Subject: [PATCH 47/77] Update tests after upgrading resourceExclusions tweak --- tests/clustergroup-industrial-edge-factory.expected.yaml | 8 +++++++- tests/clustergroup-industrial-edge-hub.expected.yaml | 8 +++++++- tests/clustergroup-medical-diagnosis-hub.expected.yaml | 8 +++++++- tests/clustergroup-naked.expected.yaml | 8 +++++++- tests/clustergroup-normal.expected.yaml | 8 +++++++- 5 files changed, 35 insertions(+), 5 deletions(-) diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index ccd2a52c..d651d450 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -121,6 +121,12 @@ data: --set clusterGroup.name=factory --post-renderer ./kustomize"] initContainers: [] + resourceExclusions: | + - apiGroups: + - tekton.dev + kinds: + - TaskRun + - PipelineRun imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role @@ -778,7 +784,7 @@ spec: requests: cpu: 250m memory: 256Mi - resourceExclusions: | + resourceExclusions: | - apiGroups: - tekton.dev kinds: diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 2486927b..eec93391 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -242,6 +242,12 @@ data: --set clusterGroup.name=datacenter --post-renderer ./kustomize"] initContainers: [] + resourceExclusions: | + - apiGroups: + - tekton.dev + kinds: + - TaskRun + - PipelineRun imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role @@ -1545,7 +1551,7 @@ spec: requests: cpu: 250m memory: 256Mi - resourceExclusions: | + resourceExclusions: | - apiGroups: - tekton.dev kinds: diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 908f526f..17e26914 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -225,6 +225,12 @@ data: argoCD: configManagementPlugins: [] initContainers: [] + resourceExclusions: | + - apiGroups: + - tekton.dev + kinds: + - TaskRun + - PipelineRun imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role @@ -1704,7 +1710,7 @@ spec: requests: cpu: 250m memory: 256Mi - resourceExclusions: | + resourceExclusions: | - apiGroups: - tekton.dev kinds: diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index 4a417d5d..3c8294d1 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -48,6 +48,12 @@ data: argoCD: configManagementPlugins: [] initContainers: [] + resourceExclusions: | + - apiGroups: + - tekton.dev + kinds: + - TaskRun + - PipelineRun imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role @@ -498,7 +504,7 @@ spec: requests: cpu: 250m memory: 256Mi - resourceExclusions: | + resourceExclusions: | - apiGroups: - tekton.dev kinds: diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index efb98493..4cb54949 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -133,6 +133,12 @@ data: argoCD: configManagementPlugins: [] initContainers: [] + resourceExclusions: | + - apiGroups: + - tekton.dev + kinds: + - TaskRun + - PipelineRun imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role @@ -1268,7 +1274,7 @@ spec: requests: cpu: 250m memory: 256Mi - resourceExclusions: | + resourceExclusions: | - apiGroups: - tekton.dev kinds: From e97b2e7313c4161e382ecbae8ef4bc1e093de000 Mon Sep 17 00:00:00 2001 From: Trevor Royer Date: Wed, 5 Jun 2024 14:42:50 -0600 Subject: [PATCH 48/77] Make resourcehealthchecks configurable --- clustergroup/values.schema.json | 22 ++++++++++++++++++++++ clustergroup/values.yaml | 20 ++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index e0331497..b05dcb03 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -552,6 +552,13 @@ "resourceExclusions": { "type": "string", "description": "ResourceExclusions is used to completely ignore entire classes of resource group/kinds." + }, + "resourceHealthChecks": { + "type": "array", + "items": { + "$ref": "#/definitions/ArgoCDResourceHealthChecks" + }, + "description": "ResourceHealthChecks customizes resource health check behavior." } } }, @@ -585,6 +592,21 @@ "image" ] }, + "ArgoCDResourceHealthChecks": { + "type": "object", + "additionalProperties": false, + "properties": { + "check": { + "type": "string" + }, + "group": { + "type": "string" + }, + "kind": { + "type": "string" + } + } + }, "IndexImages": { "type": "object", "description": "Details for overriding default catalog sources", diff --git a/clustergroup/values.yaml b/clustergroup/values.yaml index 94a01af9..cdbf823e 100644 --- a/clustergroup/values.yaml +++ b/clustergroup/values.yaml @@ -28,6 +28,26 @@ clusterGroup: argoCD: initContainers: [] configManagementPlugins: [] + resourceHealthChecks: + - kind: PersistentVolumeClaim + check: | + hs = {} + if obj.status ~= nil then + if obj.status.phase ~= nil then + if obj.status.phase == "Pending" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + elseif obj.status.phase == "Bound" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + end + end + end + hs.status = "Progressing" + hs.message = "Waiting for PVC" + return hs resourceExclusions: | - apiGroups: - tekton.dev From 8d1aaab0a77c9a2c4226b46f8160409ad34fa033 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 10 Jun 2024 17:23:39 +0200 Subject: [PATCH 49/77] Update tests after upgrading resourceHealthChecks change --- ...roup-industrial-edge-factory.expected.yaml | 20 +++++++++++++++++++ ...tergroup-industrial-edge-hub.expected.yaml | 20 +++++++++++++++++++ ...rgroup-medical-diagnosis-hub.expected.yaml | 20 +++++++++++++++++++ tests/clustergroup-naked.expected.yaml | 20 +++++++++++++++++++ tests/clustergroup-normal.expected.yaml | 20 +++++++++++++++++++ 5 files changed, 100 insertions(+) diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index d651d450..96cf061c 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -127,6 +127,26 @@ data: kinds: - TaskRun - PipelineRun + resourceHealthChecks: + - check: | + hs = {} + if obj.status ~= nil then + if obj.status.phase ~= nil then + if obj.status.phase == "Pending" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + elseif obj.status.phase == "Bound" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + end + end + end + hs.status = "Progressing" + hs.message = "Waiting for PVC" + return hs + kind: PersistentVolumeClaim imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index eec93391..eaf5b736 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -248,6 +248,26 @@ data: kinds: - TaskRun - PipelineRun + resourceHealthChecks: + - check: | + hs = {} + if obj.status ~= nil then + if obj.status.phase ~= nil then + if obj.status.phase == "Pending" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + elseif obj.status.phase == "Bound" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + end + end + end + hs.status = "Progressing" + hs.message = "Waiting for PVC" + return hs + kind: PersistentVolumeClaim imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 17e26914..e834bd9e 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -231,6 +231,26 @@ data: kinds: - TaskRun - PipelineRun + resourceHealthChecks: + - check: | + hs = {} + if obj.status ~= nil then + if obj.status.phase ~= nil then + if obj.status.phase == "Pending" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + elseif obj.status.phase == "Bound" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + end + end + end + hs.status = "Progressing" + hs.message = "Waiting for PVC" + return hs + kind: PersistentVolumeClaim imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index 3c8294d1..04724078 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -54,6 +54,26 @@ data: kinds: - TaskRun - PipelineRun + resourceHealthChecks: + - check: | + hs = {} + if obj.status ~= nil then + if obj.status.phase ~= nil then + if obj.status.phase == "Pending" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + elseif obj.status.phase == "Bound" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + end + end + end + hs.status = "Progressing" + hs.message = "Waiting for PVC" + return hs + kind: PersistentVolumeClaim imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index 4cb54949..c28834d5 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -139,6 +139,26 @@ data: kinds: - TaskRun - PipelineRun + resourceHealthChecks: + - check: | + hs = {} + if obj.status ~= nil then + if obj.status.phase ~= nil then + if obj.status.phase == "Pending" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + elseif obj.status.phase == "Bound" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + end + end + end + hs.status = "Progressing" + hs.message = "Waiting for PVC" + return hs + kind: PersistentVolumeClaim imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role From 32194d1ad4c3cce0f4d7c8ce3c8877a30b83914a Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 10 Jun 2024 18:10:27 +0200 Subject: [PATCH 50/77] Do not quote $BRANCH variable Otherwise we might error out with: error: unknown option `branch qe_test-16831' usage: git clone [] [--] [

] --- clustergroup/templates/imperative/_helpers.tpl | 2 +- tests/clustergroup-industrial-edge-factory.expected.yaml | 2 +- tests/clustergroup-industrial-edge-hub.expected.yaml | 4 ++-- tests/clustergroup-medical-diagnosis-hub.expected.yaml | 4 ++-- tests/clustergroup-naked.expected.yaml | 2 +- tests/clustergroup-normal.expected.yaml | 4 ++-- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/clustergroup/templates/imperative/_helpers.tpl b/clustergroup/templates/imperative/_helpers.tpl index c7f986e4..93299f91 100644 --- a/clustergroup/templates/imperative/_helpers.tpl +++ b/clustergroup/templates/imperative/_helpers.tpl @@ -68,7 +68,7 @@ if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; if [ "{{ $.Values.global.targetRevision }}" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch {{ $.Values.global.targetRevision }}"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; {{- end }} {{/* Final done container */}} diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index 96cf061c..e795d287 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -501,7 +501,7 @@ spec: if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index eaf5b736..8c05e007 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -662,7 +662,7 @@ spec: if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -798,7 +798,7 @@ spec: if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index e834bd9e..a299e7dc 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -589,7 +589,7 @@ spec: if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -725,7 +725,7 @@ spec: if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index 04724078..ef518557 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -354,7 +354,7 @@ spec: if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index c28834d5..c046404b 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -570,7 +570,7 @@ spec: if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -706,7 +706,7 @@ spec: if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch "${BRANCH}" --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest From 97b2afa01bffe16bf70142165b1a8e2b3ac0e1d6 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 10 Jun 2024 18:40:38 +0200 Subject: [PATCH 51/77] Fix initcontainer race on spokes initContainers on the clusterwide argo instances on spokes rely on a configmap called "trusted-ca-bundle" that gets created by ACM in the openshift-gitops namespace. Since we have no explicit guarantees about ordering, it might happen that the argocd object gets created by acm before the configmap. This is problematic because the init container will start but just ignore the missing configmap. Solve this by splitting the ocp-gitops-policy in two and making sure that both the openshift-gitops subscription and the trusted-ca-bundle configmap are green before applying the next dependency. --- acm/templates/policies/ocp-gitops-policy.yaml | 99 ++++++++++++++++--- .../acm-industrial-edge-factory.expected.yaml | 94 ++++++++++++++++-- tests/acm-industrial-edge-hub.expected.yaml | 94 ++++++++++++++++-- tests/acm-medical-diagnosis-hub.expected.yaml | 94 ++++++++++++++++-- tests/acm-naked.expected.yaml | 94 ++++++++++++++++-- tests/acm-normal.expected.yaml | 94 ++++++++++++++++-- 6 files changed, 511 insertions(+), 58 deletions(-) diff --git a/acm/templates/policies/ocp-gitops-policy.yaml b/acm/templates/policies/ocp-gitops-policy.yaml index 29204254..9210b47f 100644 --- a/acm/templates/policies/ocp-gitops-policy.yaml +++ b/acm/templates/policies/ocp-gitops-policy.yaml @@ -24,15 +24,6 @@ spec: include: - default object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT @@ -53,6 +44,88 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: openshift-gitops-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: openshift-gitops-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: openshift-gitops-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: openshift-gitops-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: vendor + operator: In + values: + - OpenShift + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# This policy depends on openshift-gitops-policy and the reason is that we need to be +# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance +# because the initcontainer references the trusted-ca-bundle and if it starts without the +# configmap being there we risk running an argo instances that won't trust public CAs +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: openshift-gitops-policy-argocd + annotations: + policy.open-cluster-management.io/standards: NIST-CSF + policy.open-cluster-management.io/categories: PR.DS Data Security + policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + dependencies: + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: openshift-gitops-policy + namespace: open-cluster-management + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: openshift-gitops-config-argocd + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: - complianceType: mustonlyhave objectDefinition: apiVersion: argoproj.io/v1beta1 @@ -217,22 +290,22 @@ spec: apiVersion: policy.open-cluster-management.io/v1 kind: PlacementBinding metadata: - name: openshift-gitops-placement-binding + name: openshift-gitops-placement-binding-argocd annotations: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true placementRef: - name: openshift-gitops-placement + name: openshift-gitops-placement-argocd kind: PlacementRule apiGroup: apps.open-cluster-management.io subjects: - - name: openshift-gitops-policy + - name: openshift-gitops-policy-argocd kind: Policy apiGroup: policy.open-cluster-management.io --- apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule metadata: - name: openshift-gitops-placement + name: openshift-gitops-placement-argocd annotations: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true spec: diff --git a/tests/acm-industrial-edge-factory.expected.yaml b/tests/acm-industrial-edge-factory.expected.yaml index fa867edd..980d0220 100644 --- a/tests/acm-industrial-edge-factory.expected.yaml +++ b/tests/acm-industrial-edge-factory.expected.yaml @@ -42,6 +42,22 @@ subjects: apiGroup: policy.open-cluster-management.io --- # Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: openshift-gitops-placement-binding-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: openshift-gitops-placement-argocd + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: openshift-gitops-policy-argocd + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule metadata: @@ -64,6 +80,28 @@ spec: - 'true' --- # Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: openshift-gitops-placement-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: vendor + operator: In + values: + - OpenShift + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml apiVersion: policy.open-cluster-management.io/v1 kind: Policy metadata: @@ -90,15 +128,6 @@ spec: include: - default object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT @@ -119,6 +148,53 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +# This policy depends on openshift-gitops-policy and the reason is that we need to be +# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance +# because the initcontainer references the trusted-ca-bundle and if it starts without the +# configmap being there we risk running an argo instances that won't trust public CAs +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: openshift-gitops-policy-argocd + annotations: + policy.open-cluster-management.io/standards: NIST-CSF + policy.open-cluster-management.io/categories: PR.DS Data Security + policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + dependencies: + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: openshift-gitops-policy + namespace: open-cluster-management + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: openshift-gitops-config-argocd + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: - complianceType: mustonlyhave objectDefinition: apiVersion: argoproj.io/v1beta1 diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml index d715989d..7e3bd0f3 100644 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ b/tests/acm-industrial-edge-hub.expected.yaml @@ -70,6 +70,22 @@ subjects: kind: Policy apiGroup: policy.open-cluster-management.io --- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: openshift-gitops-placement-binding-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: openshift-gitops-placement-argocd + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: openshift-gitops-policy-argocd + kind: Policy + apiGroup: policy.open-cluster-management.io +--- # Source: acm/templates/policies/acm-hub-ca-policy.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule @@ -136,6 +152,28 @@ spec: values: - 'true' --- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: openshift-gitops-placement-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: vendor + operator: In + values: + - OpenShift + - key: local-cluster + operator: NotIn + values: + - 'true' +--- # Source: acm/templates/policies/acm-hub-ca-policy.yaml apiVersion: policy.open-cluster-management.io/v1 kind: Policy @@ -298,15 +336,6 @@ spec: include: - default object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT @@ -327,6 +356,53 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +# This policy depends on openshift-gitops-policy and the reason is that we need to be +# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance +# because the initcontainer references the trusted-ca-bundle and if it starts without the +# configmap being there we risk running an argo instances that won't trust public CAs +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: openshift-gitops-policy-argocd + annotations: + policy.open-cluster-management.io/standards: NIST-CSF + policy.open-cluster-management.io/categories: PR.DS Data Security + policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + dependencies: + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: openshift-gitops-policy + namespace: open-cluster-management + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: openshift-gitops-config-argocd + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: - complianceType: mustonlyhave objectDefinition: apiVersion: argoproj.io/v1beta1 diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml index 2fd25e75..e63e0654 100644 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ b/tests/acm-medical-diagnosis-hub.expected.yaml @@ -70,6 +70,22 @@ subjects: kind: Policy apiGroup: policy.open-cluster-management.io --- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: openshift-gitops-placement-binding-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: openshift-gitops-placement-argocd + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: openshift-gitops-policy-argocd + kind: Policy + apiGroup: policy.open-cluster-management.io +--- # Source: acm/templates/policies/acm-hub-ca-policy.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule @@ -127,6 +143,28 @@ spec: values: - 'true' --- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: openshift-gitops-placement-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: vendor + operator: In + values: + - OpenShift + - key: local-cluster + operator: NotIn + values: + - 'true' +--- # Source: acm/templates/policies/acm-hub-ca-policy.yaml apiVersion: policy.open-cluster-management.io/v1 kind: Policy @@ -289,15 +327,6 @@ spec: include: - default object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT @@ -318,6 +347,53 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +# This policy depends on openshift-gitops-policy and the reason is that we need to be +# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance +# because the initcontainer references the trusted-ca-bundle and if it starts without the +# configmap being there we risk running an argo instances that won't trust public CAs +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: openshift-gitops-policy-argocd + annotations: + policy.open-cluster-management.io/standards: NIST-CSF + policy.open-cluster-management.io/categories: PR.DS Data Security + policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + dependencies: + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: openshift-gitops-policy + namespace: open-cluster-management + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: openshift-gitops-config-argocd + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: - complianceType: mustonlyhave objectDefinition: apiVersion: argoproj.io/v1beta1 diff --git a/tests/acm-naked.expected.yaml b/tests/acm-naked.expected.yaml index fa867edd..980d0220 100644 --- a/tests/acm-naked.expected.yaml +++ b/tests/acm-naked.expected.yaml @@ -42,6 +42,22 @@ subjects: apiGroup: policy.open-cluster-management.io --- # Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: openshift-gitops-placement-binding-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: openshift-gitops-placement-argocd + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: openshift-gitops-policy-argocd + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule metadata: @@ -64,6 +80,28 @@ spec: - 'true' --- # Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: openshift-gitops-placement-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: vendor + operator: In + values: + - OpenShift + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml apiVersion: policy.open-cluster-management.io/v1 kind: Policy metadata: @@ -90,15 +128,6 @@ spec: include: - default object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT @@ -119,6 +148,53 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +# This policy depends on openshift-gitops-policy and the reason is that we need to be +# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance +# because the initcontainer references the trusted-ca-bundle and if it starts without the +# configmap being there we risk running an argo instances that won't trust public CAs +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: openshift-gitops-policy-argocd + annotations: + policy.open-cluster-management.io/standards: NIST-CSF + policy.open-cluster-management.io/categories: PR.DS Data Security + policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + dependencies: + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: openshift-gitops-policy + namespace: open-cluster-management + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: openshift-gitops-config-argocd + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: - complianceType: mustonlyhave objectDefinition: apiVersion: argoproj.io/v1beta1 diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 356d0658..f3ca998a 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -860,6 +860,22 @@ subjects: kind: Policy apiGroup: policy.open-cluster-management.io --- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: openshift-gitops-placement-binding-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: openshift-gitops-placement-argocd + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: openshift-gitops-policy-argocd + kind: Policy + apiGroup: policy.open-cluster-management.io +--- # Source: acm/templates/policies/acm-hub-ca-policy.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule @@ -945,6 +961,28 @@ spec: values: - 'true' --- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: openshift-gitops-placement-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: vendor + operator: In + values: + - OpenShift + - key: local-cluster + operator: NotIn + values: + - 'true' +--- # Source: acm/templates/policies/acm-hub-ca-policy.yaml apiVersion: policy.open-cluster-management.io/v1 kind: Policy @@ -1301,15 +1339,6 @@ spec: include: - default object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT @@ -1330,6 +1359,53 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +# This policy depends on openshift-gitops-policy and the reason is that we need to be +# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance +# because the initcontainer references the trusted-ca-bundle and if it starts without the +# configmap being there we risk running an argo instances that won't trust public CAs +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: openshift-gitops-policy-argocd + annotations: + policy.open-cluster-management.io/standards: NIST-CSF + policy.open-cluster-management.io/categories: PR.DS Data Security + policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + dependencies: + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: openshift-gitops-policy + namespace: open-cluster-management + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: openshift-gitops-config-argocd + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: - complianceType: mustonlyhave objectDefinition: apiVersion: argoproj.io/v1beta1 From ffa35ef5be91d5542e1a468b24f40de6325267b0 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 10 Jun 2024 20:50:30 +0200 Subject: [PATCH 52/77] Release clustergroup v0.8.8 --- clustergroup/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustergroup/Chart.yaml b/clustergroup/Chart.yaml index 222a2482..5b774788 100644 --- a/clustergroup/Chart.yaml +++ b/clustergroup/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to create per-clustergroup ArgoCD applications and any keywords: - pattern name: clustergroup -version: 0.8.7 +version: 0.8.8 From e47dd3f883dac404f56721cd703784f0c61b4b46 Mon Sep 17 00:00:00 2001 From: Trevor Royer Date: Tue, 11 Jun 2024 09:57:54 +0200 Subject: [PATCH 53/77] configure annotation based resource tracking --- clustergroup/templates/plumbing/argocd.yaml | 1 + clustergroup/values.schema.json | 9 +++++++++ clustergroup/values.yaml | 2 ++ tests/clustergroup-industrial-edge-factory.expected.yaml | 2 ++ tests/clustergroup-industrial-edge-hub.expected.yaml | 2 ++ tests/clustergroup-medical-diagnosis-hub.expected.yaml | 2 ++ tests/clustergroup-naked.expected.yaml | 2 ++ tests/clustergroup-normal.expected.yaml | 2 ++ 8 files changed, 22 insertions(+) diff --git a/clustergroup/templates/plumbing/argocd.yaml b/clustergroup/templates/plumbing/argocd.yaml index 68b692ff..ee1b7c2d 100644 --- a/clustergroup/templates/plumbing/argocd.yaml +++ b/clustergroup/templates/plumbing/argocd.yaml @@ -36,6 +36,7 @@ spec: hs.message = "Waiting for PVC" return hs + resourceTrackingMethod: {{ $.Values.clusterGroup.argoCD.resourceTrackingMethod}} applicationInstanceLabelKey: argocd.argoproj.io/instance applicationSet: resources: diff --git a/clustergroup/values.schema.json b/clustergroup/values.schema.json index b05dcb03..a1449ff3 100644 --- a/clustergroup/values.schema.json +++ b/clustergroup/values.schema.json @@ -549,6 +549,15 @@ "type": "array", "description": "A list of initContainers to add to the repo-server if needed" }, + "resourceTrackingMethod": { + "type": "string", + "description": "ResourceTrackingMethod defines how Argo CD should track resources that it manages", + "enum": [ + "annotation", + "label", + "annotation+label" + ] + }, "resourceExclusions": { "type": "string", "description": "ResourceExclusions is used to completely ignore entire classes of resource group/kinds." diff --git a/clustergroup/values.yaml b/clustergroup/values.yaml index cdbf823e..f02175f9 100644 --- a/clustergroup/values.yaml +++ b/clustergroup/values.yaml @@ -28,6 +28,8 @@ clusterGroup: argoCD: initContainers: [] configManagementPlugins: [] + # resource tracking can be set to annotation, label, or annotation+label + resourceTrackingMethod: label resourceHealthChecks: - kind: PersistentVolumeClaim check: | diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index e795d287..ad6cfa3c 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -147,6 +147,7 @@ data: hs.message = "Waiting for PVC" return hs kind: PersistentVolumeClaim + resourceTrackingMethod: label imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role @@ -703,6 +704,7 @@ spec: hs.message = "Waiting for PVC" return hs + resourceTrackingMethod: label applicationInstanceLabelKey: argocd.argoproj.io/instance applicationSet: resources: diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 8c05e007..cc30a7ac 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -268,6 +268,7 @@ data: hs.message = "Waiting for PVC" return hs kind: PersistentVolumeClaim + resourceTrackingMethod: label imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role @@ -1470,6 +1471,7 @@ spec: hs.message = "Waiting for PVC" return hs + resourceTrackingMethod: label applicationInstanceLabelKey: argocd.argoproj.io/instance applicationSet: resources: diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index a299e7dc..1888528f 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -251,6 +251,7 @@ data: hs.message = "Waiting for PVC" return hs kind: PersistentVolumeClaim + resourceTrackingMethod: label imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role @@ -1655,6 +1656,7 @@ spec: hs.message = "Waiting for PVC" return hs + resourceTrackingMethod: label applicationInstanceLabelKey: argocd.argoproj.io/instance applicationSet: resources: diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index ef518557..56452cca 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -74,6 +74,7 @@ data: hs.message = "Waiting for PVC" return hs kind: PersistentVolumeClaim + resourceTrackingMethod: label imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role @@ -449,6 +450,7 @@ spec: hs.message = "Waiting for PVC" return hs + resourceTrackingMethod: label applicationInstanceLabelKey: argocd.argoproj.io/instance applicationSet: resources: diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index c046404b..ba0e704d 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -159,6 +159,7 @@ data: hs.message = "Waiting for PVC" return hs kind: PersistentVolumeClaim + resourceTrackingMethod: label imperative: activeDeadlineSeconds: 3600 adminClusterRoleName: imperative-admin-cluster-role @@ -1219,6 +1220,7 @@ spec: hs.message = "Waiting for PVC" return hs + resourceTrackingMethod: label applicationInstanceLabelKey: argocd.argoproj.io/instance applicationSet: resources: From 5b52f0daaf9cf4a7ef392b1d32394febce6df1ea Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 15 Jun 2024 14:24:48 +0200 Subject: [PATCH 54/77] Drop imperative.volumes and imperative.volumemounts With the switch to initcontainers they are not used anywhere anymore --- clustergroup/templates/imperative/_helpers.tpl | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/clustergroup/templates/imperative/_helpers.tpl b/clustergroup/templates/imperative/_helpers.tpl index 93299f91..f1d99416 100644 --- a/clustergroup/templates/imperative/_helpers.tpl +++ b/clustergroup/templates/imperative/_helpers.tpl @@ -98,22 +98,6 @@ - mountPath: /tmp/ca-bundles name: ca-bundles {{- end }} -{{- define "imperative.volumemounts" }} -- name: git - mountPath: "/git" -- name: values-volume - mountPath: /values/values.yaml - subPath: values.yaml -{{- end }} - -{{/* volumes for all containers */}} -{{- define "imperative.volumes" }} -- name: git - emptyDir: {} -- name: values-volume - configMap: - name: {{ $.Values.clusterGroup.imperative.valuesConfigMap }}-{{ $.Values.clusterGroup.name }} -{{- end }} {{- define "imperative.volumes_ca" }} - name: git From 28b2d3965ee10a31bc1ca03539ffd0d04f1a8cc9 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 18 Jun 2024 10:00:46 +0200 Subject: [PATCH 55/77] Properly quote vault kv command When using a password with a dollar, the oc exec commands run inside the vault are not properly escaped, casing the dollar signed to be interpreted by the shell inside the vault pod. So a password like 'Y$yxn54&qXAxpUd2*yGH' will become 'Y&qXAxpUd2*yGH' in the vault. This is because the command that is being run ends up being: oc exec -n vault vault-0 -i -- sh -c "vault kv patch -mount=secret global/mysecret dollar=Y$yxn54&qXAxpUd2*yGH" The `$yxn54` will be interpreted by the shell inside vault. Let's fix this by running a properly escaped command: oc exec -n vault vault-0 -i -- sh -c "vault kv patch -mount=secret global/mysecret dollar='"'Y$yxn54&qXAxpUd2*yGH'"'" Reported-By: Chris Butler --- ansible/plugins/modules/vault_load_parsed_secrets.py | 2 +- ansible/tests/unit/test_vault_load_parsed_secrets.py | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ansible/plugins/modules/vault_load_parsed_secrets.py b/ansible/plugins/modules/vault_load_parsed_secrets.py index cfcf9732..0a6aa146 100644 --- a/ansible/plugins/modules/vault_load_parsed_secrets.py +++ b/ansible/plugins/modules/vault_load_parsed_secrets.py @@ -215,7 +215,7 @@ def inject_field( for prefix in prefixes: cmd = ( f"oc exec -n {self.namespace} {self.pod} -i -- sh -c " - f"\"vault kv {verb} -mount={mount} {prefix}/{secret_name} {fieldname}='{fieldvalue}'\"" + f"\"vault kv {verb} -mount={mount} {prefix}/{secret_name} {fieldname}='\"'{fieldvalue}'\"'\"" ) self._run_command(cmd, attempts=3) return diff --git a/ansible/tests/unit/test_vault_load_parsed_secrets.py b/ansible/tests/unit/test_vault_load_parsed_secrets.py index ca37de94..1a449739 100644 --- a/ansible/tests/unit/test_vault_load_parsed_secrets.py +++ b/ansible/tests/unit/test_vault_load_parsed_secrets.py @@ -120,7 +120,7 @@ def test_ensure_value_injection_works(self): attempts=3, ), call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret hub/config-demo secret='value123'\"", + "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret hub/config-demo secret='\"'value123'\"'\"", # noqa: E501 attempts=3, ), ] @@ -159,7 +159,7 @@ def test_ensure_b64_value_injection_works(self): attempts=3, ), call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret hub/config-demo secret='dmFsdWUxMjMK'\"", # noqa: E501 + "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret hub/config-demo secret='\"'dmFsdWUxMjMK'\"'\"", # noqa: E501 attempts=3, ), ] @@ -198,11 +198,11 @@ def test_ensure_file_injection_works(self): attempts=3, ), call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret secret/region-one/config-demo secret='value123'\"", # noqa: E501 + "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret secret/region-one/config-demo secret='\"'value123'\"'\"", # noqa: E501 attempts=3, ), call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret secret/snowflake.blueprints.rhecoeng.com/config-demo secret='value123'\"", # noqa: E501 + "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret secret/snowflake.blueprints.rhecoeng.com/config-demo secret='\"'value123'\"'\"", # noqa: E501 attempts=3, ), call( @@ -249,11 +249,11 @@ def test_ensure_file_b64_injection_works(self): attempts=3, ), call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret secret/region-one/config-demo secret='value123'\"", # noqa: E501 + "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret secret/region-one/config-demo secret='\"'value123'\"'\"", # noqa: E501 attempts=3, ), call( - "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret secret/snowflake.blueprints.rhecoeng.com/config-demo secret='value123'\"", # noqa: E501 + "oc exec -n vault vault-0 -i -- sh -c \"vault kv put -mount=secret secret/snowflake.blueprints.rhecoeng.com/config-demo secret='\"'value123'\"'\"", # noqa: E501 attempts=3, ), call( From 6a312d732d1cf551f552eefd5444beddac1243c3 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 11 Jun 2024 15:35:49 +0200 Subject: [PATCH 56/77] Make HUB work when spokes point to in hub cluster gitea With this change we push the hub CA to the spokes in both the openshift-gitops, the namespaced argo namespace and in the imperative namespace. We do this so that the two argo instances are allowed to clone from an eventual gitea repository on the hub. Same goes for the imperative framework which might need to clone the code from the in-cluster gitea service running on the hub. --- acm/templates/policies/acm-hub-ca-policy.yaml | 158 +++++++++++++++++- acm/templates/policies/ocp-gitops-policy.yaml | 13 +- .../templates/imperative/_helpers.tpl | 10 +- clustergroup/templates/plumbing/argocd.yaml | 8 +- 4 files changed, 184 insertions(+), 5 deletions(-) diff --git a/acm/templates/policies/acm-hub-ca-policy.yaml b/acm/templates/policies/acm-hub-ca-policy.yaml index ef15b136..5759247c 100644 --- a/acm/templates/policies/acm-hub-ca-policy.yaml +++ b/acm/templates/policies/acm-hub-ca-policy.yaml @@ -36,6 +36,18 @@ spec: data: hub-kube-root-ca.crt: '{{ `{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}` }}' hub-openshift-service-ca.crt: '{{ `{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}` }}' + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: imperative + data: + hub-kube-root-ca.crt: | + {{ `{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}}` }} + hub-openshift-service-ca.crt: | + {{ `{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}}` }} --- apiVersion: policy.open-cluster-management.io/v1 kind: PlacementBinding @@ -68,5 +80,147 @@ spec: operator: NotIn values: - 'true' -{{- end }} -{{- end }} +--- +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-openshift-gitops-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-openshift-gitops-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: openshift-gitops + data: + hub-kube-root-ca.crt: | + {{ `{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}}` }} + hub-openshift-service-ca.crt: | + {{ `{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}}` }} +--- +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-openshift-gitops-policy-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-openshift-gitops-policy-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-openshift-gitops-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-openshift-gitops-policy-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' + +{{- end }}{{/* if (eq (((.Values.global).secretStore).backend) "vault") */}} +{{- range .Values.clusterGroup.managedClusterGroups }} +{{- $group := . }} +{{- if not .hostedArgoSites }} +--- +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-{{ .name }}-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-{{ .name }}-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: {{ $.Values.global.pattern }}-{{ .name }} + data: + hub-kube-root-ca.crt: | + {{ `{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}}` }} + hub-openshift-service-ca.crt: | + {{ `{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}}` }} +--- +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-{{ .name }}-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-{{ .name }}-placement + kind: PlacementRule + apiGroup: apps.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 +metadata: + name: hub-argo-ca-{{ .name }}-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +{{- end }}{{/* if not .hostedArgoSites */}} +{{- end }}{{/* range .Values.clusterGroup.managedClusterGroups */}} +{{- end }}{{/* isHubCluster */}} diff --git a/acm/templates/policies/ocp-gitops-policy.yaml b/acm/templates/policies/ocp-gitops-policy.yaml index 9210b47f..cdc0a7e1 100644 --- a/acm/templates/policies/ocp-gitops-policy.yaml +++ b/acm/templates/policies/ocp-gitops-policy.yaml @@ -113,6 +113,11 @@ spec: kind: Policy name: openshift-gitops-policy namespace: open-cluster-management + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: hub-argo-ca-openshift-gitops-policy + namespace: open-cluster-management policy-templates: - objectDefinition: apiVersion: policy.open-cluster-management.io/v1 @@ -209,7 +214,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: registry.redhat.io/ubi9/ubi-minimal:latest name: fetch-ca @@ -219,6 +224,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -239,6 +246,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles resourceExclusions: |- diff --git a/clustergroup/templates/imperative/_helpers.tpl b/clustergroup/templates/imperative/_helpers.tpl index f1d99416..88538f88 100644 --- a/clustergroup/templates/imperative/_helpers.tpl +++ b/clustergroup/templates/imperative/_helpers.tpl @@ -16,13 +16,15 @@ - 'sh' - '-c' - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; ls -l /tmp/ca-bundles/ volumeMounts: - mountPath: /var/run/kube-root-ca name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles {{- end }} @@ -95,6 +97,8 @@ name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle +- mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles {{- end }} @@ -112,6 +116,10 @@ name: trusted-ca-bundle optional: true name: trusted-ca-bundle +- configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - name: ca-bundles emptyDir: {} {{- end }} diff --git a/clustergroup/templates/plumbing/argocd.yaml b/clustergroup/templates/plumbing/argocd.yaml index ee1b7c2d..d7a8f7e3 100644 --- a/clustergroup/templates/plumbing/argocd.yaml +++ b/clustergroup/templates/plumbing/argocd.yaml @@ -74,7 +74,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: {{ $.Values.clusterGroup.imperative.image }} name: fetch-ca resources: {} @@ -83,6 +83,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -103,6 +105,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles {{- if len $.Values.clusterGroup.argoCD.initContainers }} From 591a339f7d8f8077185252d66a32194bf2e2221f Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 18 Jun 2024 17:59:54 +0200 Subject: [PATCH 57/77] update tests --- .../acm-industrial-edge-factory.expected.yaml | 13 +- tests/acm-industrial-edge-hub.expected.yaml | 167 +++++++++- tests/acm-medical-diagnosis-hub.expected.yaml | 167 +++++++++- tests/acm-naked.expected.yaml | 13 +- tests/acm-normal.expected.yaml | 309 +++++++++++++++++- ...roup-industrial-edge-factory.expected.yaml | 18 +- ...tergroup-industrial-edge-hub.expected.yaml | 28 +- ...rgroup-medical-diagnosis-hub.expected.yaml | 28 +- tests/clustergroup-naked.expected.yaml | 18 +- tests/clustergroup-normal.expected.yaml | 28 +- 10 files changed, 771 insertions(+), 18 deletions(-) diff --git a/tests/acm-industrial-edge-factory.expected.yaml b/tests/acm-industrial-edge-factory.expected.yaml index 980d0220..39238f91 100644 --- a/tests/acm-industrial-edge-factory.expected.yaml +++ b/tests/acm-industrial-edge-factory.expected.yaml @@ -182,6 +182,11 @@ spec: kind: Policy name: openshift-gitops-policy namespace: open-cluster-management + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: hub-argo-ca-openshift-gitops-policy + namespace: open-cluster-management policy-templates: - objectDefinition: apiVersion: policy.open-cluster-management.io/v1 @@ -278,7 +283,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: registry.redhat.io/ubi9/ubi-minimal:latest name: fetch-ca @@ -288,6 +293,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -308,6 +315,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles resourceExclusions: |- diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml index 7e3bd0f3..83a81f06 100644 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ b/tests/acm-industrial-edge-hub.expected.yaml @@ -38,6 +38,38 @@ subjects: kind: Policy apiGroup: policy.open-cluster-management.io --- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-openshift-gitops-policy-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-openshift-gitops-policy-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-openshift-gitops-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-factory-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-factory-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-factory-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- # Source: acm/templates/policies/application-policies.yaml apiVersion: policy.open-cluster-management.io/v1 kind: PlacementBinding @@ -104,6 +136,42 @@ spec: values: - 'true' --- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-openshift-gitops-policy-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-factory-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- # Source: acm/templates/policies/application-policies.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule @@ -209,6 +277,92 @@ spec: data: hub-kube-root-ca.crt: '{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}' hub-openshift-service-ca.crt: '{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}' + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: imperative + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-openshift-gitops-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-openshift-gitops-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: openshift-gitops + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-factory-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-factory-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: mypattern-factory + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} --- # Source: acm/templates/policies/application-policies.yaml # TODO: Also create a GitOpsCluster.apps.open-cluster-management.io @@ -390,6 +544,11 @@ spec: kind: Policy name: openshift-gitops-policy namespace: open-cluster-management + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: hub-argo-ca-openshift-gitops-policy + namespace: open-cluster-management policy-templates: - objectDefinition: apiVersion: policy.open-cluster-management.io/v1 @@ -486,7 +645,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: registry.redhat.io/ubi9/ubi-minimal:latest name: fetch-ca @@ -496,6 +655,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -516,6 +677,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles resourceExclusions: |- diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml index e63e0654..edb33909 100644 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ b/tests/acm-medical-diagnosis-hub.expected.yaml @@ -38,6 +38,38 @@ subjects: kind: Policy apiGroup: policy.open-cluster-management.io --- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-openshift-gitops-policy-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-openshift-gitops-policy-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-openshift-gitops-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-region-one-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-region-one-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-region-one-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- # Source: acm/templates/policies/application-policies.yaml apiVersion: policy.open-cluster-management.io/v1 kind: PlacementBinding @@ -104,6 +136,42 @@ spec: values: - 'true' --- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-openshift-gitops-policy-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-region-one-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- # Source: acm/templates/policies/application-policies.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule @@ -200,6 +268,92 @@ spec: data: hub-kube-root-ca.crt: '{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}' hub-openshift-service-ca.crt: '{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}' + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: imperative + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-openshift-gitops-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-openshift-gitops-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: openshift-gitops + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-region-one-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-region-one-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: mypattern-region-one + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} --- # Source: acm/templates/policies/application-policies.yaml # TODO: Also create a GitOpsCluster.apps.open-cluster-management.io @@ -381,6 +535,11 @@ spec: kind: Policy name: openshift-gitops-policy namespace: open-cluster-management + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: hub-argo-ca-openshift-gitops-policy + namespace: open-cluster-management policy-templates: - objectDefinition: apiVersion: policy.open-cluster-management.io/v1 @@ -477,7 +636,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: registry.redhat.io/ubi9/ubi-minimal:latest name: fetch-ca @@ -487,6 +646,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -507,6 +668,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles resourceExclusions: |- diff --git a/tests/acm-naked.expected.yaml b/tests/acm-naked.expected.yaml index 980d0220..39238f91 100644 --- a/tests/acm-naked.expected.yaml +++ b/tests/acm-naked.expected.yaml @@ -182,6 +182,11 @@ spec: kind: Policy name: openshift-gitops-policy namespace: open-cluster-management + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: hub-argo-ca-openshift-gitops-policy + namespace: open-cluster-management policy-templates: - objectDefinition: apiVersion: policy.open-cluster-management.io/v1 @@ -278,7 +283,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: registry.redhat.io/ubi9/ubi-minimal:latest name: fetch-ca @@ -288,6 +293,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -308,6 +315,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles resourceExclusions: |- diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index f3ca998a..6660ae87 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -796,6 +796,70 @@ subjects: kind: Policy apiGroup: policy.open-cluster-management.io --- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-openshift-gitops-policy-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-openshift-gitops-policy-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-openshift-gitops-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-acm-edge-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-acm-edge-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-acm-edge-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-acm-provision-edge-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-acm-provision-edge-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-acm-provision-edge-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-acm-provision-on-deploy-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-acm-provision-on-deploy-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-acm-provision-on-deploy-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- # Source: acm/templates/policies/application-policies.yaml apiVersion: policy.open-cluster-management.io/v1 kind: PlacementBinding @@ -894,6 +958,78 @@ spec: values: - 'true' --- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-openshift-gitops-policy-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-acm-edge-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-acm-provision-edge-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-acm-provision-on-deploy-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- # Source: acm/templates/policies/application-policies.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule @@ -1018,6 +1154,166 @@ spec: data: hub-kube-root-ca.crt: '{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}' hub-openshift-service-ca.crt: '{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}' + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: imperative + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-openshift-gitops-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-openshift-gitops-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: openshift-gitops + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-acm-edge-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-acm-edge-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: mypattern-acm-edge + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-acm-provision-edge-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-acm-provision-edge-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: mypattern-acm-provision-edge + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-acm-provision-on-deploy-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-acm-provision-on-deploy-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: mypattern-acm-provision-on-deploy + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} --- # Source: acm/templates/policies/application-policies.yaml # TODO: Also create a GitOpsCluster.apps.open-cluster-management.io @@ -1393,6 +1689,11 @@ spec: kind: Policy name: openshift-gitops-policy namespace: open-cluster-management + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: hub-argo-ca-openshift-gitops-policy + namespace: open-cluster-management policy-templates: - objectDefinition: apiVersion: policy.open-cluster-management.io/v1 @@ -1489,7 +1790,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: registry.redhat.io/ubi9/ubi-minimal:latest name: fetch-ca @@ -1499,6 +1800,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -1519,6 +1822,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles resourceExclusions: |- diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index ad6cfa3c..49c2c1d6 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -454,13 +454,15 @@ spec: - 'sh' - '-c' - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; ls -l /tmp/ca-bundles/ volumeMounts: - mountPath: /var/run/kube-root-ca name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles - name: git-init @@ -530,6 +532,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles containers: @@ -555,6 +559,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - name: ca-bundles emptyDir: {} restartPolicy: Never @@ -742,7 +750,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest name: fetch-ca resources: {} @@ -751,6 +759,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -771,6 +781,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles sidecarContainers: diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index cc30a7ac..4730754c 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -615,13 +615,15 @@ spec: - 'sh' - '-c' - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; ls -l /tmp/ca-bundles/ volumeMounts: - mountPath: /var/run/kube-root-ca name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles - name: git-init @@ -691,6 +693,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles containers: @@ -716,6 +720,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - name: ca-bundles emptyDir: {} restartPolicy: Never @@ -751,13 +759,15 @@ spec: - 'sh' - '-c' - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; ls -l /tmp/ca-bundles/ volumeMounts: - mountPath: /var/run/kube-root-ca name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles - name: git-init @@ -829,6 +839,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles containers: @@ -854,6 +866,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - name: ca-bundles emptyDir: {} restartPolicy: Never @@ -1509,7 +1525,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest name: fetch-ca resources: {} @@ -1518,6 +1534,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -1538,6 +1556,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles sidecarContainers: diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 1888528f..76083c4e 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -542,13 +542,15 @@ spec: - 'sh' - '-c' - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; ls -l /tmp/ca-bundles/ volumeMounts: - mountPath: /var/run/kube-root-ca name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles - name: git-init @@ -618,6 +620,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles containers: @@ -643,6 +647,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - name: ca-bundles emptyDir: {} restartPolicy: Never @@ -678,13 +686,15 @@ spec: - 'sh' - '-c' - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; ls -l /tmp/ca-bundles/ volumeMounts: - mountPath: /var/run/kube-root-ca name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles - name: git-init @@ -756,6 +766,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles containers: @@ -781,6 +793,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - name: ca-bundles emptyDir: {} restartPolicy: Never @@ -1694,7 +1710,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest name: fetch-ca resources: {} @@ -1703,6 +1719,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -1723,6 +1741,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles resources: diff --git a/tests/clustergroup-naked.expected.yaml b/tests/clustergroup-naked.expected.yaml index 56452cca..16c6d81d 100644 --- a/tests/clustergroup-naked.expected.yaml +++ b/tests/clustergroup-naked.expected.yaml @@ -307,13 +307,15 @@ spec: - 'sh' - '-c' - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; ls -l /tmp/ca-bundles/ volumeMounts: - mountPath: /var/run/kube-root-ca name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles - name: git-init @@ -385,6 +387,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles containers: @@ -410,6 +414,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - name: ca-bundles emptyDir: {} restartPolicy: Never @@ -488,7 +496,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest name: fetch-ca resources: {} @@ -497,6 +505,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -517,6 +527,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles resources: diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index ba0e704d..0ff865e3 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -523,13 +523,15 @@ spec: - 'sh' - '-c' - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; ls -l /tmp/ca-bundles/ volumeMounts: - mountPath: /var/run/kube-root-ca name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles - name: git-init @@ -599,6 +601,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles containers: @@ -624,6 +628,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - name: ca-bundles emptyDir: {} restartPolicy: Never @@ -659,13 +667,15 @@ spec: - 'sh' - '-c' - >- - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true; + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; ls -l /tmp/ca-bundles/ volumeMounts: - mountPath: /var/run/kube-root-ca name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles - name: git-init @@ -737,6 +747,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles containers: @@ -762,6 +774,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - name: ca-bundles emptyDir: {} restartPolicy: Never @@ -1258,7 +1274,7 @@ spec: - command: - bash - -c - - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt > /tmp/ca-bundles/ca-bundle.crt || true + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest name: fetch-ca resources: {} @@ -1267,6 +1283,8 @@ spec: name: kube-root-ca - mountPath: /var/run/trusted-ca name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle - mountPath: /tmp/ca-bundles name: ca-bundles resources: @@ -1287,6 +1305,10 @@ spec: name: trusted-ca-bundle optional: true name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle - emptyDir: {} name: ca-bundles resources: From de5647f19c931452cda24291b344e0ae516c5ce0 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 24 Jun 2024 10:42:09 +0200 Subject: [PATCH 58/77] ACM chart version 0.0.2 --- acm/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acm/Chart.yaml b/acm/Chart.yaml index 3bae9da5..5ab78a75 100644 --- a/acm/Chart.yaml +++ b/acm/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to configure Advanced Cluster Manager for OpenShift. keywords: - pattern name: acm -version: 0.0.1 +version: 0.0.2 From 1fa57464d8bba92c7e7dc171634833df99f946e4 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 24 Jun 2024 10:42:36 +0200 Subject: [PATCH 59/77] golang-external-secrets chart version 0.0.4 --- golang-external-secrets/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/golang-external-secrets/Chart.yaml b/golang-external-secrets/Chart.yaml index afffe393..2c214633 100644 --- a/golang-external-secrets/Chart.yaml +++ b/golang-external-secrets/Chart.yaml @@ -3,7 +3,7 @@ description: A Helm chart to configure the golang-based external-secrets. keywords: - pattern name: golang-external-secrets -version: 0.0.3 +version: 0.0.4 dependencies: - name: external-secrets version: "0.9.19" From 89b499b3cb114c41b5d2181537430094897dcd0f Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 24 Jun 2024 10:42:56 +0200 Subject: [PATCH 60/77] hashicorp-vault chart version 0.0.2 --- hashicorp-vault/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hashicorp-vault/Chart.yaml b/hashicorp-vault/Chart.yaml index e1577595..0fcbcb48 100644 --- a/hashicorp-vault/Chart.yaml +++ b/hashicorp-vault/Chart.yaml @@ -3,7 +3,7 @@ description: A Helm chart to configure Hashicorp's vault. keywords: - pattern name: hashicorp-vault -version: 0.0.1 +version: 0.0.2 dependencies: - name: vault version: "0.28.0" From 89a4cadd511133803ebff74869bb4cbec4a98705 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 24 Jun 2024 11:00:40 +0200 Subject: [PATCH 61/77] Implement multi-source --- acm/templates/_helpers.tpl | 44 +++++++++++++ .../policies/application-policies.yaml | 64 ++++++++++++------- clustergroup/templates/_helpers.tpl | 10 ++- 3 files changed, 94 insertions(+), 24 deletions(-) diff --git a/acm/templates/_helpers.tpl b/acm/templates/_helpers.tpl index 910b3970..8302457a 100644 --- a/acm/templates/_helpers.tpl +++ b/acm/templates/_helpers.tpl @@ -11,3 +11,47 @@ Default always defined valueFiles to be included when pushing the cluster wide a # hub's cluster version, whereas we want to include the spoke cluster version - '/values-{{ `{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}` }}.yaml' {{- end }} {{- /*acm.app.policies.valuefiles */}} + +{{- define "acm.app.policies.multisourcevaluefiles" -}} +- "$patternref/values-global.yaml" +- "$patternref/values-{{ .name }}.yaml" +- '$patternref/values-{{ `{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}` }}.yaml' +- '$patternref/values-{{ `{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}` }}-{{ `{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}` }}.yaml' +- '$patternref/values-{{ `{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}` }}-{{ .name }}.yaml' +# We cannot use $.Values.global.clusterVersion because that gets resolved to the +# hub's cluster version, whereas we want to include the spoke cluster version +- '$patternref/values-{{ `{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}` }}.yaml' +{{- end }} {{- /*acm.app.policies.multisourcevaluefiles */}} + +{{- define "acm.app.policies.helmparameters" -}} +- name: global.repoURL + value: {{ $.Values.global.repoURL }} +- name: global.targetRevision + value: {{ $.Values.global.targetRevision }} +- name: global.namespace + value: $ARGOCD_APP_NAMESPACE +- name: global.pattern + value: {{ $.Values.global.pattern }} +- name: global.hubClusterDomain + value: {{ $.Values.global.hubClusterDomain }} +- name: global.localClusterDomain + value: '{{ `{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}` }}' +- name: global.clusterDomain + value: '{{ `{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}` }}' +- name: global.clusterVersion + value: '{{ `{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}` }}' +- name: global.localClusterName + value: '{{ `{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}` }}' +- name: global.clusterPlatform + value: {{ $.Values.global.clusterPlatform }} +- name: global.multiSourceSupport + value: {{ $.Values.global.multiSourceSupport | quote }} +- name: global.multiSourceRepoUrl + value: {{ $.Values.global.multiSourceRepoUrl }} +- name: global.multiSourceTargetRevision + value: {{ $.Values.global.multiSourceTargetRevision }} +- name: global.privateRepo + value: {{ $.Values.global.privateRepo | quote }} +- name: global.experimentalCapabilities + value: {{ $.Values.global.experimentalCapabilities }} +{{- end }} {{- /*acm.app.policies.helmparameters */}} diff --git a/acm/templates/policies/application-policies.yaml b/acm/templates/policies/application-policies.yaml index 01073bd4..5f0d132f 100644 --- a/acm/templates/policies/application-policies.yaml +++ b/acm/templates/policies/application-policies.yaml @@ -36,6 +36,46 @@ spec: - resources-finalizer.argocd.argoproj.io/foreground spec: project: default + {{- if $.Values.global.multiSourceSupport }} + sources: + - repoURL: {{ coalesce .repoURL $.Values.global.repoURL }} + targetRevision: {{ coalesce .targetRevision $.Values.global.targetRevision }} + ref: patternref + - repoURL: {{ $.Values.global.multiSourceRepoUrl }} + targetRevision: {{ $.Values.global.multiSourceTargetRevision }} + helm: + ignoreMissingValueFiles: true + values: | + extraParametersNested: + {{- range $k, $v := $.Values.extraParametersNested }} + {{ $k }}: {{ printf "%s" $v | quote }} + {{- end }} + valueFiles: + {{- include "acm.app.policies.multisourcevaluefiles" . | nindent 26 }} + {{- range $valueFile := .extraValueFiles }} + - {{ $valueFile | quote }} + {{- end }} + parameters: + {{- include "acm.app.policies.helmparameters" $ | nindent 26 }} + - name: clusterGroup.name + value: {{ $group.name }} + {{- range $k, $v := $.Values.extraParametersNested }} + - name: {{ $k }} + value: {{ printf "%s" $v | quote }} + {{- end }} + {{- range .helmOverrides }} + - name: {{ .name }} + value: {{ .value | quote }} + {{- end }} + {{- if .fileParameters }} + fileParameters: + {{- range .fileParameters }} + - name: {{ .name }} + path: {{ .path }} + {{- end }} + {{- end }} + + {{- else }} source: repoURL: {{ coalesce .repoURL $.Values.global.repoURL }} targetRevision: {{ coalesce .targetRevision $.Values.global.targetRevision }} @@ -53,30 +93,9 @@ spec: - {{ $valueFile | quote }} {{- end }} parameters: - - name: global.repoURL - value: {{ $.Values.global.repoURL }} - - name: global.targetRevision - value: {{ $.Values.global.targetRevision }} - - name: global.namespace - value: $ARGOCD_APP_NAMESPACE - - name: global.pattern - value: {{ $.Values.global.pattern }} - - name: global.hubClusterDomain - value: {{ $.Values.global.hubClusterDomain }} - - name: global.localClusterDomain - value: '{{ `{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}` }}' - - name: global.clusterDomain - value: '{{ `{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}` }}' - - name: global.clusterVersion - value: '{{ `{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}` }}' - - name: global.localClusterName - value: '{{ `{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}` }}' - - name: global.clusterPlatform - value: {{ $.Values.global.clusterPlatform }} + {{- include "acm.app.policies.helmparameters" $ | nindent 22 }} - name: clusterGroup.name value: {{ $group.name }} - - name: global.experimentalCapabilities - value: {{ $.Values.global.experimentalCapabilities }} {{- range $k, $v := $.Values.extraParametersNested }} - name: {{ $k }} value: {{ printf "%s" $v | quote }} @@ -92,6 +111,7 @@ spec: path: {{ .path }} {{- end }} {{- end }} + {{- end }}{{/* if $.Values.global.multiSourceSupport */}} destination: server: https://kubernetes.default.svc namespace: {{ $.Values.global.pattern }}-{{ .name }} diff --git a/clustergroup/templates/_helpers.tpl b/clustergroup/templates/_helpers.tpl index c6d14d08..0237e94a 100644 --- a/clustergroup/templates/_helpers.tpl +++ b/clustergroup/templates/_helpers.tpl @@ -3,9 +3,9 @@ Default always defined top-level variables for helm charts */}} {{- define "clustergroup.app.globalvalues.helmparameters" -}} - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: {{ $.Values.global.repoURL }} - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: {{ $.Values.global.targetRevision }} - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -18,6 +18,12 @@ Default always defined top-level variables for helm charts value: "{{ $.Values.global.clusterPlatform }}" - name: global.hubClusterDomain value: {{ $.Values.global.hubClusterDomain }} +- name: global.multiSourceSupport + value: {{ $.Values.global.multiSourceSupport | quote }} +- name: global.multiSourceRepoUrl + value: {{ $.Values.global.multiSourceRepoUrl }} +- name: global.multiSourceTargetRevision + value: {{ $.Values.global.multiSourceTargetRevision }} - name: global.localClusterDomain value: {{ coalesce $.Values.global.localClusterDomain $.Values.global.hubClusterDomain }} - name: global.privateRepo From 2e7866966f29dae91c7f3a88e92c18c32ec6d8e6 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 29 Jun 2024 17:36:52 +0200 Subject: [PATCH 62/77] Add tests for proper multisource support on spokes --- tests/acm-industrial-edge-hub.expected.yaml | 12 +- tests/acm-medical-diagnosis-hub.expected.yaml | 12 +- tests/acm-normal.expected.yaml | 36 ++++- ...roup-industrial-edge-factory.expected.yaml | 10 +- ...tergroup-industrial-edge-hub.expected.yaml | 70 ++++++++-- ...rgroup-medical-diagnosis-hub.expected.yaml | 130 ++++++++++++++---- tests/clustergroup-normal.expected.yaml | 20 ++- 7 files changed, 234 insertions(+), 56 deletions(-) diff --git a/tests/acm-industrial-edge-hub.expected.yaml b/tests/acm-industrial-edge-hub.expected.yaml index 83a81f06..8b18a4da 100644 --- a/tests/acm-industrial-edge-hub.expected.yaml +++ b/tests/acm-industrial-edge-hub.expected.yaml @@ -438,10 +438,18 @@ spec: value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - name: global.clusterPlatform value: aws - - name: clusterGroup.name - value: factory + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: + - name: global.privateRepo + value: - name: global.experimentalCapabilities value: + - name: clusterGroup.name + value: factory - name: clusterGroup.isHubCluster value: "false" destination: diff --git a/tests/acm-medical-diagnosis-hub.expected.yaml b/tests/acm-medical-diagnosis-hub.expected.yaml index edb33909..dffb9eb6 100644 --- a/tests/acm-medical-diagnosis-hub.expected.yaml +++ b/tests/acm-medical-diagnosis-hub.expected.yaml @@ -429,10 +429,18 @@ spec: value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - name: global.clusterPlatform value: aws - - name: clusterGroup.name - value: region-one + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: + - name: global.privateRepo + value: - name: global.experimentalCapabilities value: + - name: clusterGroup.name + value: region-one - name: clusterGroup.isHubCluster value: "false" destination: diff --git a/tests/acm-normal.expected.yaml b/tests/acm-normal.expected.yaml index 6660ae87..1e2b1573 100644 --- a/tests/acm-normal.expected.yaml +++ b/tests/acm-normal.expected.yaml @@ -1389,10 +1389,18 @@ spec: value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - name: global.clusterPlatform value: aws - - name: clusterGroup.name - value: acm-edge + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: + - name: global.privateRepo + value: - name: global.experimentalCapabilities value: + - name: clusterGroup.name + value: acm-edge - name: clusterGroup.isHubCluster value: "false" destination: @@ -1487,10 +1495,18 @@ spec: value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - name: global.clusterPlatform value: aws - - name: clusterGroup.name - value: acm-provision-edge + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: + - name: global.privateRepo + value: - name: global.experimentalCapabilities value: + - name: clusterGroup.name + value: acm-provision-edge - name: clusterGroup.isHubCluster value: "false" destination: @@ -1585,10 +1601,18 @@ spec: value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - name: global.clusterPlatform value: aws - - name: clusterGroup.name - value: acm-provision-on-deploy + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: + - name: global.privateRepo + value: - name: global.experimentalCapabilities value: + - name: clusterGroup.name + value: acm-provision-on-deploy destination: server: https://kubernetes.default.svc namespace: mypattern-acm-provision-on-deploy diff --git a/tests/clustergroup-industrial-edge-factory.expected.yaml b/tests/clustergroup-industrial-edge-factory.expected.yaml index 49c2c1d6..0d479fe4 100644 --- a/tests/clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/clustergroup-industrial-edge-factory.expected.yaml @@ -650,9 +650,9 @@ spec: - "/values-4.12-factory.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -665,6 +665,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo diff --git a/tests/clustergroup-industrial-edge-hub.expected.yaml b/tests/clustergroup-industrial-edge-hub.expected.yaml index 4730754c..626b823a 100644 --- a/tests/clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/clustergroup-industrial-edge-hub.expected.yaml @@ -993,9 +993,9 @@ spec: - "/values-4.12-datacenter.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1008,6 +1008,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1060,9 +1066,9 @@ spec: - "/values-4.12-datacenter.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1075,6 +1081,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1118,9 +1130,9 @@ spec: - "/values-4.12-datacenter.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1133,6 +1145,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1176,9 +1194,9 @@ spec: - "/values-4.12-datacenter.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1191,6 +1209,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1264,9 +1288,9 @@ spec: - "/values-4.12-datacenter.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1279,6 +1303,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1322,9 +1352,9 @@ spec: - "/values-4.12-datacenter.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1337,6 +1367,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1407,9 +1443,9 @@ spec: - "/values-4.12-datacenter.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1422,6 +1458,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo diff --git a/tests/clustergroup-medical-diagnosis-hub.expected.yaml b/tests/clustergroup-medical-diagnosis-hub.expected.yaml index 76083c4e..0b15ec3a 100644 --- a/tests/clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/clustergroup-medical-diagnosis-hub.expected.yaml @@ -878,9 +878,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -893,6 +893,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -936,9 +942,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -951,6 +957,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -994,9 +1006,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1009,6 +1021,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1052,9 +1070,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1067,6 +1085,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1110,9 +1134,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1125,6 +1149,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1168,9 +1198,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1183,6 +1213,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1226,9 +1262,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1241,6 +1277,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1284,9 +1326,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1299,6 +1341,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1360,9 +1408,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1375,6 +1423,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1418,9 +1472,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1433,6 +1487,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1476,9 +1536,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1491,6 +1551,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1543,9 +1609,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1558,6 +1624,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1610,9 +1682,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1625,6 +1697,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo diff --git a/tests/clustergroup-normal.expected.yaml b/tests/clustergroup-normal.expected.yaml index 0ff865e3..9b035135 100644 --- a/tests/clustergroup-normal.expected.yaml +++ b/tests/clustergroup-normal.expected.yaml @@ -864,9 +864,9 @@ spec: - "/values/4.12.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -879,6 +879,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -934,9 +940,9 @@ spec: - "/values/4.12/aws.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -949,6 +955,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo From 9a3aa2b289bbb4bf6c77184254e734f58035617e Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 29 Jun 2024 19:13:30 +0200 Subject: [PATCH 63/77] Release clustergroup v0.8.9 --- clustergroup/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustergroup/Chart.yaml b/clustergroup/Chart.yaml index 5b774788..ab8abbf5 100644 --- a/clustergroup/Chart.yaml +++ b/clustergroup/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to create per-clustergroup ArgoCD applications and any keywords: - pattern name: clustergroup -version: 0.8.8 +version: 0.8.9 From 13f3b23d0cd7d7131b5105e472da362c1f54c282 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 29 Jun 2024 20:11:21 +0200 Subject: [PATCH 64/77] Fix multisource indent error --- acm/templates/policies/application-policies.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acm/templates/policies/application-policies.yaml b/acm/templates/policies/application-policies.yaml index 5f0d132f..d157e473 100644 --- a/acm/templates/policies/application-policies.yaml +++ b/acm/templates/policies/application-policies.yaml @@ -51,12 +51,12 @@ spec: {{ $k }}: {{ printf "%s" $v | quote }} {{- end }} valueFiles: - {{- include "acm.app.policies.multisourcevaluefiles" . | nindent 26 }} + {{- include "acm.app.policies.multisourcevaluefiles" . | nindent 24 }} {{- range $valueFile := .extraValueFiles }} - {{ $valueFile | quote }} {{- end }} parameters: - {{- include "acm.app.policies.helmparameters" $ | nindent 26 }} + {{- include "acm.app.policies.helmparameters" $ | nindent 24 }} - name: clusterGroup.name value: {{ $group.name }} {{- range $k, $v := $.Values.extraParametersNested }} From ac6640c6d83e931ac4b6c95d742cc92eecc3ebdb Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 29 Jun 2024 20:13:02 +0200 Subject: [PATCH 65/77] Release clustergroup v0.8.10 --- clustergroup/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clustergroup/Chart.yaml b/clustergroup/Chart.yaml index ab8abbf5..b2d703a2 100644 --- a/clustergroup/Chart.yaml +++ b/clustergroup/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to create per-clustergroup ArgoCD applications and any keywords: - pattern name: clustergroup -version: 0.8.9 +version: 0.8.10 From 5f678b534a5e21c47b830194c3e4db2479e190ca Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 29 Jun 2024 20:18:15 +0200 Subject: [PATCH 66/77] Release acm v0.0.3 --- acm/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acm/Chart.yaml b/acm/Chart.yaml index 5ab78a75..b756d549 100644 --- a/acm/Chart.yaml +++ b/acm/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to configure Advanced Cluster Manager for OpenShift. keywords: - pattern name: acm -version: 0.0.2 +version: 0.0.3 From ca9e3a2831df18ff3137fe338cd48c7f4eaf0aac Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Sat, 29 Jun 2024 20:46:23 +0200 Subject: [PATCH 67/77] Fix missing chart field --- acm/templates/policies/application-policies.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/acm/templates/policies/application-policies.yaml b/acm/templates/policies/application-policies.yaml index d157e473..fd7c2a3f 100644 --- a/acm/templates/policies/application-policies.yaml +++ b/acm/templates/policies/application-policies.yaml @@ -43,6 +43,7 @@ spec: ref: patternref - repoURL: {{ $.Values.global.multiSourceRepoUrl }} targetRevision: {{ $.Values.global.multiSourceTargetRevision }} + chart: clustergroup helm: ignoreMissingValueFiles: true values: | From 5bdeff5e33c49fba525e8fc21439b29bb8b26de8 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 9 Jul 2024 17:16:31 +0200 Subject: [PATCH 68/77] Release acm v0.0.4 --- acm/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acm/Chart.yaml b/acm/Chart.yaml index b756d549..327e0ba5 100644 --- a/acm/Chart.yaml +++ b/acm/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to configure Advanced Cluster Manager for OpenShift. keywords: - pattern name: acm -version: 0.0.3 +version: 0.0.4 From bf0c8aac8a2d3b1e0437cd76eb57b940b49447d6 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Tue, 9 Jul 2024 18:04:18 +0200 Subject: [PATCH 69/77] Update chart versions --- acm/Chart.yaml | 2 +- golang-external-secrets/Chart.yaml | 2 +- hashicorp-vault/Chart.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/acm/Chart.yaml b/acm/Chart.yaml index 327e0ba5..31fa54ea 100644 --- a/acm/Chart.yaml +++ b/acm/Chart.yaml @@ -3,4 +3,4 @@ description: A Helm chart to configure Advanced Cluster Manager for OpenShift. keywords: - pattern name: acm -version: 0.0.4 +version: 0.1.0 diff --git a/golang-external-secrets/Chart.yaml b/golang-external-secrets/Chart.yaml index 2c214633..b304d092 100644 --- a/golang-external-secrets/Chart.yaml +++ b/golang-external-secrets/Chart.yaml @@ -3,7 +3,7 @@ description: A Helm chart to configure the golang-based external-secrets. keywords: - pattern name: golang-external-secrets -version: 0.0.4 +version: 0.1.0 dependencies: - name: external-secrets version: "0.9.19" diff --git a/hashicorp-vault/Chart.yaml b/hashicorp-vault/Chart.yaml index 0fcbcb48..ef3c22d2 100644 --- a/hashicorp-vault/Chart.yaml +++ b/hashicorp-vault/Chart.yaml @@ -3,7 +3,7 @@ description: A Helm chart to configure Hashicorp's vault. keywords: - pattern name: hashicorp-vault -version: 0.0.2 +version: 0.1.0 dependencies: - name: vault version: "0.28.0" From fc675e51643b2c9ad12e86654c305ced7939f881 Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 15 Jul 2024 10:17:31 -0600 Subject: [PATCH 70/77] Update vault-helm to v0.28.1 and vault to 1.17.2 --- hashicorp-vault/Chart.yaml | 2 +- hashicorp-vault/charts/vault-0.28.0.tgz | Bin 49079 -> 0 bytes hashicorp-vault/charts/vault-0.28.1.tgz | Bin 0 -> 49807 bytes hashicorp-vault/values.yaml | 2 +- ...ault-industrial-edge-factory.expected.yaml | 20 +++++++++--------- ...rp-vault-industrial-edge-hub.expected.yaml | 20 +++++++++--------- ...-vault-medical-diagnosis-hub.expected.yaml | 20 +++++++++--------- tests/hashicorp-vault-naked.expected.yaml | 20 +++++++++--------- tests/hashicorp-vault-normal.expected.yaml | 20 +++++++++--------- 9 files changed, 52 insertions(+), 52 deletions(-) delete mode 100644 hashicorp-vault/charts/vault-0.28.0.tgz create mode 100644 hashicorp-vault/charts/vault-0.28.1.tgz diff --git a/hashicorp-vault/Chart.yaml b/hashicorp-vault/Chart.yaml index ef3c22d2..ede5950f 100644 --- a/hashicorp-vault/Chart.yaml +++ b/hashicorp-vault/Chart.yaml @@ -6,5 +6,5 @@ name: hashicorp-vault version: 0.1.0 dependencies: - name: vault - version: "0.28.0" + version: "0.28.1" repository: "https://helm.releases.hashicorp.com" diff --git a/hashicorp-vault/charts/vault-0.28.0.tgz b/hashicorp-vault/charts/vault-0.28.0.tgz deleted file mode 100644 index 0e02f376d504c1c78df62986fa658fc8a73e796c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49079 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

-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

U@r}nz0LDB{;n` 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 z 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 z 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 Date: Mon, 15 Jul 2024 15:02:36 -0600 Subject: [PATCH 72/77] Release new hashicorp-vault and golang-external-secrets charts --- golang-external-secrets/Chart.yaml | 2 +- hashicorp-vault/Chart.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/golang-external-secrets/Chart.yaml b/golang-external-secrets/Chart.yaml index 802979b4..0bcc381d 100644 --- a/golang-external-secrets/Chart.yaml +++ b/golang-external-secrets/Chart.yaml @@ -3,7 +3,7 @@ description: A Helm chart to configure the golang-based external-secrets. keywords: - pattern name: golang-external-secrets -version: 0.1.0 +version: 0.1.1 dependencies: - name: external-secrets version: "0.9.20" diff --git a/hashicorp-vault/Chart.yaml b/hashicorp-vault/Chart.yaml index ede5950f..87d3470d 100644 --- a/hashicorp-vault/Chart.yaml +++ b/hashicorp-vault/Chart.yaml @@ -3,7 +3,7 @@ description: A Helm chart to configure Hashicorp's vault. keywords: - pattern name: hashicorp-vault -version: 0.1.0 +version: 0.1.1 dependencies: - name: vault version: "0.28.1" From 5a5c7ffc7b38a9ba74e9727b551c9681231a7bcc Mon Sep 17 00:00:00 2001 From: Martin Jackson Date: Mon, 29 Jul 2024 08:39:19 -0500 Subject: [PATCH 73/77] Update tests --- ...-acm-industrial-edge-factory.expected.yaml | 260 +++- ...mmon-acm-industrial-edge-hub.expected.yaml | 430 +++++- ...on-acm-medical-diagnosis-hub.expected.yaml | 430 +++++- tests/common-acm-naked.expected.yaml | 260 +++- tests/common-acm-normal.expected.yaml | 1261 +++++++++++++++-- ...roup-industrial-edge-factory.expected.yaml | 179 ++- ...tergroup-industrial-edge-hub.expected.yaml | 298 +++- ...rgroup-medical-diagnosis-hub.expected.yaml | 370 ++++- tests/common-clustergroup-naked.expected.yaml | 167 ++- .../common-clustergroup-normal.expected.yaml | 267 +++- ...rets-industrial-edge-factory.expected.yaml | 594 +++++++- ...-secrets-industrial-edge-hub.expected.yaml | 592 +++++++- ...ecrets-medical-diagnosis-hub.expected.yaml | 592 +++++++- ...olang-external-secrets-naked.expected.yaml | 592 +++++++- ...lang-external-secrets-normal.expected.yaml | 592 +++++++- ...ault-industrial-edge-factory.expected.yaml | 20 +- ...rp-vault-industrial-edge-hub.expected.yaml | 20 +- ...-vault-medical-diagnosis-hub.expected.yaml | 20 +- ...common-hashicorp-vault-naked.expected.yaml | 20 +- ...ommon-hashicorp-vault-normal.expected.yaml | 20 +- ...tall-industrial-edge-factory.expected.yaml | 3 - ...-install-industrial-edge-hub.expected.yaml | 3 - ...nstall-medical-diagnosis-hub.expected.yaml | 3 - ...ommon-operator-install-naked.expected.yaml | 3 - ...mmon-operator-install-normal.expected.yaml | 3 - 25 files changed, 6398 insertions(+), 601 deletions(-) diff --git a/tests/common-acm-industrial-edge-factory.expected.yaml b/tests/common-acm-industrial-edge-factory.expected.yaml index 561fbd7b..39238f91 100644 --- a/tests/common-acm-industrial-edge-factory.expected.yaml +++ b/tests/common-acm-industrial-edge-factory.expected.yaml @@ -42,6 +42,22 @@ subjects: apiGroup: policy.open-cluster-management.io --- # Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: openshift-gitops-placement-binding-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: openshift-gitops-placement-argocd + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: openshift-gitops-policy-argocd + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule metadata: @@ -64,6 +80,28 @@ spec: - 'true' --- # Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: openshift-gitops-placement-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: vendor + operator: In + values: + - OpenShift + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml apiVersion: policy.open-cluster-management.io/v1 kind: Policy metadata: @@ -90,15 +128,6 @@ spec: include: - default object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT @@ -119,3 +148,216 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +# This policy depends on openshift-gitops-policy and the reason is that we need to be +# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance +# because the initcontainer references the trusted-ca-bundle and if it starts without the +# configmap being there we risk running an argo instances that won't trust public CAs +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: openshift-gitops-policy-argocd + annotations: + policy.open-cluster-management.io/standards: NIST-CSF + policy.open-cluster-management.io/categories: PR.DS Data Security + policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + dependencies: + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: openshift-gitops-policy + namespace: open-cluster-management + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: hub-argo-ca-openshift-gitops-policy + namespace: open-cluster-management + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: openshift-gitops-config-argocd + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + apiVersion: argoproj.io/v1beta1 + kind: ArgoCD + metadata: + name: openshift-gitops + namespace: openshift-gitops + spec: + applicationSet: + resources: + limits: + cpu: "2" + memory: 1Gi + requests: + cpu: 250m + memory: 512Mi + webhookServer: + ingress: + enabled: false + route: + enabled: false + controller: + processors: {} + resources: + limits: + cpu: "2" + memory: 2Gi + requests: + cpu: 250m + memory: 1Gi + sharding: {} + grafana: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + route: + enabled: false + ha: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + initialSSHKnownHosts: {} + monitoring: + enabled: false + notifications: + enabled: false + prometheus: + enabled: false + ingress: + enabled: false + route: + enabled: false + rbac: + defaultPolicy: "" + policy: |- + g, system:cluster-admins, role:admin + g, cluster-admins, role:admin + scopes: '[groups]' + redis: + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt + || true + image: registry.redhat.io/ubi9/ubi-minimal:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle + - emptyDir: {} + name: ca-bundles + resourceExclusions: |- + - apiGroups: + - tekton.dev + clusters: + - '*' + kinds: + - TaskRun + - PipelineRun + server: + autoscale: + enabled: false + grpc: + ingress: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 125m + memory: 128Mi + route: + enabled: true + service: + type: "" + sso: + dex: + openShiftOAuth: true + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + provider: dex + tls: + ca: {} diff --git a/tests/common-acm-industrial-edge-hub.expected.yaml b/tests/common-acm-industrial-edge-hub.expected.yaml index 453e8a9e..8b18a4da 100644 --- a/tests/common-acm-industrial-edge-hub.expected.yaml +++ b/tests/common-acm-industrial-edge-hub.expected.yaml @@ -38,6 +38,38 @@ subjects: kind: Policy apiGroup: policy.open-cluster-management.io --- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-openshift-gitops-policy-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-openshift-gitops-policy-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-openshift-gitops-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-factory-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-factory-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-factory-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- # Source: acm/templates/policies/application-policies.yaml apiVersion: policy.open-cluster-management.io/v1 kind: PlacementBinding @@ -70,6 +102,22 @@ subjects: kind: Policy apiGroup: policy.open-cluster-management.io --- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: openshift-gitops-placement-binding-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: openshift-gitops-placement-argocd + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: openshift-gitops-policy-argocd + kind: Policy + apiGroup: policy.open-cluster-management.io +--- # Source: acm/templates/policies/acm-hub-ca-policy.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule @@ -88,6 +136,42 @@ spec: values: - 'true' --- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-openshift-gitops-policy-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-factory-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- # Source: acm/templates/policies/application-policies.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule @@ -136,6 +220,28 @@ spec: values: - 'true' --- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: openshift-gitops-placement-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: vendor + operator: In + values: + - OpenShift + - key: local-cluster + operator: NotIn + values: + - 'true' +--- # Source: acm/templates/policies/acm-hub-ca-policy.yaml apiVersion: policy.open-cluster-management.io/v1 kind: Policy @@ -167,10 +273,96 @@ spec: type: Opaque metadata: name: hub-ca - namespace: imperative + namespace: golang-external-secrets data: hub-kube-root-ca.crt: '{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}' hub-openshift-service-ca.crt: '{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}' + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: imperative + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-openshift-gitops-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-openshift-gitops-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: openshift-gitops + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-factory-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-factory-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: mypattern-factory + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} --- # Source: acm/templates/policies/application-policies.yaml # TODO: Also create a GitOpsCluster.apps.open-cluster-management.io @@ -214,6 +406,8 @@ spec: path: common/clustergroup helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-factory.yaml" @@ -244,10 +438,18 @@ spec: value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - name: global.clusterPlatform value: aws - - name: clusterGroup.name - value: factory + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: + - name: global.privateRepo + value: - name: global.experimentalCapabilities value: + - name: clusterGroup.name + value: factory - name: clusterGroup.isHubCluster value: "false" destination: @@ -296,15 +498,6 @@ spec: include: - default object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT @@ -325,3 +518,216 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +# This policy depends on openshift-gitops-policy and the reason is that we need to be +# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance +# because the initcontainer references the trusted-ca-bundle and if it starts without the +# configmap being there we risk running an argo instances that won't trust public CAs +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: openshift-gitops-policy-argocd + annotations: + policy.open-cluster-management.io/standards: NIST-CSF + policy.open-cluster-management.io/categories: PR.DS Data Security + policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + dependencies: + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: openshift-gitops-policy + namespace: open-cluster-management + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: hub-argo-ca-openshift-gitops-policy + namespace: open-cluster-management + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: openshift-gitops-config-argocd + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + apiVersion: argoproj.io/v1beta1 + kind: ArgoCD + metadata: + name: openshift-gitops + namespace: openshift-gitops + spec: + applicationSet: + resources: + limits: + cpu: "2" + memory: 1Gi + requests: + cpu: 250m + memory: 512Mi + webhookServer: + ingress: + enabled: false + route: + enabled: false + controller: + processors: {} + resources: + limits: + cpu: "2" + memory: 2Gi + requests: + cpu: 250m + memory: 1Gi + sharding: {} + grafana: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + route: + enabled: false + ha: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + initialSSHKnownHosts: {} + monitoring: + enabled: false + notifications: + enabled: false + prometheus: + enabled: false + ingress: + enabled: false + route: + enabled: false + rbac: + defaultPolicy: "" + policy: |- + g, system:cluster-admins, role:admin + g, cluster-admins, role:admin + scopes: '[groups]' + redis: + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt + || true + image: registry.redhat.io/ubi9/ubi-minimal:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle + - emptyDir: {} + name: ca-bundles + resourceExclusions: |- + - apiGroups: + - tekton.dev + clusters: + - '*' + kinds: + - TaskRun + - PipelineRun + server: + autoscale: + enabled: false + grpc: + ingress: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 125m + memory: 128Mi + route: + enabled: true + service: + type: "" + sso: + dex: + openShiftOAuth: true + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + provider: dex + tls: + ca: {} diff --git a/tests/common-acm-medical-diagnosis-hub.expected.yaml b/tests/common-acm-medical-diagnosis-hub.expected.yaml index 8b50de7a..dffb9eb6 100644 --- a/tests/common-acm-medical-diagnosis-hub.expected.yaml +++ b/tests/common-acm-medical-diagnosis-hub.expected.yaml @@ -38,6 +38,38 @@ subjects: kind: Policy apiGroup: policy.open-cluster-management.io --- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-openshift-gitops-policy-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-openshift-gitops-policy-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-openshift-gitops-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-region-one-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-region-one-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-region-one-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- # Source: acm/templates/policies/application-policies.yaml apiVersion: policy.open-cluster-management.io/v1 kind: PlacementBinding @@ -70,6 +102,22 @@ subjects: kind: Policy apiGroup: policy.open-cluster-management.io --- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: openshift-gitops-placement-binding-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: openshift-gitops-placement-argocd + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: openshift-gitops-policy-argocd + kind: Policy + apiGroup: policy.open-cluster-management.io +--- # Source: acm/templates/policies/acm-hub-ca-policy.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule @@ -88,6 +136,42 @@ spec: values: - 'true' --- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-openshift-gitops-policy-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-region-one-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- # Source: acm/templates/policies/application-policies.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule @@ -127,6 +211,28 @@ spec: values: - 'true' --- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: openshift-gitops-placement-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: vendor + operator: In + values: + - OpenShift + - key: local-cluster + operator: NotIn + values: + - 'true' +--- # Source: acm/templates/policies/acm-hub-ca-policy.yaml apiVersion: policy.open-cluster-management.io/v1 kind: Policy @@ -158,10 +264,96 @@ spec: type: Opaque metadata: name: hub-ca - namespace: imperative + namespace: golang-external-secrets data: hub-kube-root-ca.crt: '{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}' hub-openshift-service-ca.crt: '{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}' + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: imperative + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-openshift-gitops-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-openshift-gitops-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: openshift-gitops + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-region-one-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-region-one-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: mypattern-region-one + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} --- # Source: acm/templates/policies/application-policies.yaml # TODO: Also create a GitOpsCluster.apps.open-cluster-management.io @@ -205,6 +397,8 @@ spec: path: common/clustergroup helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-region-one.yaml" @@ -235,10 +429,18 @@ spec: value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - name: global.clusterPlatform value: aws - - name: clusterGroup.name - value: region-one + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: + - name: global.privateRepo + value: - name: global.experimentalCapabilities value: + - name: clusterGroup.name + value: region-one - name: clusterGroup.isHubCluster value: "false" destination: @@ -287,15 +489,6 @@ spec: include: - default object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT @@ -316,3 +509,216 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +# This policy depends on openshift-gitops-policy and the reason is that we need to be +# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance +# because the initcontainer references the trusted-ca-bundle and if it starts without the +# configmap being there we risk running an argo instances that won't trust public CAs +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: openshift-gitops-policy-argocd + annotations: + policy.open-cluster-management.io/standards: NIST-CSF + policy.open-cluster-management.io/categories: PR.DS Data Security + policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + dependencies: + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: openshift-gitops-policy + namespace: open-cluster-management + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: hub-argo-ca-openshift-gitops-policy + namespace: open-cluster-management + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: openshift-gitops-config-argocd + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + apiVersion: argoproj.io/v1beta1 + kind: ArgoCD + metadata: + name: openshift-gitops + namespace: openshift-gitops + spec: + applicationSet: + resources: + limits: + cpu: "2" + memory: 1Gi + requests: + cpu: 250m + memory: 512Mi + webhookServer: + ingress: + enabled: false + route: + enabled: false + controller: + processors: {} + resources: + limits: + cpu: "2" + memory: 2Gi + requests: + cpu: 250m + memory: 1Gi + sharding: {} + grafana: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + route: + enabled: false + ha: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + initialSSHKnownHosts: {} + monitoring: + enabled: false + notifications: + enabled: false + prometheus: + enabled: false + ingress: + enabled: false + route: + enabled: false + rbac: + defaultPolicy: "" + policy: |- + g, system:cluster-admins, role:admin + g, cluster-admins, role:admin + scopes: '[groups]' + redis: + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt + || true + image: registry.redhat.io/ubi9/ubi-minimal:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle + - emptyDir: {} + name: ca-bundles + resourceExclusions: |- + - apiGroups: + - tekton.dev + clusters: + - '*' + kinds: + - TaskRun + - PipelineRun + server: + autoscale: + enabled: false + grpc: + ingress: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 125m + memory: 128Mi + route: + enabled: true + service: + type: "" + sso: + dex: + openShiftOAuth: true + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + provider: dex + tls: + ca: {} diff --git a/tests/common-acm-naked.expected.yaml b/tests/common-acm-naked.expected.yaml index 561fbd7b..39238f91 100644 --- a/tests/common-acm-naked.expected.yaml +++ b/tests/common-acm-naked.expected.yaml @@ -42,6 +42,22 @@ subjects: apiGroup: policy.open-cluster-management.io --- # Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: openshift-gitops-placement-binding-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: openshift-gitops-placement-argocd + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: openshift-gitops-policy-argocd + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule metadata: @@ -64,6 +80,28 @@ spec: - 'true' --- # Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: openshift-gitops-placement-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: vendor + operator: In + values: + - OpenShift + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml apiVersion: policy.open-cluster-management.io/v1 kind: Policy metadata: @@ -90,15 +128,6 @@ spec: include: - default object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT @@ -119,3 +148,216 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +# This policy depends on openshift-gitops-policy and the reason is that we need to be +# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance +# because the initcontainer references the trusted-ca-bundle and if it starts without the +# configmap being there we risk running an argo instances that won't trust public CAs +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: openshift-gitops-policy-argocd + annotations: + policy.open-cluster-management.io/standards: NIST-CSF + policy.open-cluster-management.io/categories: PR.DS Data Security + policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + dependencies: + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: openshift-gitops-policy + namespace: open-cluster-management + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: hub-argo-ca-openshift-gitops-policy + namespace: open-cluster-management + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: openshift-gitops-config-argocd + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + apiVersion: argoproj.io/v1beta1 + kind: ArgoCD + metadata: + name: openshift-gitops + namespace: openshift-gitops + spec: + applicationSet: + resources: + limits: + cpu: "2" + memory: 1Gi + requests: + cpu: 250m + memory: 512Mi + webhookServer: + ingress: + enabled: false + route: + enabled: false + controller: + processors: {} + resources: + limits: + cpu: "2" + memory: 2Gi + requests: + cpu: 250m + memory: 1Gi + sharding: {} + grafana: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + route: + enabled: false + ha: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + initialSSHKnownHosts: {} + monitoring: + enabled: false + notifications: + enabled: false + prometheus: + enabled: false + ingress: + enabled: false + route: + enabled: false + rbac: + defaultPolicy: "" + policy: |- + g, system:cluster-admins, role:admin + g, cluster-admins, role:admin + scopes: '[groups]' + redis: + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt + || true + image: registry.redhat.io/ubi9/ubi-minimal:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle + - emptyDir: {} + name: ca-bundles + resourceExclusions: |- + - apiGroups: + - tekton.dev + clusters: + - '*' + kinds: + - TaskRun + - PipelineRun + server: + autoscale: + enabled: false + grpc: + ingress: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 125m + memory: 128Mi + route: + enabled: true + service: + type: "" + sso: + dex: + openShiftOAuth: true + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + provider: dex + tls: + ca: {} diff --git a/tests/common-acm-normal.expected.yaml b/tests/common-acm-normal.expected.yaml index 66f1c590..1e2b1573 100644 --- a/tests/common-acm-normal.expected.yaml +++ b/tests/common-acm-normal.expected.yaml @@ -1,4 +1,16 @@ --- +# Source: acm/templates/provision/clusterdeployment.yaml +apiVersion: v1 +kind: Namespace +metadata: + name: aws-cd-one-w-pool-acm-provision-edge +--- +# Source: acm/templates/provision/clusterdeployment.yaml +apiVersion: v1 +kind: Namespace +metadata: + name: aws-cd-two-wo-pool-acm-provision-on-deploy +--- # Source: acm/templates/provision/secrets-common.yaml apiVersion: v1 kind: Secret @@ -6,7 +18,7 @@ metadata: name: aws-ap-acm-provision-edge-install-config data: # Base64 encoding of install-config yaml - install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXdzLWFwJyAKYmFzZURvbWFpbjogYmx1ZXByaW50cy5yaGVjb2VuZy5jb20KY29udHJvbFBsYW5lOgogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIG5hbWU6IGNvbnRyb2xQbGFuZQogIHJlcGxpY2FzOiAxCiAgcGxhdGZvcm06CiAgICBhd3M6CiAgICAgIHR5cGU6IG01LnhsYXJnZQpjb21wdXRlOgotIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIG5hbWU6ICd3b3JrZXInCiAgcmVwbGljYXM6IDAKbmV0d29ya2luZzoKICBjbHVzdGVyTmV0d29yazoKICAtIGNpZHI6IDEwLjEyOC4wLjAvMTQKICAgIGhvc3RQcmVmaXg6IDIzCiAgbWFjaGluZU5ldHdvcms6CiAgLSBjaWRyOiAxMC4wLjAuMC8xNgogIG5ldHdvcmtUeXBlOiBPVk5LdWJlcm5ldGVzCiAgc2VydmljZU5ldHdvcms6CiAgLSAxNzIuMzAuMC4wLzE2CnBsYXRmb3JtOgogIGF3czoKICAgIHJlZ2lvbjogYXAtc291dGhlYXN0LTIKcHVsbFNlY3JldDogIiIgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cwpzc2hLZXk6ICIiICAgICAjIHNraXAsIGhpdmUgd2lsbCBpbmplY3QgYmFzZWQgb24gaXQncyBzZWNyZXRz + install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXdzLWFwJyAKYmFzZURvbWFpbjogYmx1ZXByaW50cy5yaGVjb2VuZy5jb20KY29udHJvbFBsYW5lOgogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIG5hbWU6IGNvbnRyb2xQbGFuZQogIHJlcGxpY2FzOiAxCiAgcGxhdGZvcm06CiAgICBhd3M6CiAgICAgIHR5cGU6IG01LnhsYXJnZQpjb21wdXRlOgotIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIG5hbWU6ICd3b3JrZXInCiAgcmVwbGljYXM6IDAKbmV0d29ya2luZzoKICBjbHVzdGVyTmV0d29yazoKICAtIGNpZHI6IDEwLjEyOC4wLjAvMTQKICAgIGhvc3RQcmVmaXg6IDIzCiAgbWFjaGluZU5ldHdvcms6CiAgLSBjaWRyOiAxMC4wLjAuMC8xNgogIG5ldHdvcmtUeXBlOiBPVk5LdWJlcm5ldGVzCiAgc2VydmljZU5ldHdvcms6CiAgLSAxNzIuMzAuMC4wLzE2CnBsYXRmb3JtOgogIGF3czoKICAgIHJlZ2lvbjogYXAtc291dGhlYXN0LTIKcHVsbFNlY3JldDogIiIgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cwpzc2hLZXk6ICIiICAgICAjIHNraXAsIGhpdmUgd2lsbCBpbmplY3QgYmFzZWQgb24gaXQncyBzZWNyZXRz type: Opaque --- # Source: acm/templates/provision/secrets-common.yaml @@ -16,7 +28,29 @@ metadata: name: azure-us-acm-provision-edge-install-config data: # Base64 encoding of install-config yaml - install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXp1cmUtdXMnIApiYXNlRG9tYWluOiBibHVlcHJpbnRzLnJoZWNvZW5nLmNvbQpjb250cm9sUGxhbmU6CiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgbmFtZTogY29udHJvbFBsYW5lCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF6dXJlOgogICAgICB0eXBlOiBTdGFuZGFyZF9EOHNfdjMKY29tcHV0ZToKLSBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBuYW1lOiAnd29ya2VyJwogIHJlcGxpY2FzOiAzCiAgcGxhdGZvcm06CiAgICBhenVyZToKICAgICAgdHlwZTogU3RhbmRhcmRfRDhzX3YzCm5ldHdvcmtpbmc6CiAgY2x1c3Rlck5ldHdvcms6CiAgLSBjaWRyOiAxMC4xMjguMC4wLzE0CiAgICBob3N0UHJlZml4OiAyMwogIG1hY2hpbmVOZXR3b3JrOgogIC0gY2lkcjogMTAuMC4wLjAvMTYKICBuZXR3b3JrVHlwZTogT1ZOS3ViZXJuZXRlcwogIHNlcnZpY2VOZXR3b3JrOgogIC0gMTcyLjMwLjAuMC8xNgpwbGF0Zm9ybToKICBhenVyZToKICAgIGJhc2VEb21haW5SZXNvdXJjZUdyb3VwTmFtZTogZG9qby1kbnMtem9uZXMKICAgIHJlZ2lvbjogZWFzdHVzCnB1bGxTZWNyZXQ6ICIiICMgc2tpcCwgaGl2ZSB3aWxsIGluamVjdCBiYXNlZCBvbiBpdCdzIHNlY3JldHMKc3NoS2V5OiAiIiAgICAgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cw== + install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXp1cmUtdXMnIApiYXNlRG9tYWluOiBibHVlcHJpbnRzLnJoZWNvZW5nLmNvbQpjb250cm9sUGxhbmU6CiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgbmFtZTogY29udHJvbFBsYW5lCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF6dXJlOgogICAgICB0eXBlOiBTdGFuZGFyZF9EOHNfdjMKY29tcHV0ZToKLSBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBuYW1lOiAnd29ya2VyJwogIHJlcGxpY2FzOiAzCiAgcGxhdGZvcm06CiAgICBhenVyZToKICAgICAgdHlwZTogU3RhbmRhcmRfRDhzX3YzCm5ldHdvcmtpbmc6CiAgY2x1c3Rlck5ldHdvcms6CiAgLSBjaWRyOiAxMC4xMjguMC4wLzE0CiAgICBob3N0UHJlZml4OiAyMwogIG1hY2hpbmVOZXR3b3JrOgogIC0gY2lkcjogMTAuMC4wLjAvMTYKICBuZXR3b3JrVHlwZTogT1ZOS3ViZXJuZXRlcwogIHNlcnZpY2VOZXR3b3JrOgogIC0gMTcyLjMwLjAuMC8xNgpwbGF0Zm9ybToKICBhenVyZToKICAgIGJhc2VEb21haW5SZXNvdXJjZUdyb3VwTmFtZTogZG9qby1kbnMtem9uZXMKICAgIHJlZ2lvbjogZWFzdHVzCnB1bGxTZWNyZXQ6ICIiICMgc2tpcCwgaGl2ZSB3aWxsIGluamVjdCBiYXNlZCBvbiBpdCdzIHNlY3JldHMKc3NoS2V5OiAiIiAgICAgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cw== +type: Opaque +--- +# Source: acm/templates/provision/secrets-common.yaml +apiVersion: v1 +kind: Secret +metadata: + name: aws-cd-one-w-pool-acm-provision-edge-install-config + namespace: aws-cd-one-w-pool-acm-provision-edge +data: + # Base64 encoding of install-config yaml + install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXdzLWNkLW9uZS13LXBvb2wnIApiYXNlRG9tYWluOiBibHVlcHJpbnRzLnJoZWNvZW5nLmNvbQpjb250cm9sUGxhbmU6CiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgbmFtZTogY29udHJvbFBsYW5lCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF3czoKICAgICAgdHlwZTogbTUueGxhcmdlCmNvbXB1dGU6Ci0gaHlwZXJ0aHJlYWRpbmc6IEVuYWJsZWQKICBhcmNoaXRlY3R1cmU6IGFtZDY0CiAgbmFtZTogJ3dvcmtlcicKICByZXBsaWNhczogMwogIHBsYXRmb3JtOgogICAgYXdzOgogICAgICB0eXBlOiBtNS54bGFyZ2UKbmV0d29ya2luZzoKICBjbHVzdGVyTmV0d29yazoKICAtIGNpZHI6IDEwLjEyOC4wLjAvMTQKICAgIGhvc3RQcmVmaXg6IDIzCiAgbWFjaGluZU5ldHdvcms6CiAgLSBjaWRyOiAxMC4wLjAuMC8xNgogIG5ldHdvcmtUeXBlOiBPVk5LdWJlcm5ldGVzCiAgc2VydmljZU5ldHdvcms6CiAgLSAxNzIuMzAuMC4wLzE2CnBsYXRmb3JtOgogIGF3czoKICAgIHJlZ2lvbjogYXAtc291dGhlYXN0LTEKcHVsbFNlY3JldDogIiIgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cwpzc2hLZXk6ICIiICAgICAjIHNraXAsIGhpdmUgd2lsbCBpbmplY3QgYmFzZWQgb24gaXQncyBzZWNyZXRz +type: Opaque +--- +# Source: acm/templates/provision/secrets-common.yaml +apiVersion: v1 +kind: Secret +metadata: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-install-config + namespace: aws-cd-two-wo-pool-acm-provision-on-deploy +data: + # Base64 encoding of install-config yaml + install-config.yaml: CgphcGlWZXJzaW9uOiB2MQptZXRhZGF0YToKICBuYW1lOiAnYXdzLWNkLXR3by13by1wb29sJyAKYmFzZURvbWFpbjogYmx1ZXByaW50cy5yaGVjb2VuZy5jb20KY29udHJvbFBsYW5lOgogIGFyY2hpdGVjdHVyZTogYW1kNjQKICBoeXBlcnRocmVhZGluZzogRW5hYmxlZAogIG5hbWU6IGNvbnRyb2xQbGFuZQogIHJlcGxpY2FzOiAzCiAgcGxhdGZvcm06CiAgICBhd3M6CiAgICAgIHR5cGU6IG01LnhsYXJnZQpjb21wdXRlOgotIGh5cGVydGhyZWFkaW5nOiBFbmFibGVkCiAgYXJjaGl0ZWN0dXJlOiBhbWQ2NAogIG5hbWU6ICd3b3JrZXInCiAgcmVwbGljYXM6IDMKICBwbGF0Zm9ybToKICAgIGF3czoKICAgICAgdHlwZTogbTUueGxhcmdlCm5ldHdvcmtpbmc6CiAgY2x1c3Rlck5ldHdvcms6CiAgLSBjaWRyOiAxMC4xMjguMC4wLzE0CiAgICBob3N0UHJlZml4OiAyMwogIG1hY2hpbmVOZXR3b3JrOgogIC0gY2lkcjogMTAuMC4wLjAvMTYKICBuZXR3b3JrVHlwZTogT1ZOS3ViZXJuZXRlcwogIHNlcnZpY2VOZXR3b3JrOgogIC0gMTcyLjMwLjAuMC8xNgpwbGF0Zm9ybToKICBhd3M6CiAgICByZWdpb246IGFwLXNvdXRoZWFzdC0zCnB1bGxTZWNyZXQ6ICIiICMgc2tpcCwgaGl2ZSB3aWxsIGluamVjdCBiYXNlZCBvbiBpdCdzIHNlY3JldHMKc3NoS2V5OiAiIiAgICAgIyBza2lwLCBoaXZlIHdpbGwgaW5qZWN0IGJhc2VkIG9uIGl0J3Mgc2VjcmV0cw== type: Opaque --- # Source: acm/templates/policies/acm-hub-ca-policy.yaml @@ -61,6 +95,64 @@ metadata: spec: clusterPoolName: azure-us-acm-provision-edge --- +# Source: acm/templates/provision/clusterdeployment.yaml +apiVersion: hive.openshift.io/v1 +kind: ClusterDeployment +metadata: + name: aws-cd-one-w-pool-acm-provision-edge + namespace: aws-cd-one-w-pool-acm-provision-edge + labels: + vendor: OpenShift + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + baseDomain: blueprints.rhecoeng.com + clusterName: aws-cd-one-w-pool-acm-provision-edge + installAttemptsLimit: 1 + platform: + aws: + credentialsSecretRef: + name: aws-cd-one-w-pool-acm-provision-edge-creds + region: ap-southeast-1 + provisioning: + installConfigSecretRef: + name: aws-cd-one-w-pool-acm-provision-edge-install-config + sshPrivateKeySecretRef: + name: aws-cd-one-w-pool-acm-provision-edge-ssh-private-key + imageSetRef: + name: img4.10.18-multi-appsub + pullSecretRef: + name: aws-cd-one-w-pool-acm-provision-edge-pull-secret +--- +# Source: acm/templates/provision/clusterdeployment.yaml +apiVersion: hive.openshift.io/v1 +kind: ClusterDeployment +metadata: + name: aws-cd-two-wo-pool-acm-provision-on-deploy + namespace: aws-cd-two-wo-pool-acm-provision-on-deploy + labels: + vendor: OpenShift + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + baseDomain: blueprints.rhecoeng.com + clusterName: aws-cd-two-wo-pool-acm-provision-on-deploy + installAttemptsLimit: 1 + platform: + aws: + credentialsSecretRef: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-creds + region: ap-southeast-3 + provisioning: + installConfigSecretRef: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-install-config + sshPrivateKeySecretRef: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-ssh-private-key + imageSetRef: + name: img4.10.18-multi-appsub + pullSecretRef: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-pull-secret +--- # Source: acm/templates/provision/clusterpool.yaml apiVersion: hive.openshift.io/v1 kind: ClusterPool @@ -79,7 +171,7 @@ spec: runningCount: 0 baseDomain: blueprints.rhecoeng.com installConfigSecretTemplateRef: - name: aws-ap-acm-provision-edge-install-config + name: aws-ap-acm-provision-edge-install-config imageSetRef: name: img4.10.18-multi-appsub pullSecretRef: @@ -109,7 +201,7 @@ spec: runningCount: 2 baseDomain: blueprints.rhecoeng.com installConfigSecretTemplateRef: - name: azure-us-acm-provision-edge-install-config + name: azure-us-acm-provision-edge-install-config imageSetRef: name: img4.10.18-multi-appsub pullSecretRef: @@ -147,7 +239,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-ap-acm-provision-edge-infra-creds -spec: +spec: data: - secretKey: openshiftPullSecret remoteRef: @@ -170,7 +262,7 @@ spec: key: secret/data/hub/privatekey property: content refreshInterval: 24h0m0s - secretStoreRef: + secretStoreRef: name: vault-backend kind: ClusterSecretStore target: @@ -199,6 +291,166 @@ spec: noProxy: "" additionalTrustBundle: "" --- +# Source: acm/templates/provision/secrets-aws.yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-cd-one-w-pool-acm-provision-edge-creds + namespace: aws-cd-one-w-pool-acm-provision-edge +spec: + dataFrom: + - extract: + # Expects entries called: aws_access_key_id and aws_secret_access_key + key: secret/data/hub/aws + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-one-w-pool-acm-provision-edge-creds + creationPolicy: Owner + template: + type: Opaque +--- +# Source: acm/templates/provision/secrets-aws.yaml +# For use when manually creating clusters with ACM +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-cd-one-w-pool-acm-provision-edge-infra-creds + namespace: aws-cd-one-w-pool-acm-provision-edge +spec: + data: + - secretKey: openshiftPullSecret + remoteRef: + key: secret/data/hub/openshiftPullSecret + property: content + - secretKey: awsKeyId + remoteRef: + key: secret/data/hub/aws + property: aws_access_key_id + - secretKey: awsAccessKey + remoteRef: + key: secret/data/hub/aws + property: aws_secret_access_key + - secretKey: sshPublicKey + remoteRef: + key: secret/data/hub/publickey + property: content + - secretKey: sshPrivateKey + remoteRef: + key: secret/data/hub/privatekey + property: content + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-one-w-pool-acm-provision-edge-infra-creds + creationPolicy: Owner + template: + type: Opaque + metadata: + labels: + cluster.open-cluster-management.io/credentials: "" + cluster.open-cluster-management.io/type: aws + data: + baseDomain: "blueprints.rhecoeng.com" + pullSecret: |- + {{ .openshiftPullSecret | toString }} + aws_access_key_id: |- + {{ .awsKeyId | toString }} + aws_secret_access_key: |- + {{ .awsAccessKey | toString }} + ssh-privatekey: |- + {{ .sshPrivateKey | toString }} + ssh-publickey: |- + {{ .sshPublicKey | toString }} + httpProxy: "" + httpsProxy: "" + noProxy: "" + additionalTrustBundle: "" +--- +# Source: acm/templates/provision/secrets-aws.yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-creds + namespace: aws-cd-two-wo-pool-acm-provision-on-deploy +spec: + dataFrom: + - extract: + # Expects entries called: aws_access_key_id and aws_secret_access_key + key: secret/data/hub/aws + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-creds + creationPolicy: Owner + template: + type: Opaque +--- +# Source: acm/templates/provision/secrets-aws.yaml +# For use when manually creating clusters with ACM +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-infra-creds + namespace: aws-cd-two-wo-pool-acm-provision-on-deploy +spec: + data: + - secretKey: openshiftPullSecret + remoteRef: + key: secret/data/hub/openshiftPullSecret + property: content + - secretKey: awsKeyId + remoteRef: + key: secret/data/hub/aws + property: aws_access_key_id + - secretKey: awsAccessKey + remoteRef: + key: secret/data/hub/aws + property: aws_secret_access_key + - secretKey: sshPublicKey + remoteRef: + key: secret/data/hub/publickey + property: content + - secretKey: sshPrivateKey + remoteRef: + key: secret/data/hub/privatekey + property: content + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-infra-creds + creationPolicy: Owner + template: + type: Opaque + metadata: + labels: + cluster.open-cluster-management.io/credentials: "" + cluster.open-cluster-management.io/type: aws + data: + baseDomain: "blueprints.rhecoeng.com" + pullSecret: |- + {{ .openshiftPullSecret | toString }} + aws_access_key_id: |- + {{ .awsKeyId | toString }} + aws_secret_access_key: |- + {{ .awsAccessKey | toString }} + ssh-privatekey: |- + {{ .sshPrivateKey | toString }} + ssh-publickey: |- + {{ .sshPublicKey | toString }} + httpProxy: "" + httpsProxy: "" + noProxy: "" + additionalTrustBundle: "" +--- # Source: acm/templates/provision/secrets-azure.yaml apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret @@ -229,7 +481,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: azure-us-acm-provision-edge-infra-creds -spec: +spec: data: - secretKey: openshiftPullSecret remoteRef: @@ -248,7 +500,7 @@ spec: key: secret/data/hub/azureOsServicePrincipal property: content refreshInterval: 24h0m0s - secretStoreRef: + secretStoreRef: name: vault-backend kind: ClusterSecretStore target: @@ -282,7 +534,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: aws-ap-acm-provision-edge-pull-secret -spec: +spec: data: - secretKey: openshiftPullSecret remoteRef: @@ -330,7 +582,7 @@ apiVersion: external-secrets.io/v1beta1 kind: ExternalSecret metadata: name: azure-us-acm-provision-edge-pull-secret -spec: +spec: data: - secretKey: openshiftPullSecret remoteRef: @@ -373,44 +625,240 @@ spec: ssh-privatekey: |- {{ .sshPrivateKey | toString }} --- -# Source: acm/templates/provision/clusterpool.yaml -apiVersion: cluster.open-cluster-management.io/v1beta1 -kind: ManagedClusterSet +# Source: acm/templates/provision/secrets-common.yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret metadata: - annotations: - cluster.open-cluster-management.io/submariner-broker-ns: acm-provision-edge-broker - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true - name: acm-provision-edge + name: aws-cd-one-w-pool-acm-provision-edge-pull-secret + namespace: aws-cd-one-w-pool-acm-provision-edge spec: - clusterSelector: - selectorType: LegacyClusterSetLabel ---- -# Source: acm/templates/multiclusterhub.yaml -apiVersion: operator.open-cluster-management.io/v1 -kind: MultiClusterHub -metadata: - name: multiclusterhub - namespace: open-cluster-management - annotations: - argocd.argoproj.io/sync-wave: "-1" - installer.open-cluster-management.io/mce-subscription-spec: '{"source": "redhat-operators" }' -spec: {} + data: + - secretKey: openshiftPullSecret + remoteRef: + key: secret/data/hub/openshiftPullSecret + property: content + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-one-w-pool-acm-provision-edge-pull-secret + creationPolicy: Owner + template: + type: kubernetes.io/dockerconfigjson + data: + .dockerconfigjson: |- + {{ .openshiftPullSecret | toString }} --- -# Source: acm/templates/policies/acm-hub-ca-policy.yaml -apiVersion: policy.open-cluster-management.io/v1 -kind: PlacementBinding +# Source: acm/templates/provision/secrets-common.yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret metadata: - name: acm-hub-ca-policy-placement-binding - annotations: - argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true -placementRef: - name: acm-hub-ca-policy-placement - kind: PlacementRule - apiGroup: apps.open-cluster-management.io -subjects: - - name: acm-hub-ca-policy - kind: Policy - apiGroup: policy.open-cluster-management.io + name: aws-cd-one-w-pool-acm-provision-edge-ssh-private-key + namespace: aws-cd-one-w-pool-acm-provision-edge +spec: + data: + - secretKey: sshPrivateKey + remoteRef: + key: secret/data/hub/privatekey + property: content + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-one-w-pool-acm-provision-edge-ssh-private-key + creationPolicy: Owner + template: + type: Opaque + data: + ssh-privatekey: |- + {{ .sshPrivateKey | toString }} +--- +# Source: acm/templates/provision/secrets-common.yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-pull-secret + namespace: aws-cd-two-wo-pool-acm-provision-on-deploy +spec: + data: + - secretKey: openshiftPullSecret + remoteRef: + key: secret/data/hub/openshiftPullSecret + property: content + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-pull-secret + creationPolicy: Owner + template: + type: kubernetes.io/dockerconfigjson + data: + .dockerconfigjson: |- + {{ .openshiftPullSecret | toString }} +--- +# Source: acm/templates/provision/secrets-common.yaml +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-ssh-private-key + namespace: aws-cd-two-wo-pool-acm-provision-on-deploy +spec: + data: + - secretKey: sshPrivateKey + remoteRef: + key: secret/data/hub/privatekey + property: content + refreshInterval: 24h0m0s + secretStoreRef: + name: vault-backend + kind: ClusterSecretStore + target: + name: aws-cd-two-wo-pool-acm-provision-on-deploy-ssh-private-key + creationPolicy: Owner + template: + type: Opaque + data: + ssh-privatekey: |- + {{ .sshPrivateKey | toString }} +--- +# Source: acm/templates/provision/clusterdeployment.yaml +apiVersion: cluster.open-cluster-management.io/v1 +kind: ManagedCluster +metadata: + labels: + cluster.open-cluster-management.io/clusterset: acm-provision-edge + clusterGroup: region + name: aws-cd-one-w-pool-acm-provision-edge + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + hubAcceptsClient: true +--- +# Source: acm/templates/provision/clusterdeployment.yaml +apiVersion: cluster.open-cluster-management.io/v1 +kind: ManagedCluster +metadata: + labels: + cluster.open-cluster-management.io/clusterset: acm-provision-on-deploy + clusterGroup: acm-provision-on-deploy + name: aws-cd-two-wo-pool-acm-provision-on-deploy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + hubAcceptsClient: true +--- +# Source: acm/templates/provision/managedclusterset.yaml +apiVersion: cluster.open-cluster-management.io/v1beta2 +kind: ManagedClusterSet +metadata: + annotations: + cluster.open-cluster-management.io/submariner-broker-ns: acm-provision-edge-broker + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + name: acm-provision-edge +--- +# Source: acm/templates/provision/managedclusterset.yaml +apiVersion: cluster.open-cluster-management.io/v1beta2 +kind: ManagedClusterSet +metadata: + annotations: + cluster.open-cluster-management.io/submariner-broker-ns: acm-provision-on-deploy-broker + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + name: acm-provision-on-deploy +--- +# Source: acm/templates/multiclusterhub.yaml +apiVersion: operator.open-cluster-management.io/v1 +kind: MultiClusterHub +metadata: + name: multiclusterhub + namespace: open-cluster-management + annotations: + argocd.argoproj.io/sync-wave: "-1" + installer.open-cluster-management.io/mce-subscription-spec: '{"source": "redhat-operators" }' +spec: {} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: acm-hub-ca-policy-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: acm-hub-ca-policy-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: acm-hub-ca-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-openshift-gitops-policy-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-openshift-gitops-policy-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-openshift-gitops-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-acm-edge-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-acm-edge-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-acm-edge-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-acm-provision-edge-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-acm-provision-edge-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-acm-provision-edge-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: hub-argo-ca-acm-provision-on-deploy-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: hub-argo-ca-acm-provision-on-deploy-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: hub-argo-ca-acm-provision-on-deploy-policy + kind: Policy + apiGroup: policy.open-cluster-management.io --- # Source: acm/templates/policies/application-policies.yaml apiVersion: policy.open-cluster-management.io/v1 @@ -444,6 +892,22 @@ subjects: kind: Policy apiGroup: policy.open-cluster-management.io --- +# Source: acm/templates/policies/application-policies.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: acm-provision-on-deploy-placement-binding + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: acm-provision-on-deploy-placement + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: acm-provision-on-deploy-clustergroup-policy + kind: Policy + apiGroup: policy.open-cluster-management.io +--- # Source: acm/templates/policies/ocp-gitops-policy.yaml apiVersion: policy.open-cluster-management.io/v1 kind: PlacementBinding @@ -460,6 +924,22 @@ subjects: kind: Policy apiGroup: policy.open-cluster-management.io --- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: PlacementBinding +metadata: + name: openshift-gitops-placement-binding-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +placementRef: + name: openshift-gitops-placement-argocd + kind: PlacementRule + apiGroup: apps.open-cluster-management.io +subjects: + - name: openshift-gitops-policy-argocd + kind: Policy + apiGroup: policy.open-cluster-management.io +--- # Source: acm/templates/policies/acm-hub-ca-policy.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule @@ -478,6 +958,78 @@ spec: values: - 'true' --- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-openshift-gitops-policy-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-acm-edge-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-acm-provision-edge-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: hub-argo-ca-acm-provision-on-deploy-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: local-cluster + operator: NotIn + values: + - 'true' +--- # Source: acm/templates/policies/application-policies.yaml apiVersion: apps.open-cluster-management.io/v1 kind: PlacementRule @@ -493,48 +1045,244 @@ spec: matchLabels: clusterGroup: acm-region --- -# Source: acm/templates/policies/application-policies.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule +# Source: acm/templates/policies/application-policies.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: acm-provision-edge-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchLabels: + clusterGroup: region +--- +# Source: acm/templates/policies/application-policies.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: acm-provision-on-deploy-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchLabels: + clusterGroup: acm-provision-on-deploy +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: openshift-gitops-placement + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: vendor + operator: In + values: + - OpenShift + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +apiVersion: apps.open-cluster-management.io/v1 +kind: PlacementRule +metadata: + name: openshift-gitops-placement-argocd + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true +spec: + clusterConditions: + - status: 'True' + type: ManagedClusterConditionAvailable + clusterSelector: + matchExpressions: + - key: vendor + operator: In + values: + - OpenShift + - key: local-cluster + operator: NotIn + values: + - 'true' +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: acm-hub-ca-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: acm-hub-ca-config-policy + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: Secret + apiVersion: v1 + type: Opaque + metadata: + name: hub-ca + namespace: golang-external-secrets + data: + hub-kube-root-ca.crt: '{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}' + hub-openshift-service-ca.crt: '{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}' + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: imperative + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: hub-argo-ca-openshift-gitops-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-openshift-gitops-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: openshift-gitops + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} +--- +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy metadata: - name: acm-provision-edge-placement + name: hub-argo-ca-acm-edge-policy annotations: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchLabels: - clusterGroup: region + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-acm-edge-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: mypattern-acm-edge + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} --- -# Source: acm/templates/policies/ocp-gitops-policy.yaml -apiVersion: apps.open-cluster-management.io/v1 -kind: PlacementRule +# Source: acm/templates/policies/acm-hub-ca-policy.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy metadata: - name: openshift-gitops-placement + name: hub-argo-ca-acm-provision-edge-policy annotations: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous spec: - clusterConditions: - - status: 'True' - type: ManagedClusterConditionAvailable - clusterSelector: - matchExpressions: - - key: vendor - operator: In - values: - - OpenShift - - key: local-cluster - operator: NotIn - values: - - 'true' + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: hub-argo-ca-acm-provision-edge-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-hub-bundle + namespace: mypattern-acm-provision-edge + data: + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} --- # Source: acm/templates/policies/acm-hub-ca-policy.yaml apiVersion: policy.open-cluster-management.io/v1 kind: Policy metadata: - name: acm-hub-ca-policy + name: hub-argo-ca-acm-provision-on-deploy-policy annotations: argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true argocd.argoproj.io/compare-options: IgnoreExtraneous @@ -546,7 +1294,7 @@ spec: apiVersion: policy.open-cluster-management.io/v1 kind: ConfigurationPolicy metadata: - name: acm-hub-ca-config-policy + name: hub-argo-ca-acm-provision-on-deploy-config spec: remediationAction: enforce severity: medium @@ -556,15 +1304,16 @@ spec: object-templates: - complianceType: mustonlyhave objectDefinition: - kind: Secret + kind: ConfigMap apiVersion: v1 - type: Opaque metadata: - name: hub-ca - namespace: imperative + name: trusted-hub-bundle + namespace: mypattern-acm-provision-on-deploy data: - hub-kube-root-ca.crt: '{{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | base64enc hub}}' - hub-openshift-service-ca.crt: '{{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | base64enc hub}}' + hub-kube-root-ca.crt: | + {{hub fromConfigMap "" "kube-root-ca.crt" "ca.crt" | autoindent hub}} + hub-openshift-service-ca.crt: | + {{hub fromConfigMap "" "openshift-service-ca.crt" "service-ca.crt" | autoindent hub}} --- # Source: acm/templates/policies/application-policies.yaml # TODO: Also create a GitOpsCluster.apps.open-cluster-management.io @@ -608,6 +1357,8 @@ spec: path: common/clustergroup helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-acm-edge.yaml" @@ -638,10 +1389,18 @@ spec: value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - name: global.clusterPlatform value: aws - - name: clusterGroup.name - value: acm-edge + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: + - name: global.privateRepo + value: - name: global.experimentalCapabilities value: + - name: clusterGroup.name + value: acm-edge - name: clusterGroup.isHubCluster value: "false" destination: @@ -704,6 +1463,8 @@ spec: path: common/clustergroup helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-acm-provision-edge.yaml" @@ -734,10 +1495,18 @@ spec: value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' - name: global.clusterPlatform value: aws - - name: clusterGroup.name - value: acm-provision-edge + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: + - name: global.privateRepo + value: - name: global.experimentalCapabilities value: + - name: clusterGroup.name + value: acm-provision-edge - name: clusterGroup.isHubCluster value: "false" destination: @@ -759,6 +1528,110 @@ spec: jsonPointers: - /status --- +# Source: acm/templates/policies/application-policies.yaml +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: acm-provision-on-deploy-clustergroup-policy + annotations: + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: acm-provision-on-deploy-clustergroup-config + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + apiVersion: argoproj.io/v1alpha1 + kind: Application + metadata: + name: mypattern-acm-provision-on-deploy + namespace: openshift-gitops + finalizers: + - resources-finalizer.argocd.argoproj.io/foreground + spec: + project: default + source: + repoURL: https://github.com/pattern-clone/mypattern + targetRevision: main + path: common/clustergroup + helm: + ignoreMissingValueFiles: true + values: | + extraParametersNested: + valueFiles: + - "/values-global.yaml" + - "/values-acm-provision-on-deploy.yaml" + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + - '/values-{{ (lookup "config.openshift.io/v1" "Infrastructure" "" "cluster").spec.platformSpec.type }}-acm-provision-on-deploy.yaml' + # We cannot use $.Values.global.clusterVersion because that gets resolved to the + # hub's cluster version, whereas we want to include the spoke cluster version + - '/values-{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}.yaml' + parameters: + - name: global.repoURL + value: https://github.com/pattern-clone/mypattern + - name: global.targetRevision + value: main + - name: global.namespace + value: $ARGOCD_APP_NAMESPACE + - name: global.pattern + value: mypattern + - name: global.hubClusterDomain + value: apps.hub.example.com + - name: global.localClusterDomain + value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain }}' + - name: global.clusterDomain + value: '{{ (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain | replace "apps." "" }}' + - name: global.clusterVersion + value: '{{ printf "%d.%d" ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Major) ((semver (index (lookup "config.openshift.io/v1" "ClusterVersion" "" "version").status.history 0).version).Minor) }}' + - name: global.localClusterName + value: '{{ (split "." (lookup "config.openshift.io/v1" "Ingress" "" "cluster").spec.domain)._1 }}' + - name: global.clusterPlatform + value: aws + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: + - name: global.privateRepo + value: + - name: global.experimentalCapabilities + value: + - name: clusterGroup.name + value: acm-provision-on-deploy + destination: + server: https://kubernetes.default.svc + namespace: mypattern-acm-provision-on-deploy + syncPolicy: + automated: + prune: false + selfHeal: true + retry: + limit: 20 + ignoreDifferences: + - group: apps + kind: Deployment + jsonPointers: + - /spec/replicas + - group: route.openshift.io + kind: Route + jsonPointers: + - /status +--- # Source: acm/templates/policies/ocp-gitops-policy.yaml apiVersion: policy.open-cluster-management.io/v1 kind: Policy @@ -786,15 +1659,6 @@ spec: include: - default object-templates: - - complianceType: mustonlyhave - objectDefinition: - kind: ConfigMap - apiVersion: v1 - metadata: - name: trusted-ca-bundle - namespace: openshift-gitops - labels: - config.openshift.io/inject-trusted-cabundle: 'true' - complianceType: mustonlyhave objectDefinition: # This is an auto-generated file. DO NOT EDIT @@ -815,3 +1679,216 @@ spec: env: - name: ARGOCD_CLUSTER_CONFIG_NAMESPACES value: "*" + - complianceType: mustonlyhave + objectDefinition: + kind: ConfigMap + apiVersion: v1 + metadata: + name: trusted-ca-bundle + namespace: openshift-gitops + labels: + config.openshift.io/inject-trusted-cabundle: 'true' +--- +# Source: acm/templates/policies/ocp-gitops-policy.yaml +# This policy depends on openshift-gitops-policy and the reason is that we need to be +# certain that the trusted-ca-bundle exists before spawning the clusterwide argocd instance +# because the initcontainer references the trusted-ca-bundle and if it starts without the +# configmap being there we risk running an argo instances that won't trust public CAs +apiVersion: policy.open-cluster-management.io/v1 +kind: Policy +metadata: + name: openshift-gitops-policy-argocd + annotations: + policy.open-cluster-management.io/standards: NIST-CSF + policy.open-cluster-management.io/categories: PR.DS Data Security + policy.open-cluster-management.io/controls: PR.DS-1 Data-at-rest + argocd.argoproj.io/sync-options: SkipDryRunOnMissingResource=true + argocd.argoproj.io/compare-options: IgnoreExtraneous +spec: + remediationAction: enforce + disabled: false + dependencies: + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: openshift-gitops-policy + namespace: open-cluster-management + - apiVersion: policy.open-cluster-management.io/v1 + compliance: Compliant + kind: Policy + name: hub-argo-ca-openshift-gitops-policy + namespace: open-cluster-management + policy-templates: + - objectDefinition: + apiVersion: policy.open-cluster-management.io/v1 + kind: ConfigurationPolicy + metadata: + name: openshift-gitops-config-argocd + spec: + remediationAction: enforce + severity: medium + namespaceSelector: + include: + - default + object-templates: + - complianceType: mustonlyhave + objectDefinition: + apiVersion: argoproj.io/v1beta1 + kind: ArgoCD + metadata: + name: openshift-gitops + namespace: openshift-gitops + spec: + applicationSet: + resources: + limits: + cpu: "2" + memory: 1Gi + requests: + cpu: 250m + memory: 512Mi + webhookServer: + ingress: + enabled: false + route: + enabled: false + controller: + processors: {} + resources: + limits: + cpu: "2" + memory: 2Gi + requests: + cpu: 250m + memory: 1Gi + sharding: {} + grafana: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + route: + enabled: false + ha: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + initialSSHKnownHosts: {} + monitoring: + enabled: false + notifications: + enabled: false + prometheus: + enabled: false + ingress: + enabled: false + route: + enabled: false + rbac: + defaultPolicy: "" + policy: |- + g, system:cluster-admins, role:admin + g, cluster-admins, role:admin + scopes: '[groups]' + redis: + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt + || true + image: registry.redhat.io/ubi9/ubi-minimal:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle + - emptyDir: {} + name: ca-bundles + resourceExclusions: |- + - apiGroups: + - tekton.dev + clusters: + - '*' + kinds: + - TaskRun + - PipelineRun + server: + autoscale: + enabled: false + grpc: + ingress: + enabled: false + ingress: + enabled: false + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 125m + memory: 128Mi + route: + enabled: true + service: + type: "" + sso: + dex: + openShiftOAuth: true + resources: + limits: + cpu: 500m + memory: 256Mi + requests: + cpu: 250m + memory: 128Mi + provider: dex + tls: + ca: {} diff --git a/tests/common-clustergroup-industrial-edge-factory.expected.yaml b/tests/common-clustergroup-industrial-edge-factory.expected.yaml index e681e11b..21110d8b 100644 --- a/tests/common-clustergroup-industrial-edge-factory.expected.yaml +++ b/tests/common-clustergroup-industrial-edge-factory.expected.yaml @@ -64,6 +64,13 @@ metadata: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/imperative/configmap.yaml apiVersion: v1 kind: ConfigMap @@ -114,8 +121,38 @@ data: --set clusterGroup.name=factory --post-renderer ./kustomize"] initContainers: [] + resourceExclusions: | + - apiGroups: + - tekton.dev + kinds: + - TaskRun + - PipelineRun + resourceHealthChecks: + - check: | + hs = {} + if obj.status ~= nil then + if obj.status.phase ~= nil then + if obj.status.phase == "Pending" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + elseif obj.status.phase == "Bound" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + end + end + end + hs.status = "Progressing" + hs.message = "Waiting for PVC" + return hs + kind: PersistentVolumeClaim + resourceTrackingMethod: label imperative: activeDeadlineSeconds: 3600 + adminClusterRoleName: imperative-admin-cluster-role + adminServiceAccountCreate: true + adminServiceAccountName: imperative-admin-sa clusterRoleName: imperative-cluster-role clusterRoleYaml: "" cronJobName: imperative-cronjob @@ -261,11 +298,24 @@ rules: - list - watch --- +# Source: clustergroup/templates/imperative/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: imperative-admin-cluster-role +rules: + - apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +--- # Source: clustergroup/templates/imperative/rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: imperative-cluster-admin-rolebinding + name: imperative-cluster-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -275,12 +325,30 @@ subjects: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: imperative-admin-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: imperative-admin-cluster-role +subjects: + - kind: ServiceAccount + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/plumbing/argocd-super-role.yaml # WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: openshift-gitops-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -300,6 +368,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: mypattern-factory-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -337,7 +409,7 @@ rules: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: imperative-admin-rolebinding + name: imperative-rolebinding namespace: imperative roleRef: apiGroup: rbac.authorization.k8s.io @@ -369,6 +441,27 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -378,6 +471,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -404,8 +499,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -429,6 +525,14 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -445,6 +549,19 @@ spec: - name: values-volume configMap: name: helm-values-configmap-factory + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/core/subscriptions.yaml @@ -519,6 +636,8 @@ spec: path: charts/datacenter/opendatahub helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-factory.yaml" @@ -528,9 +647,9 @@ spec: - "/values-4.12-factory.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -543,6 +662,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -590,6 +715,7 @@ spec: hs.message = "Waiting for PVC" return hs + resourceTrackingMethod: label applicationInstanceLabelKey: argocd.argoproj.io/instance applicationSet: resources: @@ -623,6 +749,47 @@ spec: rbac: defaultPolicy: role:admin repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle + - emptyDir: {} + name: ca-bundles sidecarContainers: - name: helm-with-kustomize command: [/var/run/argocd/argocd-cmp-server] @@ -656,7 +823,7 @@ spec: requests: cpu: 250m memory: 256Mi - resourceExclusions: | + resourceExclusions: | - apiGroups: - tekton.dev kinds: diff --git a/tests/common-clustergroup-industrial-edge-hub.expected.yaml b/tests/common-clustergroup-industrial-edge-hub.expected.yaml index dbb88e50..2ebd5c32 100644 --- a/tests/common-clustergroup-industrial-edge-hub.expected.yaml +++ b/tests/common-clustergroup-industrial-edge-hub.expected.yaml @@ -109,6 +109,13 @@ metadata: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/imperative/configmap.yaml apiVersion: v1 kind: ConfigMap @@ -235,8 +242,38 @@ data: --set clusterGroup.name=datacenter --post-renderer ./kustomize"] initContainers: [] + resourceExclusions: | + - apiGroups: + - tekton.dev + kinds: + - TaskRun + - PipelineRun + resourceHealthChecks: + - check: | + hs = {} + if obj.status ~= nil then + if obj.status.phase ~= nil then + if obj.status.phase == "Pending" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + elseif obj.status.phase == "Bound" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + end + end + end + hs.status = "Progressing" + hs.message = "Waiting for PVC" + return hs + kind: PersistentVolumeClaim + resourceTrackingMethod: label imperative: activeDeadlineSeconds: 3600 + adminClusterRoleName: imperative-admin-cluster-role + adminServiceAccountCreate: true + adminServiceAccountName: imperative-admin-sa clusterRoleName: imperative-cluster-role clusterRoleYaml: "" cronJobName: imperative-cronjob @@ -422,11 +459,24 @@ rules: - list - watch --- +# Source: clustergroup/templates/imperative/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: imperative-admin-cluster-role +rules: + - apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +--- # Source: clustergroup/templates/imperative/rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: imperative-cluster-admin-rolebinding + name: imperative-cluster-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -436,12 +486,30 @@ subjects: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: imperative-admin-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: imperative-admin-cluster-role +subjects: + - kind: ServiceAccount + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/plumbing/argocd-super-role.yaml # WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: openshift-gitops-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -461,6 +529,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: mypattern-datacenter-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -498,7 +570,7 @@ rules: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: imperative-admin-rolebinding + name: imperative-rolebinding namespace: imperative roleRef: apiGroup: rbac.authorization.k8s.io @@ -530,6 +602,27 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -539,6 +632,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -565,8 +660,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -590,6 +686,14 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -606,6 +710,19 @@ spec: - name: values-volume configMap: name: helm-values-configmap-datacenter + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/imperative/unsealjob.yaml @@ -629,6 +746,27 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -638,6 +776,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -664,8 +804,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -691,6 +832,14 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -707,6 +856,19 @@ spec: - name: values-volume configMap: name: helm-values-configmap-datacenter + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/core/subscriptions.yaml @@ -817,6 +979,8 @@ spec: path: common/acm helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-datacenter.yaml" @@ -826,9 +990,9 @@ spec: - "/values-4.12-datacenter.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -841,6 +1005,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -882,6 +1052,8 @@ spec: path: charts/datacenter/opendatahub helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-datacenter.yaml" @@ -891,9 +1063,9 @@ spec: - "/values-4.12-datacenter.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -906,6 +1078,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -938,6 +1116,8 @@ spec: path: charts/datacenter/pipelines helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-datacenter.yaml" @@ -947,9 +1127,9 @@ spec: - "/values-4.12-datacenter.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -962,6 +1142,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -994,6 +1180,8 @@ spec: path: charts/datacenter/manuela-data-lake helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-datacenter.yaml" @@ -1003,9 +1191,9 @@ spec: - "/values-4.12-datacenter.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1018,6 +1206,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1080,6 +1274,8 @@ spec: path: charts/datacenter/external-secrets helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-datacenter.yaml" @@ -1089,9 +1285,9 @@ spec: - "/values-4.12-datacenter.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1104,6 +1300,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1136,6 +1338,8 @@ spec: path: common/golang-external-secrets helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-datacenter.yaml" @@ -1145,9 +1349,9 @@ spec: - "/values-4.12-datacenter.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1160,6 +1364,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1219,6 +1429,8 @@ spec: chart: vault helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-datacenter.yaml" @@ -1228,9 +1440,9 @@ spec: - "/values-4.12-datacenter.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1243,6 +1455,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1308,6 +1526,7 @@ spec: hs.message = "Waiting for PVC" return hs + resourceTrackingMethod: label applicationInstanceLabelKey: argocd.argoproj.io/instance applicationSet: resources: @@ -1341,6 +1560,47 @@ spec: rbac: defaultPolicy: role:admin repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle + - emptyDir: {} + name: ca-bundles sidecarContainers: - name: helm-with-kustomize command: [/var/run/argocd/argocd-cmp-server] @@ -1374,7 +1634,7 @@ spec: requests: cpu: 250m memory: 256Mi - resourceExclusions: | + resourceExclusions: | - apiGroups: - tekton.dev kinds: diff --git a/tests/common-clustergroup-medical-diagnosis-hub.expected.yaml b/tests/common-clustergroup-medical-diagnosis-hub.expected.yaml index 59115478..cbca4462 100644 --- a/tests/common-clustergroup-medical-diagnosis-hub.expected.yaml +++ b/tests/common-clustergroup-medical-diagnosis-hub.expected.yaml @@ -109,6 +109,13 @@ metadata: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/imperative/configmap.yaml apiVersion: v1 kind: ConfigMap @@ -218,8 +225,38 @@ data: argoCD: configManagementPlugins: [] initContainers: [] + resourceExclusions: | + - apiGroups: + - tekton.dev + kinds: + - TaskRun + - PipelineRun + resourceHealthChecks: + - check: | + hs = {} + if obj.status ~= nil then + if obj.status.phase ~= nil then + if obj.status.phase == "Pending" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + elseif obj.status.phase == "Bound" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + end + end + end + hs.status = "Progressing" + hs.message = "Waiting for PVC" + return hs + kind: PersistentVolumeClaim + resourceTrackingMethod: label imperative: activeDeadlineSeconds: 3600 + adminClusterRoleName: imperative-admin-cluster-role + adminServiceAccountCreate: true + adminServiceAccountName: imperative-admin-sa clusterRoleName: imperative-cluster-role clusterRoleYaml: "" cronJobName: imperative-cronjob @@ -349,11 +386,24 @@ rules: - list - watch --- +# Source: clustergroup/templates/imperative/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: imperative-admin-cluster-role +rules: + - apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +--- # Source: clustergroup/templates/imperative/rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: imperative-cluster-admin-rolebinding + name: imperative-cluster-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -363,12 +413,30 @@ subjects: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: imperative-admin-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: imperative-admin-cluster-role +subjects: + - kind: ServiceAccount + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/plumbing/argocd-super-role.yaml # WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: openshift-gitops-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -388,6 +456,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: mypattern-hub-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -425,7 +497,7 @@ rules: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: imperative-admin-rolebinding + name: imperative-rolebinding namespace: imperative roleRef: apiGroup: rbac.authorization.k8s.io @@ -457,6 +529,27 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -466,6 +559,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -492,8 +587,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -517,6 +613,14 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -533,6 +637,19 @@ spec: - name: values-volume configMap: name: helm-values-configmap-hub + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/imperative/unsealjob.yaml @@ -556,6 +673,27 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -565,6 +703,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -591,8 +731,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -618,6 +759,14 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -634,6 +783,19 @@ spec: - name: values-volume configMap: name: helm-values-configmap-hub + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/core/subscriptions.yaml @@ -702,6 +864,8 @@ spec: path: common/golang-external-secrets helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -711,9 +875,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -726,6 +890,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -758,6 +928,8 @@ spec: path: charts/all/kafdrop helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -767,9 +939,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -782,6 +954,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -814,6 +992,8 @@ spec: path: charts/all/kafka helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -823,9 +1003,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -838,6 +1018,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -870,6 +1056,8 @@ spec: path: charts/all/opendatahub helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -879,9 +1067,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -894,6 +1082,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -926,6 +1120,8 @@ spec: path: charts/all/openshift-data-foundations helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -935,9 +1131,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -950,6 +1146,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -982,6 +1184,8 @@ spec: path: charts/all/openshift-serverless helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -991,9 +1195,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1006,6 +1210,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1038,6 +1248,8 @@ spec: path: charts/all/medical-diagnosis/service-account helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1047,9 +1259,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1062,6 +1274,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1094,6 +1312,8 @@ spec: chart: vault helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1103,9 +1323,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1118,6 +1338,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1168,6 +1394,8 @@ spec: path: charts/all/medical-diagnosis/database helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1177,9 +1405,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1192,6 +1420,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1224,6 +1458,8 @@ spec: path: charts/all/medical-diagnosis/grafana helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1233,9 +1469,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1248,6 +1484,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1280,6 +1522,8 @@ spec: path: charts/all/medical-diagnosis/image-generator helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1289,9 +1533,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1304,6 +1548,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1345,6 +1595,8 @@ spec: path: charts/all/medical-diagnosis/image-server helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1354,9 +1606,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1369,6 +1621,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1410,6 +1668,8 @@ spec: path: charts/all/medical-diagnosis/xray-init helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-hub.yaml" @@ -1419,9 +1679,9 @@ spec: - "/values-4.12-hub.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -1434,6 +1694,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1481,6 +1747,7 @@ spec: hs.message = "Waiting for PVC" return hs + resourceTrackingMethod: label applicationInstanceLabelKey: argocd.argoproj.io/instance applicationSet: resources: @@ -1514,6 +1781,47 @@ spec: rbac: defaultPolicy: role:admin repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle + - emptyDir: {} + name: ca-bundles resources: limits: cpu: "1" @@ -1521,7 +1829,7 @@ spec: requests: cpu: 250m memory: 256Mi - resourceExclusions: | + resourceExclusions: | - apiGroups: - tekton.dev kinds: diff --git a/tests/common-clustergroup-naked.expected.yaml b/tests/common-clustergroup-naked.expected.yaml index fdaf4293..16c6d81d 100644 --- a/tests/common-clustergroup-naked.expected.yaml +++ b/tests/common-clustergroup-naked.expected.yaml @@ -28,6 +28,13 @@ metadata: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/imperative/configmap.yaml apiVersion: v1 kind: ConfigMap @@ -41,8 +48,38 @@ data: argoCD: configManagementPlugins: [] initContainers: [] + resourceExclusions: | + - apiGroups: + - tekton.dev + kinds: + - TaskRun + - PipelineRun + resourceHealthChecks: + - check: | + hs = {} + if obj.status ~= nil then + if obj.status.phase ~= nil then + if obj.status.phase == "Pending" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + elseif obj.status.phase == "Bound" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + end + end + end + hs.status = "Progressing" + hs.message = "Waiting for PVC" + return hs + kind: PersistentVolumeClaim + resourceTrackingMethod: label imperative: activeDeadlineSeconds: 3600 + adminClusterRoleName: imperative-admin-cluster-role + adminServiceAccountCreate: true + adminServiceAccountName: imperative-admin-sa clusterRoleName: imperative-cluster-role clusterRoleYaml: "" cronJobName: imperative-cronjob @@ -117,11 +154,24 @@ rules: - list - watch --- +# Source: clustergroup/templates/imperative/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: imperative-admin-cluster-role +rules: + - apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +--- # Source: clustergroup/templates/imperative/rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: imperative-cluster-admin-rolebinding + name: imperative-cluster-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -131,12 +181,30 @@ subjects: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: imperative-admin-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: imperative-admin-cluster-role +subjects: + - kind: ServiceAccount + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/plumbing/argocd-super-role.yaml # WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: openshift-gitops-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -156,6 +224,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: common-example-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -193,7 +265,7 @@ rules: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: imperative-admin-rolebinding + name: imperative-rolebinding namespace: imperative roleRef: apiGroup: rbac.authorization.k8s.io @@ -225,6 +297,27 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -234,6 +327,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -260,8 +355,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -287,6 +383,14 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -303,6 +407,19 @@ spec: - name: values-volume configMap: name: helm-values-configmap-example + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/plumbing/argocd.yaml @@ -341,6 +458,7 @@ spec: hs.message = "Waiting for PVC" return hs + resourceTrackingMethod: label applicationInstanceLabelKey: argocd.argoproj.io/instance applicationSet: resources: @@ -374,6 +492,47 @@ spec: rbac: defaultPolicy: role:admin repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle + - emptyDir: {} + name: ca-bundles resources: limits: cpu: "1" @@ -381,7 +540,7 @@ spec: requests: cpu: 250m memory: 256Mi - resourceExclusions: | + resourceExclusions: | - apiGroups: - tekton.dev kinds: diff --git a/tests/common-clustergroup-normal.expected.yaml b/tests/common-clustergroup-normal.expected.yaml index 85995a56..a4b1dc7f 100644 --- a/tests/common-clustergroup-normal.expected.yaml +++ b/tests/common-clustergroup-normal.expected.yaml @@ -96,6 +96,13 @@ metadata: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/imperative/configmap.yaml apiVersion: v1 kind: ConfigMap @@ -126,8 +133,38 @@ data: argoCD: configManagementPlugins: [] initContainers: [] + resourceExclusions: | + - apiGroups: + - tekton.dev + kinds: + - TaskRun + - PipelineRun + resourceHealthChecks: + - check: | + hs = {} + if obj.status ~= nil then + if obj.status.phase ~= nil then + if obj.status.phase == "Pending" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + elseif obj.status.phase == "Bound" then + hs.status = "Healthy" + hs.message = obj.status.phase + return hs + end + end + end + hs.status = "Progressing" + hs.message = "Waiting for PVC" + return hs + kind: PersistentVolumeClaim + resourceTrackingMethod: label imperative: activeDeadlineSeconds: 3600 + adminClusterRoleName: imperative-admin-cluster-role + adminServiceAccountCreate: true + adminServiceAccountName: imperative-admin-sa clusterRoleName: imperative-cluster-role clusterRoleYaml: "" cronJobName: imperative-cronjob @@ -160,6 +197,14 @@ data: - acmlabels: - name: clusterGroup value: region + clusterDeployments: + myFirstCluster: + baseDomain: blueprints.rhecoeng.com + name: aws-cd-one-w-pool + openshiftVersion: 4.10.18 + platform: + aws: + region: ap-southeast-1 clusterPools: exampleAWSPool: baseDomain: blueprints.rhecoeng.com @@ -192,6 +237,15 @@ data: value: "false" name: acm-provision-edge targetRevision: main + - clusterDeployments: + mySecondCluster: + baseDomain: blueprints.rhecoeng.com + name: aws-cd-two-wo-pool + openshiftVersion: 4.10.18 + platform: + aws: + region: ap-southeast-3 + name: acm-provision-on-deploy - helmOverrides: - name: clusterGroup.isHubCluster value: "false" @@ -228,6 +282,8 @@ data: - exclude-og projects: - datacenter + scheduler: + mastersSchedulable: true sharedValueFiles: - /values/aws.yaml - /values/4.12.yaml @@ -311,11 +367,24 @@ rules: - list - watch --- +# Source: clustergroup/templates/imperative/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: imperative-admin-cluster-role +rules: + - apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +--- # Source: clustergroup/templates/imperative/rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: imperative-cluster-admin-rolebinding + name: imperative-cluster-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -325,12 +394,30 @@ subjects: name: imperative-sa namespace: imperative --- +# Source: clustergroup/templates/imperative/rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: imperative-admin-clusterrolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: imperative-admin-cluster-role +subjects: + - kind: ServiceAccount + name: imperative-admin-sa + namespace: imperative +--- # Source: clustergroup/templates/plumbing/argocd-super-role.yaml # WARNING: ONLY USE THIS FOR MANAGING CLUSTERS NOT FOR REGULAR USERS apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: openshift-gitops-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -350,6 +437,10 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: mypattern-example-cluster-admin-rolebinding + # We need to have this before anything else or the sync might get stuck forever + # due to permission issues + annotations: + argocd.argoproj.io/sync-wave: "-100" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -387,7 +478,7 @@ rules: apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: - name: imperative-admin-rolebinding + name: imperative-rolebinding namespace: imperative roleRef: apiGroup: rbac.authorization.k8s.io @@ -419,6 +510,27 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -428,6 +540,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -454,8 +568,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: test image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -479,6 +594,14 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -495,6 +618,19 @@ spec: - name: values-volume configMap: name: helm-values-configmap-example + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/imperative/unsealjob.yaml @@ -518,6 +654,27 @@ spec: initContainers: # git init happens in /git/repo so that we can set the folder to 0770 permissions # reason for that is ansible refuses to create temporary folders in there + - name: fetch-ca + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + imagePullPolicy: Always + env: + - name: HOME + value: /git/home + command: + - 'sh' + - '-c' + - >- + cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true; + ls -l /tmp/ca-bundles/ + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles - name: git-init image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest imagePullPolicy: Always @@ -527,6 +684,8 @@ spec: volumeMounts: - name: git mountPath: "/git" + - name: ca-bundles + mountPath: /etc/pki/tls/certs command: - 'sh' - '-c' @@ -553,8 +712,9 @@ spec: if [ -n "${OUT}" ]; then export HTTPS_PROXY="${OUT}"; fi; OUT="$(oc get proxy.config.openshift.io/cluster -o jsonpath='{.spec.noProxy}' 2>/dev/null)"; if [ -n "${OUT}" ]; then export NO_PROXY="${OUT}"; fi; + if [ "main" = "HEAD" ]; then BRANCH=""; else BRANCH="--branch main"; fi; mkdir /git/{repo,home}; - git clone --recurse-submodules --single-branch --branch main --depth 1 -- "${URL}" /git/repo; + git clone --recurse-submodules --single-branch ${BRANCH} --depth 1 -- "${URL}" /git/repo; chmod 0770 /git/{repo,home}; - name: unseal-playbook image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -580,6 +740,14 @@ spec: - name: values-volume mountPath: /values/values.yaml subPath: values.yaml + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles containers: - name: "done" image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest @@ -596,6 +764,19 @@ spec: - name: values-volume configMap: name: helm-values-configmap-example + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle + - name: ca-bundles + emptyDir: {} restartPolicy: Never --- # Source: clustergroup/templates/core/operatorgroup.yaml @@ -667,6 +848,8 @@ spec: path: common/acm helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-example.yaml" @@ -678,9 +861,9 @@ spec: - "/values/4.12.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -693,6 +876,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -734,6 +923,8 @@ spec: path: charts/datacenter/pipelines helm: ignoreMissingValueFiles: true + values: | + extraParametersNested: valueFiles: - "/values-global.yaml" - "/values-example.yaml" @@ -746,9 +937,9 @@ spec: - "/values/4.12/aws.yaml" parameters: - name: global.repoURL - value: $ARGOCD_APP_SOURCE_REPO_URL + value: https://github.com/pattern-clone/mypattern - name: global.targetRevision - value: $ARGOCD_APP_SOURCE_TARGET_REVISION + value: main - name: global.namespace value: $ARGOCD_APP_NAMESPACE - name: global.pattern @@ -761,6 +952,12 @@ spec: value: "aws" - name: global.hubClusterDomain value: apps.hub.example.com + - name: global.multiSourceSupport + value: + - name: global.multiSourceRepoUrl + value: + - name: global.multiSourceTargetRevision + value: - name: global.localClusterDomain value: apps.region.example.com - name: global.privateRepo @@ -1048,6 +1245,7 @@ spec: hs.message = "Waiting for PVC" return hs + resourceTrackingMethod: label applicationInstanceLabelKey: argocd.argoproj.io/instance applicationSet: resources: @@ -1081,6 +1279,47 @@ spec: rbac: defaultPolicy: role:admin repo: + initContainers: + - command: + - bash + - -c + - cat /var/run/kube-root-ca/ca.crt /var/run/trusted-ca/ca-bundle.crt /var/run/trusted-hub/hub-kube-root-ca.crt > /tmp/ca-bundles/ca-bundle.crt || true + image: registry.redhat.io/ansible-automation-platform-24/ee-supported-rhel9:latest + name: fetch-ca + resources: {} + volumeMounts: + - mountPath: /var/run/kube-root-ca + name: kube-root-ca + - mountPath: /var/run/trusted-ca + name: trusted-ca-bundle + - mountPath: /var/run/trusted-hub + name: trusted-hub-bundle + - mountPath: /tmp/ca-bundles + name: ca-bundles + resources: + limits: + cpu: "1" + memory: 1Gi + requests: + cpu: 250m + memory: 256Mi + volumeMounts: + - mountPath: /etc/pki/tls/certs + name: ca-bundles + volumes: + - configMap: + name: kube-root-ca.crt + name: kube-root-ca + - configMap: + name: trusted-ca-bundle + optional: true + name: trusted-ca-bundle + - configMap: + name: trusted-hub-bundle + optional: true + name: trusted-hub-bundle + - emptyDir: {} + name: ca-bundles resources: limits: cpu: "1" @@ -1088,7 +1327,7 @@ spec: requests: cpu: 250m memory: 256Mi - resourceExclusions: | + resourceExclusions: | - apiGroups: - tekton.dev kinds: @@ -1153,8 +1392,6 @@ kind: OperatorGroup metadata: name: exclude-targetns-operator-group namespace: exclude-targetns -spec: - targetNamespaces: --- # Source: clustergroup/templates/core/operatorgroup.yaml --- @@ -1177,6 +1414,14 @@ spec: targetNamespaces: - include-default-og --- +# Source: clustergroup/templates/core/scheduler.yaml +apiVersion: config.openshift.io/v1 +kind: Scheduler +metadata: + name: cluster +spec: + mastersSchedulable: true +--- # Source: clustergroup/templates/core/subscriptions.yaml apiVersion: operators.coreos.com/v1alpha1 kind: Subscription diff --git a/tests/common-golang-external-secrets-industrial-edge-factory.expected.yaml b/tests/common-golang-external-secrets-industrial-edge-factory.expected.yaml index dde550fd..66b23292 100644 --- a/tests/common-golang-external-secrets-industrial-edge-factory.expected.yaml +++ b/tests/common-golang-external-secrets-industrial-edge-factory.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: common-golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -263,7 +265,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -780,11 +784,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -827,11 +833,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -844,7 +852,7 @@ spec: x-kubernetes-map-type: atomic type: array namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelector ends up choosing. + description: Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing. items: type: string type: array @@ -916,7 +924,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2457,6 +2467,11 @@ spec: ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in for a ClusterSecretStore instance. properties: + namespaceRegexes: + description: Choose namespaces by using regex matching + items: + type: string + type: array namespaceSelector: description: Choose namespace using a labelSelector properties: @@ -2484,11 +2499,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -2921,6 +2938,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -3034,6 +3068,63 @@ spec: required: - vaultUrl type: object + bitwardensecretsmanager: + description: BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider + properties: + apiURL: + type: string + auth: + description: |- + Auth configures how secret-manager authenticates with a bitwarden machine account instance. + Make sure that the token being used has permissions on the given secret. + properties: + secretRef: + description: BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance. + properties: + credentials: + description: AccessToken used for the bitwarden instance. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - credentials + type: object + required: + - secretRef + type: object + bitwardenServerSDKURL: + type: string + caBundle: + description: |- + Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack + can be performed. + type: string + identityURL: + type: string + organizationID: + description: OrganizationID determines which organization this secret store manages. + type: string + projectID: + description: ProjectID determines which project this secret store manages. + type: string + required: + - auth + - caBundle + - organizationID + - projectID + type: object chef: description: Chef configures this store to sync secrets with chef server properties: @@ -3295,6 +3386,42 @@ spec: - clientSecret - tenant type: object + device42: + description: Device42 configures this store to sync secrets using the Device42 provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a Device42 instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + host: + description: URL configures the Device42 instance URL. + type: string + required: + - auth + - host + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -3471,6 +3598,9 @@ spec: - serviceAccountRef type: object type: object + location: + description: Location optionally defines a location for a secret + type: string projectID: description: ProjectID project where secret is located type: string @@ -3573,6 +3703,77 @@ spec: required: - auth type: object + infisical: + description: Infisical configures this store to sync secrets using the Infisical provider + properties: + auth: + description: Auth configures how the Operator authenticates with the Infisical API + properties: + universalAuthCredentials: + properties: + clientId: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientSecret: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - clientId + - clientSecret + type: object + type: object + hostAPI: + default: https://app.infisical.com/api + type: string + secretsScope: + properties: + environmentSlug: + type: string + projectSlug: + type: string + secretsPath: + default: / + type: string + required: + - environmentSlug + - projectSlug + type: object + required: + - auth + - secretsScope + type: object keepersecurity: description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider properties: @@ -3697,6 +3898,23 @@ spec: type: object type: object type: object + authRef: + description: A reference to a secret that contains the auth information. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object remoteNamespace: default: default description: Remote namespace to fetch the secrets from @@ -3737,8 +3955,6 @@ spec: description: configures the Kubernetes server Address. type: string type: object - required: - - auth type: object onboardbase: description: Onboardbase configures this store to sync secrets using the Onboardbase provider @@ -5079,7 +5295,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -5246,7 +5464,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -5487,10 +5707,15 @@ spec: description: Binding represents a servicebinding.io Provisioned Service reference to the secret properties: name: + default: "" description: |- Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. type: string type: object x-kubernetes-map-type: atomic @@ -5993,10 +6218,15 @@ spec: description: Binding represents a servicebinding.io Provisioned Service reference to the secret properties: name: + default: "" description: |- Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. type: string type: object x-kubernetes-map-type: atomic @@ -6051,7 +6281,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6127,7 +6359,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6255,7 +6489,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: githubaccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6299,7 +6535,7 @@ spec: auth: description: Auth configures how ESO authenticates with a Github instance. properties: - privatKey: + privateKey: properties: secretRef: description: |- @@ -6324,7 +6560,7 @@ spec: - secretRef type: object required: - - privatKey + - privateKey type: object installID: type: string @@ -6357,7 +6593,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6455,7 +6693,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -6586,11 +6824,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6831,7 +7071,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -8372,6 +8614,11 @@ spec: ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in for a ClusterSecretStore instance. properties: + namespaceRegexes: + description: Choose namespaces by using regex matching + items: + type: string + type: array namespaceSelector: description: Choose namespace using a labelSelector properties: @@ -8399,11 +8646,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8836,6 +9085,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -8949,6 +9215,63 @@ spec: required: - vaultUrl type: object + bitwardensecretsmanager: + description: BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider + properties: + apiURL: + type: string + auth: + description: |- + Auth configures how secret-manager authenticates with a bitwarden machine account instance. + Make sure that the token being used has permissions on the given secret. + properties: + secretRef: + description: BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance. + properties: + credentials: + description: AccessToken used for the bitwarden instance. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - credentials + type: object + required: + - secretRef + type: object + bitwardenServerSDKURL: + type: string + caBundle: + description: |- + Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack + can be performed. + type: string + identityURL: + type: string + organizationID: + description: OrganizationID determines which organization this secret store manages. + type: string + projectID: + description: ProjectID determines which project this secret store manages. + type: string + required: + - auth + - caBundle + - organizationID + - projectID + type: object chef: description: Chef configures this store to sync secrets with chef server properties: @@ -9210,6 +9533,42 @@ spec: - clientSecret - tenant type: object + device42: + description: Device42 configures this store to sync secrets using the Device42 provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a Device42 instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + host: + description: URL configures the Device42 instance URL. + type: string + required: + - auth + - host + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -9386,6 +9745,9 @@ spec: - serviceAccountRef type: object type: object + location: + description: Location optionally defines a location for a secret + type: string projectID: description: ProjectID project where secret is located type: string @@ -9488,6 +9850,77 @@ spec: required: - auth type: object + infisical: + description: Infisical configures this store to sync secrets using the Infisical provider + properties: + auth: + description: Auth configures how the Operator authenticates with the Infisical API + properties: + universalAuthCredentials: + properties: + clientId: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientSecret: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - clientId + - clientSecret + type: object + type: object + hostAPI: + default: https://app.infisical.com/api + type: string + secretsScope: + properties: + environmentSlug: + type: string + projectSlug: + type: string + secretsPath: + default: / + type: string + required: + - environmentSlug + - projectSlug + type: object + required: + - auth + - secretsScope + type: object keepersecurity: description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider properties: @@ -9612,6 +10045,23 @@ spec: type: object type: object type: object + authRef: + description: A reference to a secret that contains the auth information. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object remoteNamespace: default: default description: Remote namespace to fetch the secrets from @@ -9652,8 +10102,6 @@ spec: description: configures the Kubernetes server Address. type: string type: object - required: - - auth type: object onboardbase: description: Onboardbase configures this store to sync secrets using the Onboardbase provider @@ -10994,7 +11442,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11686,7 +12136,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: webhooks.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11834,10 +12286,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11901,10 +12353,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11938,6 +12390,7 @@ rules: - "pushsecrets/status" - "pushsecrets/finalizers" verbs: + - "get" - "update" - "patch" - apiGroups: @@ -12012,10 +12465,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -12054,10 +12507,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -12100,10 +12553,10 @@ metadata: name: common-golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12121,10 +12574,10 @@ kind: ClusterRoleBinding metadata: name: common-golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12141,10 +12594,10 @@ kind: ClusterRoleBinding metadata: name: common-golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12177,10 +12630,10 @@ metadata: name: common-golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12216,10 +12669,10 @@ metadata: name: common-golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12237,10 +12690,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -12261,10 +12714,10 @@ metadata: name: common-golang-external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12276,10 +12729,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: external-secrets-cert-controller @@ -12294,7 +12747,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.20-ubi imagePullPolicy: IfNotPresent args: - certcontroller @@ -12305,7 +12758,9 @@ spec: - --secret-namespace=default - --metrics-addr=:8080 - --healthz-addr=:8081 - + - --loglevel=info + - --zap-time-encoding=epoch + - --enable-partial-cache=true ports: - containerPort: 8080 protocol: TCP @@ -12324,10 +12779,10 @@ metadata: name: common-golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12339,10 +12794,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: common-golang-external-secrets @@ -12357,15 +12812,18 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.20-ubi imagePullPolicy: IfNotPresent args: - --concurrent=1 - --metrics-addr=:8080 + - --loglevel=info + - --zap-time-encoding=epoch ports: - containerPort: 8080 protocol: TCP name: metrics + dnsPolicy: ClusterFirst --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml apiVersion: apps/v1 @@ -12374,10 +12832,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12389,10 +12847,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: hostNetwork: false @@ -12407,7 +12865,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.20-ubi imagePullPolicy: IfNotPresent args: - webhook @@ -12417,6 +12875,8 @@ spec: - --check-interval=5m - --metrics-addr=:8080 - --healthz-addr=:8081 + - --loglevel=info + - --zap-time-encoding=epoch ports: - containerPort: 8080 protocol: TCP @@ -12457,7 +12917,7 @@ spec: type: Secret name: hub-ca key: hub-kube-root-ca.crt - namespace: imperative + namespace: golang-external-secrets auth: kubernetes: diff --git a/tests/common-golang-external-secrets-industrial-edge-hub.expected.yaml b/tests/common-golang-external-secrets-industrial-edge-hub.expected.yaml index a0ad351a..b7c2ad96 100644 --- a/tests/common-golang-external-secrets-industrial-edge-hub.expected.yaml +++ b/tests/common-golang-external-secrets-industrial-edge-hub.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: common-golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -263,7 +265,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -780,11 +784,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -827,11 +833,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -844,7 +852,7 @@ spec: x-kubernetes-map-type: atomic type: array namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelector ends up choosing. + description: Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing. items: type: string type: array @@ -916,7 +924,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2457,6 +2467,11 @@ spec: ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in for a ClusterSecretStore instance. properties: + namespaceRegexes: + description: Choose namespaces by using regex matching + items: + type: string + type: array namespaceSelector: description: Choose namespace using a labelSelector properties: @@ -2484,11 +2499,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -2921,6 +2938,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -3034,6 +3068,63 @@ spec: required: - vaultUrl type: object + bitwardensecretsmanager: + description: BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider + properties: + apiURL: + type: string + auth: + description: |- + Auth configures how secret-manager authenticates with a bitwarden machine account instance. + Make sure that the token being used has permissions on the given secret. + properties: + secretRef: + description: BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance. + properties: + credentials: + description: AccessToken used for the bitwarden instance. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - credentials + type: object + required: + - secretRef + type: object + bitwardenServerSDKURL: + type: string + caBundle: + description: |- + Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack + can be performed. + type: string + identityURL: + type: string + organizationID: + description: OrganizationID determines which organization this secret store manages. + type: string + projectID: + description: ProjectID determines which project this secret store manages. + type: string + required: + - auth + - caBundle + - organizationID + - projectID + type: object chef: description: Chef configures this store to sync secrets with chef server properties: @@ -3295,6 +3386,42 @@ spec: - clientSecret - tenant type: object + device42: + description: Device42 configures this store to sync secrets using the Device42 provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a Device42 instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + host: + description: URL configures the Device42 instance URL. + type: string + required: + - auth + - host + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -3471,6 +3598,9 @@ spec: - serviceAccountRef type: object type: object + location: + description: Location optionally defines a location for a secret + type: string projectID: description: ProjectID project where secret is located type: string @@ -3573,6 +3703,77 @@ spec: required: - auth type: object + infisical: + description: Infisical configures this store to sync secrets using the Infisical provider + properties: + auth: + description: Auth configures how the Operator authenticates with the Infisical API + properties: + universalAuthCredentials: + properties: + clientId: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientSecret: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - clientId + - clientSecret + type: object + type: object + hostAPI: + default: https://app.infisical.com/api + type: string + secretsScope: + properties: + environmentSlug: + type: string + projectSlug: + type: string + secretsPath: + default: / + type: string + required: + - environmentSlug + - projectSlug + type: object + required: + - auth + - secretsScope + type: object keepersecurity: description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider properties: @@ -3697,6 +3898,23 @@ spec: type: object type: object type: object + authRef: + description: A reference to a secret that contains the auth information. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object remoteNamespace: default: default description: Remote namespace to fetch the secrets from @@ -3737,8 +3955,6 @@ spec: description: configures the Kubernetes server Address. type: string type: object - required: - - auth type: object onboardbase: description: Onboardbase configures this store to sync secrets using the Onboardbase provider @@ -5079,7 +5295,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -5246,7 +5464,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -5487,10 +5707,15 @@ spec: description: Binding represents a servicebinding.io Provisioned Service reference to the secret properties: name: + default: "" description: |- Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. type: string type: object x-kubernetes-map-type: atomic @@ -5993,10 +6218,15 @@ spec: description: Binding represents a servicebinding.io Provisioned Service reference to the secret properties: name: + default: "" description: |- Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. type: string type: object x-kubernetes-map-type: atomic @@ -6051,7 +6281,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6127,7 +6359,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6255,7 +6489,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: githubaccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6299,7 +6535,7 @@ spec: auth: description: Auth configures how ESO authenticates with a Github instance. properties: - privatKey: + privateKey: properties: secretRef: description: |- @@ -6324,7 +6560,7 @@ spec: - secretRef type: object required: - - privatKey + - privateKey type: object installID: type: string @@ -6357,7 +6593,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6455,7 +6693,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -6586,11 +6824,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6831,7 +7071,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -8372,6 +8614,11 @@ spec: ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in for a ClusterSecretStore instance. properties: + namespaceRegexes: + description: Choose namespaces by using regex matching + items: + type: string + type: array namespaceSelector: description: Choose namespace using a labelSelector properties: @@ -8399,11 +8646,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8836,6 +9085,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -8949,6 +9215,63 @@ spec: required: - vaultUrl type: object + bitwardensecretsmanager: + description: BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider + properties: + apiURL: + type: string + auth: + description: |- + Auth configures how secret-manager authenticates with a bitwarden machine account instance. + Make sure that the token being used has permissions on the given secret. + properties: + secretRef: + description: BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance. + properties: + credentials: + description: AccessToken used for the bitwarden instance. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - credentials + type: object + required: + - secretRef + type: object + bitwardenServerSDKURL: + type: string + caBundle: + description: |- + Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack + can be performed. + type: string + identityURL: + type: string + organizationID: + description: OrganizationID determines which organization this secret store manages. + type: string + projectID: + description: ProjectID determines which project this secret store manages. + type: string + required: + - auth + - caBundle + - organizationID + - projectID + type: object chef: description: Chef configures this store to sync secrets with chef server properties: @@ -9210,6 +9533,42 @@ spec: - clientSecret - tenant type: object + device42: + description: Device42 configures this store to sync secrets using the Device42 provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a Device42 instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + host: + description: URL configures the Device42 instance URL. + type: string + required: + - auth + - host + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -9386,6 +9745,9 @@ spec: - serviceAccountRef type: object type: object + location: + description: Location optionally defines a location for a secret + type: string projectID: description: ProjectID project where secret is located type: string @@ -9488,6 +9850,77 @@ spec: required: - auth type: object + infisical: + description: Infisical configures this store to sync secrets using the Infisical provider + properties: + auth: + description: Auth configures how the Operator authenticates with the Infisical API + properties: + universalAuthCredentials: + properties: + clientId: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientSecret: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - clientId + - clientSecret + type: object + type: object + hostAPI: + default: https://app.infisical.com/api + type: string + secretsScope: + properties: + environmentSlug: + type: string + projectSlug: + type: string + secretsPath: + default: / + type: string + required: + - environmentSlug + - projectSlug + type: object + required: + - auth + - secretsScope + type: object keepersecurity: description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider properties: @@ -9612,6 +10045,23 @@ spec: type: object type: object type: object + authRef: + description: A reference to a secret that contains the auth information. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object remoteNamespace: default: default description: Remote namespace to fetch the secrets from @@ -9652,8 +10102,6 @@ spec: description: configures the Kubernetes server Address. type: string type: object - required: - - auth type: object onboardbase: description: Onboardbase configures this store to sync secrets using the Onboardbase provider @@ -10994,7 +11442,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11686,7 +12136,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: webhooks.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11834,10 +12286,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11901,10 +12353,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11938,6 +12390,7 @@ rules: - "pushsecrets/status" - "pushsecrets/finalizers" verbs: + - "get" - "update" - "patch" - apiGroups: @@ -12012,10 +12465,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -12054,10 +12507,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -12100,10 +12553,10 @@ metadata: name: common-golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12121,10 +12574,10 @@ kind: ClusterRoleBinding metadata: name: common-golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12141,10 +12594,10 @@ kind: ClusterRoleBinding metadata: name: common-golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12177,10 +12630,10 @@ metadata: name: common-golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12216,10 +12669,10 @@ metadata: name: common-golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12237,10 +12690,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -12261,10 +12714,10 @@ metadata: name: common-golang-external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12276,10 +12729,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: external-secrets-cert-controller @@ -12294,7 +12747,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.20-ubi imagePullPolicy: IfNotPresent args: - certcontroller @@ -12305,7 +12758,9 @@ spec: - --secret-namespace=default - --metrics-addr=:8080 - --healthz-addr=:8081 - + - --loglevel=info + - --zap-time-encoding=epoch + - --enable-partial-cache=true ports: - containerPort: 8080 protocol: TCP @@ -12324,10 +12779,10 @@ metadata: name: common-golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12339,10 +12794,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: common-golang-external-secrets @@ -12357,15 +12812,18 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.20-ubi imagePullPolicy: IfNotPresent args: - --concurrent=1 - --metrics-addr=:8080 + - --loglevel=info + - --zap-time-encoding=epoch ports: - containerPort: 8080 protocol: TCP name: metrics + dnsPolicy: ClusterFirst --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml apiVersion: apps/v1 @@ -12374,10 +12832,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12389,10 +12847,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: hostNetwork: false @@ -12407,7 +12865,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.20-ubi imagePullPolicy: IfNotPresent args: - webhook @@ -12417,6 +12875,8 @@ spec: - --check-interval=5m - --metrics-addr=:8080 - --healthz-addr=:8081 + - --loglevel=info + - --zap-time-encoding=epoch ports: - containerPort: 8080 protocol: TCP diff --git a/tests/common-golang-external-secrets-medical-diagnosis-hub.expected.yaml b/tests/common-golang-external-secrets-medical-diagnosis-hub.expected.yaml index a0ad351a..b7c2ad96 100644 --- a/tests/common-golang-external-secrets-medical-diagnosis-hub.expected.yaml +++ b/tests/common-golang-external-secrets-medical-diagnosis-hub.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: common-golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -263,7 +265,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -780,11 +784,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -827,11 +833,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -844,7 +852,7 @@ spec: x-kubernetes-map-type: atomic type: array namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelector ends up choosing. + description: Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing. items: type: string type: array @@ -916,7 +924,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2457,6 +2467,11 @@ spec: ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in for a ClusterSecretStore instance. properties: + namespaceRegexes: + description: Choose namespaces by using regex matching + items: + type: string + type: array namespaceSelector: description: Choose namespace using a labelSelector properties: @@ -2484,11 +2499,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -2921,6 +2938,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -3034,6 +3068,63 @@ spec: required: - vaultUrl type: object + bitwardensecretsmanager: + description: BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider + properties: + apiURL: + type: string + auth: + description: |- + Auth configures how secret-manager authenticates with a bitwarden machine account instance. + Make sure that the token being used has permissions on the given secret. + properties: + secretRef: + description: BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance. + properties: + credentials: + description: AccessToken used for the bitwarden instance. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - credentials + type: object + required: + - secretRef + type: object + bitwardenServerSDKURL: + type: string + caBundle: + description: |- + Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack + can be performed. + type: string + identityURL: + type: string + organizationID: + description: OrganizationID determines which organization this secret store manages. + type: string + projectID: + description: ProjectID determines which project this secret store manages. + type: string + required: + - auth + - caBundle + - organizationID + - projectID + type: object chef: description: Chef configures this store to sync secrets with chef server properties: @@ -3295,6 +3386,42 @@ spec: - clientSecret - tenant type: object + device42: + description: Device42 configures this store to sync secrets using the Device42 provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a Device42 instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + host: + description: URL configures the Device42 instance URL. + type: string + required: + - auth + - host + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -3471,6 +3598,9 @@ spec: - serviceAccountRef type: object type: object + location: + description: Location optionally defines a location for a secret + type: string projectID: description: ProjectID project where secret is located type: string @@ -3573,6 +3703,77 @@ spec: required: - auth type: object + infisical: + description: Infisical configures this store to sync secrets using the Infisical provider + properties: + auth: + description: Auth configures how the Operator authenticates with the Infisical API + properties: + universalAuthCredentials: + properties: + clientId: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientSecret: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - clientId + - clientSecret + type: object + type: object + hostAPI: + default: https://app.infisical.com/api + type: string + secretsScope: + properties: + environmentSlug: + type: string + projectSlug: + type: string + secretsPath: + default: / + type: string + required: + - environmentSlug + - projectSlug + type: object + required: + - auth + - secretsScope + type: object keepersecurity: description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider properties: @@ -3697,6 +3898,23 @@ spec: type: object type: object type: object + authRef: + description: A reference to a secret that contains the auth information. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object remoteNamespace: default: default description: Remote namespace to fetch the secrets from @@ -3737,8 +3955,6 @@ spec: description: configures the Kubernetes server Address. type: string type: object - required: - - auth type: object onboardbase: description: Onboardbase configures this store to sync secrets using the Onboardbase provider @@ -5079,7 +5295,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -5246,7 +5464,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -5487,10 +5707,15 @@ spec: description: Binding represents a servicebinding.io Provisioned Service reference to the secret properties: name: + default: "" description: |- Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. type: string type: object x-kubernetes-map-type: atomic @@ -5993,10 +6218,15 @@ spec: description: Binding represents a servicebinding.io Provisioned Service reference to the secret properties: name: + default: "" description: |- Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. type: string type: object x-kubernetes-map-type: atomic @@ -6051,7 +6281,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6127,7 +6359,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6255,7 +6489,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: githubaccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6299,7 +6535,7 @@ spec: auth: description: Auth configures how ESO authenticates with a Github instance. properties: - privatKey: + privateKey: properties: secretRef: description: |- @@ -6324,7 +6560,7 @@ spec: - secretRef type: object required: - - privatKey + - privateKey type: object installID: type: string @@ -6357,7 +6593,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6455,7 +6693,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -6586,11 +6824,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6831,7 +7071,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -8372,6 +8614,11 @@ spec: ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in for a ClusterSecretStore instance. properties: + namespaceRegexes: + description: Choose namespaces by using regex matching + items: + type: string + type: array namespaceSelector: description: Choose namespace using a labelSelector properties: @@ -8399,11 +8646,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8836,6 +9085,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -8949,6 +9215,63 @@ spec: required: - vaultUrl type: object + bitwardensecretsmanager: + description: BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider + properties: + apiURL: + type: string + auth: + description: |- + Auth configures how secret-manager authenticates with a bitwarden machine account instance. + Make sure that the token being used has permissions on the given secret. + properties: + secretRef: + description: BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance. + properties: + credentials: + description: AccessToken used for the bitwarden instance. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - credentials + type: object + required: + - secretRef + type: object + bitwardenServerSDKURL: + type: string + caBundle: + description: |- + Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack + can be performed. + type: string + identityURL: + type: string + organizationID: + description: OrganizationID determines which organization this secret store manages. + type: string + projectID: + description: ProjectID determines which project this secret store manages. + type: string + required: + - auth + - caBundle + - organizationID + - projectID + type: object chef: description: Chef configures this store to sync secrets with chef server properties: @@ -9210,6 +9533,42 @@ spec: - clientSecret - tenant type: object + device42: + description: Device42 configures this store to sync secrets using the Device42 provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a Device42 instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + host: + description: URL configures the Device42 instance URL. + type: string + required: + - auth + - host + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -9386,6 +9745,9 @@ spec: - serviceAccountRef type: object type: object + location: + description: Location optionally defines a location for a secret + type: string projectID: description: ProjectID project where secret is located type: string @@ -9488,6 +9850,77 @@ spec: required: - auth type: object + infisical: + description: Infisical configures this store to sync secrets using the Infisical provider + properties: + auth: + description: Auth configures how the Operator authenticates with the Infisical API + properties: + universalAuthCredentials: + properties: + clientId: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientSecret: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - clientId + - clientSecret + type: object + type: object + hostAPI: + default: https://app.infisical.com/api + type: string + secretsScope: + properties: + environmentSlug: + type: string + projectSlug: + type: string + secretsPath: + default: / + type: string + required: + - environmentSlug + - projectSlug + type: object + required: + - auth + - secretsScope + type: object keepersecurity: description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider properties: @@ -9612,6 +10045,23 @@ spec: type: object type: object type: object + authRef: + description: A reference to a secret that contains the auth information. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object remoteNamespace: default: default description: Remote namespace to fetch the secrets from @@ -9652,8 +10102,6 @@ spec: description: configures the Kubernetes server Address. type: string type: object - required: - - auth type: object onboardbase: description: Onboardbase configures this store to sync secrets using the Onboardbase provider @@ -10994,7 +11442,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11686,7 +12136,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: webhooks.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11834,10 +12286,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11901,10 +12353,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11938,6 +12390,7 @@ rules: - "pushsecrets/status" - "pushsecrets/finalizers" verbs: + - "get" - "update" - "patch" - apiGroups: @@ -12012,10 +12465,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -12054,10 +12507,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -12100,10 +12553,10 @@ metadata: name: common-golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12121,10 +12574,10 @@ kind: ClusterRoleBinding metadata: name: common-golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12141,10 +12594,10 @@ kind: ClusterRoleBinding metadata: name: common-golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12177,10 +12630,10 @@ metadata: name: common-golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12216,10 +12669,10 @@ metadata: name: common-golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12237,10 +12690,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -12261,10 +12714,10 @@ metadata: name: common-golang-external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12276,10 +12729,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: external-secrets-cert-controller @@ -12294,7 +12747,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.20-ubi imagePullPolicy: IfNotPresent args: - certcontroller @@ -12305,7 +12758,9 @@ spec: - --secret-namespace=default - --metrics-addr=:8080 - --healthz-addr=:8081 - + - --loglevel=info + - --zap-time-encoding=epoch + - --enable-partial-cache=true ports: - containerPort: 8080 protocol: TCP @@ -12324,10 +12779,10 @@ metadata: name: common-golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12339,10 +12794,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: common-golang-external-secrets @@ -12357,15 +12812,18 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.20-ubi imagePullPolicy: IfNotPresent args: - --concurrent=1 - --metrics-addr=:8080 + - --loglevel=info + - --zap-time-encoding=epoch ports: - containerPort: 8080 protocol: TCP name: metrics + dnsPolicy: ClusterFirst --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml apiVersion: apps/v1 @@ -12374,10 +12832,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12389,10 +12847,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: hostNetwork: false @@ -12407,7 +12865,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.20-ubi imagePullPolicy: IfNotPresent args: - webhook @@ -12417,6 +12875,8 @@ spec: - --check-interval=5m - --metrics-addr=:8080 - --healthz-addr=:8081 + - --loglevel=info + - --zap-time-encoding=epoch ports: - containerPort: 8080 protocol: TCP diff --git a/tests/common-golang-external-secrets-naked.expected.yaml b/tests/common-golang-external-secrets-naked.expected.yaml index 3d54dd63..b6a836e9 100644 --- a/tests/common-golang-external-secrets-naked.expected.yaml +++ b/tests/common-golang-external-secrets-naked.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: common-golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -263,7 +265,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -780,11 +784,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -827,11 +833,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -844,7 +852,7 @@ spec: x-kubernetes-map-type: atomic type: array namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelector ends up choosing. + description: Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing. items: type: string type: array @@ -916,7 +924,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2457,6 +2467,11 @@ spec: ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in for a ClusterSecretStore instance. properties: + namespaceRegexes: + description: Choose namespaces by using regex matching + items: + type: string + type: array namespaceSelector: description: Choose namespace using a labelSelector properties: @@ -2484,11 +2499,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -2921,6 +2938,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -3034,6 +3068,63 @@ spec: required: - vaultUrl type: object + bitwardensecretsmanager: + description: BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider + properties: + apiURL: + type: string + auth: + description: |- + Auth configures how secret-manager authenticates with a bitwarden machine account instance. + Make sure that the token being used has permissions on the given secret. + properties: + secretRef: + description: BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance. + properties: + credentials: + description: AccessToken used for the bitwarden instance. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - credentials + type: object + required: + - secretRef + type: object + bitwardenServerSDKURL: + type: string + caBundle: + description: |- + Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack + can be performed. + type: string + identityURL: + type: string + organizationID: + description: OrganizationID determines which organization this secret store manages. + type: string + projectID: + description: ProjectID determines which project this secret store manages. + type: string + required: + - auth + - caBundle + - organizationID + - projectID + type: object chef: description: Chef configures this store to sync secrets with chef server properties: @@ -3295,6 +3386,42 @@ spec: - clientSecret - tenant type: object + device42: + description: Device42 configures this store to sync secrets using the Device42 provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a Device42 instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + host: + description: URL configures the Device42 instance URL. + type: string + required: + - auth + - host + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -3471,6 +3598,9 @@ spec: - serviceAccountRef type: object type: object + location: + description: Location optionally defines a location for a secret + type: string projectID: description: ProjectID project where secret is located type: string @@ -3573,6 +3703,77 @@ spec: required: - auth type: object + infisical: + description: Infisical configures this store to sync secrets using the Infisical provider + properties: + auth: + description: Auth configures how the Operator authenticates with the Infisical API + properties: + universalAuthCredentials: + properties: + clientId: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientSecret: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - clientId + - clientSecret + type: object + type: object + hostAPI: + default: https://app.infisical.com/api + type: string + secretsScope: + properties: + environmentSlug: + type: string + projectSlug: + type: string + secretsPath: + default: / + type: string + required: + - environmentSlug + - projectSlug + type: object + required: + - auth + - secretsScope + type: object keepersecurity: description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider properties: @@ -3697,6 +3898,23 @@ spec: type: object type: object type: object + authRef: + description: A reference to a secret that contains the auth information. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object remoteNamespace: default: default description: Remote namespace to fetch the secrets from @@ -3737,8 +3955,6 @@ spec: description: configures the Kubernetes server Address. type: string type: object - required: - - auth type: object onboardbase: description: Onboardbase configures this store to sync secrets using the Onboardbase provider @@ -5079,7 +5295,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -5246,7 +5464,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -5487,10 +5707,15 @@ spec: description: Binding represents a servicebinding.io Provisioned Service reference to the secret properties: name: + default: "" description: |- Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. type: string type: object x-kubernetes-map-type: atomic @@ -5993,10 +6218,15 @@ spec: description: Binding represents a servicebinding.io Provisioned Service reference to the secret properties: name: + default: "" description: |- Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. type: string type: object x-kubernetes-map-type: atomic @@ -6051,7 +6281,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6127,7 +6359,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6255,7 +6489,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: githubaccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6299,7 +6535,7 @@ spec: auth: description: Auth configures how ESO authenticates with a Github instance. properties: - privatKey: + privateKey: properties: secretRef: description: |- @@ -6324,7 +6560,7 @@ spec: - secretRef type: object required: - - privatKey + - privateKey type: object installID: type: string @@ -6357,7 +6593,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6455,7 +6693,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -6586,11 +6824,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6831,7 +7071,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -8372,6 +8614,11 @@ spec: ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in for a ClusterSecretStore instance. properties: + namespaceRegexes: + description: Choose namespaces by using regex matching + items: + type: string + type: array namespaceSelector: description: Choose namespace using a labelSelector properties: @@ -8399,11 +8646,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8836,6 +9085,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -8949,6 +9215,63 @@ spec: required: - vaultUrl type: object + bitwardensecretsmanager: + description: BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider + properties: + apiURL: + type: string + auth: + description: |- + Auth configures how secret-manager authenticates with a bitwarden machine account instance. + Make sure that the token being used has permissions on the given secret. + properties: + secretRef: + description: BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance. + properties: + credentials: + description: AccessToken used for the bitwarden instance. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - credentials + type: object + required: + - secretRef + type: object + bitwardenServerSDKURL: + type: string + caBundle: + description: |- + Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack + can be performed. + type: string + identityURL: + type: string + organizationID: + description: OrganizationID determines which organization this secret store manages. + type: string + projectID: + description: ProjectID determines which project this secret store manages. + type: string + required: + - auth + - caBundle + - organizationID + - projectID + type: object chef: description: Chef configures this store to sync secrets with chef server properties: @@ -9210,6 +9533,42 @@ spec: - clientSecret - tenant type: object + device42: + description: Device42 configures this store to sync secrets using the Device42 provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a Device42 instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + host: + description: URL configures the Device42 instance URL. + type: string + required: + - auth + - host + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -9386,6 +9745,9 @@ spec: - serviceAccountRef type: object type: object + location: + description: Location optionally defines a location for a secret + type: string projectID: description: ProjectID project where secret is located type: string @@ -9488,6 +9850,77 @@ spec: required: - auth type: object + infisical: + description: Infisical configures this store to sync secrets using the Infisical provider + properties: + auth: + description: Auth configures how the Operator authenticates with the Infisical API + properties: + universalAuthCredentials: + properties: + clientId: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientSecret: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - clientId + - clientSecret + type: object + type: object + hostAPI: + default: https://app.infisical.com/api + type: string + secretsScope: + properties: + environmentSlug: + type: string + projectSlug: + type: string + secretsPath: + default: / + type: string + required: + - environmentSlug + - projectSlug + type: object + required: + - auth + - secretsScope + type: object keepersecurity: description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider properties: @@ -9612,6 +10045,23 @@ spec: type: object type: object type: object + authRef: + description: A reference to a secret that contains the auth information. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object remoteNamespace: default: default description: Remote namespace to fetch the secrets from @@ -9652,8 +10102,6 @@ spec: description: configures the Kubernetes server Address. type: string type: object - required: - - auth type: object onboardbase: description: Onboardbase configures this store to sync secrets using the Onboardbase provider @@ -10994,7 +11442,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11686,7 +12136,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: webhooks.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11834,10 +12286,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11901,10 +12353,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11938,6 +12390,7 @@ rules: - "pushsecrets/status" - "pushsecrets/finalizers" verbs: + - "get" - "update" - "patch" - apiGroups: @@ -12012,10 +12465,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -12054,10 +12507,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -12100,10 +12553,10 @@ metadata: name: common-golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12121,10 +12574,10 @@ kind: ClusterRoleBinding metadata: name: common-golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12141,10 +12594,10 @@ kind: ClusterRoleBinding metadata: name: common-golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12177,10 +12630,10 @@ metadata: name: common-golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12216,10 +12669,10 @@ metadata: name: common-golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12237,10 +12690,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -12261,10 +12714,10 @@ metadata: name: common-golang-external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12276,10 +12729,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: external-secrets-cert-controller @@ -12294,7 +12747,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.20-ubi imagePullPolicy: IfNotPresent args: - certcontroller @@ -12305,7 +12758,9 @@ spec: - --secret-namespace=default - --metrics-addr=:8080 - --healthz-addr=:8081 - + - --loglevel=info + - --zap-time-encoding=epoch + - --enable-partial-cache=true ports: - containerPort: 8080 protocol: TCP @@ -12324,10 +12779,10 @@ metadata: name: common-golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12339,10 +12794,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: common-golang-external-secrets @@ -12357,15 +12812,18 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.20-ubi imagePullPolicy: IfNotPresent args: - --concurrent=1 - --metrics-addr=:8080 + - --loglevel=info + - --zap-time-encoding=epoch ports: - containerPort: 8080 protocol: TCP name: metrics + dnsPolicy: ClusterFirst --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml apiVersion: apps/v1 @@ -12374,10 +12832,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12389,10 +12847,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: hostNetwork: false @@ -12407,7 +12865,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.20-ubi imagePullPolicy: IfNotPresent args: - webhook @@ -12417,6 +12875,8 @@ spec: - --check-interval=5m - --metrics-addr=:8080 - --healthz-addr=:8081 + - --loglevel=info + - --zap-time-encoding=epoch ports: - containerPort: 8080 protocol: TCP diff --git a/tests/common-golang-external-secrets-normal.expected.yaml b/tests/common-golang-external-secrets-normal.expected.yaml index a0ad351a..b7c2ad96 100644 --- a/tests/common-golang-external-secrets-normal.expected.yaml +++ b/tests/common-golang-external-secrets-normal.expected.yaml @@ -6,10 +6,10 @@ metadata: name: external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/serviceaccount.yaml @@ -19,10 +19,10 @@ metadata: name: common-golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-serviceaccount.yaml @@ -32,10 +32,10 @@ metadata: name: external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-secret.yaml @@ -45,10 +45,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook --- @@ -67,7 +67,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: acraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -263,7 +265,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: clusterexternalsecrets.external-secrets.io spec: group: external-secrets.io @@ -780,11 +784,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -827,11 +833,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -844,7 +852,7 @@ spec: x-kubernetes-map-type: atomic type: array namespaces: - description: Choose namespaces by name. This field is ORed with anything that NamespaceSelector ends up choosing. + description: Choose namespaces by name. This field is ORed with anything that NamespaceSelectors ends up choosing. items: type: string type: array @@ -916,7 +924,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: clustersecretstores.external-secrets.io spec: group: external-secrets.io @@ -2457,6 +2467,11 @@ spec: ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in for a ClusterSecretStore instance. properties: + namespaceRegexes: + description: Choose namespaces by using regex matching + items: + type: string + type: array namespaceSelector: description: Choose namespace using a labelSelector properties: @@ -2484,11 +2499,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -2921,6 +2938,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -3034,6 +3068,63 @@ spec: required: - vaultUrl type: object + bitwardensecretsmanager: + description: BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider + properties: + apiURL: + type: string + auth: + description: |- + Auth configures how secret-manager authenticates with a bitwarden machine account instance. + Make sure that the token being used has permissions on the given secret. + properties: + secretRef: + description: BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance. + properties: + credentials: + description: AccessToken used for the bitwarden instance. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - credentials + type: object + required: + - secretRef + type: object + bitwardenServerSDKURL: + type: string + caBundle: + description: |- + Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack + can be performed. + type: string + identityURL: + type: string + organizationID: + description: OrganizationID determines which organization this secret store manages. + type: string + projectID: + description: ProjectID determines which project this secret store manages. + type: string + required: + - auth + - caBundle + - organizationID + - projectID + type: object chef: description: Chef configures this store to sync secrets with chef server properties: @@ -3295,6 +3386,42 @@ spec: - clientSecret - tenant type: object + device42: + description: Device42 configures this store to sync secrets using the Device42 provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a Device42 instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + host: + description: URL configures the Device42 instance URL. + type: string + required: + - auth + - host + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -3471,6 +3598,9 @@ spec: - serviceAccountRef type: object type: object + location: + description: Location optionally defines a location for a secret + type: string projectID: description: ProjectID project where secret is located type: string @@ -3573,6 +3703,77 @@ spec: required: - auth type: object + infisical: + description: Infisical configures this store to sync secrets using the Infisical provider + properties: + auth: + description: Auth configures how the Operator authenticates with the Infisical API + properties: + universalAuthCredentials: + properties: + clientId: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientSecret: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - clientId + - clientSecret + type: object + type: object + hostAPI: + default: https://app.infisical.com/api + type: string + secretsScope: + properties: + environmentSlug: + type: string + projectSlug: + type: string + secretsPath: + default: / + type: string + required: + - environmentSlug + - projectSlug + type: object + required: + - auth + - secretsScope + type: object keepersecurity: description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider properties: @@ -3697,6 +3898,23 @@ spec: type: object type: object type: object + authRef: + description: A reference to a secret that contains the auth information. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object remoteNamespace: default: default description: Remote namespace to fetch the secrets from @@ -3737,8 +3955,6 @@ spec: description: configures the Kubernetes server Address. type: string type: object - required: - - auth type: object onboardbase: description: Onboardbase configures this store to sync secrets using the Onboardbase provider @@ -5079,7 +5295,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: ecrauthorizationtokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -5246,7 +5464,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: externalsecrets.external-secrets.io spec: group: external-secrets.io @@ -5487,10 +5707,15 @@ spec: description: Binding represents a servicebinding.io Provisioned Service reference to the secret properties: name: + default: "" description: |- Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. type: string type: object x-kubernetes-map-type: atomic @@ -5993,10 +6218,15 @@ spec: description: Binding represents a servicebinding.io Provisioned Service reference to the secret properties: name: + default: "" description: |- Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. TODO: Add other useful fields. apiVersion, kind, uid? + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Drop `kubebuilder:default` when controller-gen doesn't need it https://github.com/kubernetes-sigs/kubebuilder/issues/3896. type: string type: object x-kubernetes-map-type: atomic @@ -6051,7 +6281,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: fakes.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6127,7 +6359,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: gcraccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6255,7 +6489,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: githubaccesstokens.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6299,7 +6535,7 @@ spec: auth: description: Auth configures how ESO authenticates with a Github instance. properties: - privatKey: + privateKey: properties: secretRef: description: |- @@ -6324,7 +6560,7 @@ spec: - secretRef type: object required: - - privatKey + - privateKey type: object installID: type: string @@ -6357,7 +6593,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: passwords.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -6455,7 +6693,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 name: pushsecrets.external-secrets.io spec: group: external-secrets.io @@ -6586,11 +6824,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6831,7 +7071,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: secretstores.external-secrets.io spec: group: external-secrets.io @@ -8372,6 +8614,11 @@ spec: ClusterSecretStoreCondition describes a condition by which to choose namespaces to process ExternalSecrets in for a ClusterSecretStore instance. properties: + namespaceRegexes: + description: Choose namespaces by using regex matching + items: + type: string + type: array namespaceSelector: description: Choose namespace using a labelSelector properties: @@ -8399,11 +8646,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8836,6 +9085,23 @@ spec: authSecretRef: description: Auth configures how the operator authenticates with Azure. Required for ServicePrincipal auth type. Optional for WorkloadIdentity. properties: + clientCertificate: + description: The Azure ClientCertificate of the service principle used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object clientId: description: The Azure clientId of the service principle or managed identity used for authentication. properties: @@ -8949,6 +9215,63 @@ spec: required: - vaultUrl type: object + bitwardensecretsmanager: + description: BitwardenSecretsManager configures this store to sync secrets using BitwardenSecretsManager provider + properties: + apiURL: + type: string + auth: + description: |- + Auth configures how secret-manager authenticates with a bitwarden machine account instance. + Make sure that the token being used has permissions on the given secret. + properties: + secretRef: + description: BitwardenSecretsManagerSecretRef contains the credential ref to the bitwarden instance. + properties: + credentials: + description: AccessToken used for the bitwarden instance. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - credentials + type: object + required: + - secretRef + type: object + bitwardenServerSDKURL: + type: string + caBundle: + description: |- + Base64 encoded certificate for the bitwarden server sdk. The sdk MUST run with HTTPS to make sure no MITM attack + can be performed. + type: string + identityURL: + type: string + organizationID: + description: OrganizationID determines which organization this secret store manages. + type: string + projectID: + description: ProjectID determines which project this secret store manages. + type: string + required: + - auth + - caBundle + - organizationID + - projectID + type: object chef: description: Chef configures this store to sync secrets with chef server properties: @@ -9210,6 +9533,42 @@ spec: - clientSecret - tenant type: object + device42: + description: Device42 configures this store to sync secrets using the Device42 provider + properties: + auth: + description: Auth configures how secret-manager authenticates with a Device42 instance. + properties: + secretRef: + properties: + credentials: + description: Username / Password is used for authentication. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + type: object + required: + - secretRef + type: object + host: + description: URL configures the Device42 instance URL. + type: string + required: + - auth + - host + type: object doppler: description: Doppler configures this store to sync secrets using the Doppler provider properties: @@ -9386,6 +9745,9 @@ spec: - serviceAccountRef type: object type: object + location: + description: Location optionally defines a location for a secret + type: string projectID: description: ProjectID project where secret is located type: string @@ -9488,6 +9850,77 @@ spec: required: - auth type: object + infisical: + description: Infisical configures this store to sync secrets using the Infisical provider + properties: + auth: + description: Auth configures how the Operator authenticates with the Infisical API + properties: + universalAuthCredentials: + properties: + clientId: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + clientSecret: + description: |- + A reference to a specific 'key' within a Secret resource, + In some instances, `key` is a required field. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object + required: + - clientId + - clientSecret + type: object + type: object + hostAPI: + default: https://app.infisical.com/api + type: string + secretsScope: + properties: + environmentSlug: + type: string + projectSlug: + type: string + secretsPath: + default: / + type: string + required: + - environmentSlug + - projectSlug + type: object + required: + - auth + - secretsScope + type: object keepersecurity: description: KeeperSecurity configures this store to sync secrets using the KeeperSecurity provider properties: @@ -9612,6 +10045,23 @@ spec: type: object type: object type: object + authRef: + description: A reference to a secret that contains the auth information. + properties: + key: + description: |- + The key of the entry in the Secret resource's `data` field to be used. Some instances of this field may be + defaulted, in others it may be required. + type: string + name: + description: The name of the Secret resource being referred to. + type: string + namespace: + description: |- + Namespace of the resource being referred to. Ignored if referent is not cluster-scoped. cluster-scoped defaults + to the namespace of the referent. + type: string + type: object remoteNamespace: default: default description: Remote namespace to fetch the secrets from @@ -9652,8 +10102,6 @@ spec: description: configures the Kubernetes server Address. type: string type: object - required: - - auth type: object onboardbase: description: Onboardbase configures this store to sync secrets using the Onboardbase provider @@ -10994,7 +11442,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: vaultdynamicsecrets.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11686,7 +12136,9 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.14.0 + controller-gen.kubebuilder.io/version: v0.15.0 + labels: + external-secrets.io/component: controller name: webhooks.generators.external-secrets.io spec: group: generators.external-secrets.io @@ -11834,10 +12286,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11901,10 +12353,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -11938,6 +12390,7 @@ rules: - "pushsecrets/status" - "pushsecrets/finalizers" verbs: + - "get" - "update" - "patch" - apiGroups: @@ -12012,10 +12465,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-view labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-view: "true" rbac.authorization.k8s.io/aggregate-to-edit: "true" @@ -12054,10 +12507,10 @@ kind: ClusterRole metadata: name: common-golang-external-secrets-edit labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rbac.authorization.k8s.io/aggregate-to-edit: "true" rbac.authorization.k8s.io/aggregate-to-admin: "true" @@ -12100,10 +12553,10 @@ metadata: name: common-golang-external-secrets-servicebindings labels: servicebinding.io/controller: "true" - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12121,10 +12574,10 @@ kind: ClusterRoleBinding metadata: name: common-golang-external-secrets-cert-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12141,10 +12594,10 @@ kind: ClusterRoleBinding metadata: name: common-golang-external-secrets-controller labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12177,10 +12630,10 @@ metadata: name: common-golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm rules: - apiGroups: @@ -12216,10 +12669,10 @@ metadata: name: common-golang-external-secrets-leaderelection namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm roleRef: apiGroup: rbac.authorization.k8s.io @@ -12237,10 +12690,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm external-secrets.io/component: webhook spec: @@ -12261,10 +12714,10 @@ metadata: name: common-golang-external-secrets-cert-controller namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12276,10 +12729,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-cert-controller app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: external-secrets-cert-controller @@ -12294,7 +12747,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.20-ubi imagePullPolicy: IfNotPresent args: - certcontroller @@ -12305,7 +12758,9 @@ spec: - --secret-namespace=default - --metrics-addr=:8080 - --healthz-addr=:8081 - + - --loglevel=info + - --zap-time-encoding=epoch + - --enable-partial-cache=true ports: - containerPort: 8080 protocol: TCP @@ -12324,10 +12779,10 @@ metadata: name: common-golang-external-secrets namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12339,10 +12794,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: serviceAccountName: common-golang-external-secrets @@ -12357,15 +12812,18 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.20-ubi imagePullPolicy: IfNotPresent args: - --concurrent=1 - --metrics-addr=:8080 + - --loglevel=info + - --zap-time-encoding=epoch ports: - containerPort: 8080 protocol: TCP name: metrics + dnsPolicy: ClusterFirst --- # Source: golang-external-secrets/charts/external-secrets/templates/webhook-deployment.yaml apiVersion: apps/v1 @@ -12374,10 +12832,10 @@ metadata: name: common-golang-external-secrets-webhook namespace: default labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: replicas: 1 @@ -12389,10 +12847,10 @@ spec: template: metadata: labels: - helm.sh/chart: external-secrets-0.9.16 + helm.sh/chart: external-secrets-0.9.20 app.kubernetes.io/name: external-secrets-webhook app.kubernetes.io/instance: common-golang-external-secrets - app.kubernetes.io/version: "v0.9.16" + app.kubernetes.io/version: "v0.9.20" app.kubernetes.io/managed-by: Helm spec: hostNetwork: false @@ -12407,7 +12865,7 @@ spec: - ALL readOnlyRootFilesystem: true runAsNonRoot: true - image: ghcr.io/external-secrets/external-secrets:v0.9.16-ubi + image: ghcr.io/external-secrets/external-secrets:v0.9.20-ubi imagePullPolicy: IfNotPresent args: - webhook @@ -12417,6 +12875,8 @@ spec: - --check-interval=5m - --metrics-addr=:8080 - --healthz-addr=:8081 + - --loglevel=info + - --zap-time-encoding=epoch ports: - containerPort: 8080 protocol: TCP diff --git a/tests/common-hashicorp-vault-industrial-edge-factory.expected.yaml b/tests/common-hashicorp-vault-industrial-edge-factory.expected.yaml index 9838c4a7..19cef108 100644 --- a/tests/common-hashicorp-vault-industrial-edge-factory.expected.yaml +++ b/tests/common-hashicorp-vault-industrial-edge-factory.expected.yaml @@ -6,7 +6,7 @@ metadata: name: common-hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -18,7 +18,7 @@ metadata: name: common-hashicorp-vault-config namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -43,7 +43,7 @@ kind: ClusterRoleBinding metadata: name: common-hashicorp-vault-server-binding labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -64,7 +64,7 @@ metadata: name: common-hashicorp-vault-internal namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -96,7 +96,7 @@ metadata: name: common-hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -127,7 +127,7 @@ metadata: name: common-hashicorp-vault-ui namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault-ui app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -168,7 +168,7 @@ spec: template: metadata: labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault component: server @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -348,7 +348,7 @@ metadata: name: common-hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -375,7 +375,7 @@ spec: containers: - name: common-hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/common-hashicorp-vault-industrial-edge-hub.expected.yaml b/tests/common-hashicorp-vault-industrial-edge-hub.expected.yaml index 9838c4a7..19cef108 100644 --- a/tests/common-hashicorp-vault-industrial-edge-hub.expected.yaml +++ b/tests/common-hashicorp-vault-industrial-edge-hub.expected.yaml @@ -6,7 +6,7 @@ metadata: name: common-hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -18,7 +18,7 @@ metadata: name: common-hashicorp-vault-config namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -43,7 +43,7 @@ kind: ClusterRoleBinding metadata: name: common-hashicorp-vault-server-binding labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -64,7 +64,7 @@ metadata: name: common-hashicorp-vault-internal namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -96,7 +96,7 @@ metadata: name: common-hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -127,7 +127,7 @@ metadata: name: common-hashicorp-vault-ui namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault-ui app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -168,7 +168,7 @@ spec: template: metadata: labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault component: server @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -348,7 +348,7 @@ metadata: name: common-hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -375,7 +375,7 @@ spec: containers: - name: common-hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/common-hashicorp-vault-medical-diagnosis-hub.expected.yaml b/tests/common-hashicorp-vault-medical-diagnosis-hub.expected.yaml index 9838c4a7..19cef108 100644 --- a/tests/common-hashicorp-vault-medical-diagnosis-hub.expected.yaml +++ b/tests/common-hashicorp-vault-medical-diagnosis-hub.expected.yaml @@ -6,7 +6,7 @@ metadata: name: common-hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -18,7 +18,7 @@ metadata: name: common-hashicorp-vault-config namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -43,7 +43,7 @@ kind: ClusterRoleBinding metadata: name: common-hashicorp-vault-server-binding labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -64,7 +64,7 @@ metadata: name: common-hashicorp-vault-internal namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -96,7 +96,7 @@ metadata: name: common-hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -127,7 +127,7 @@ metadata: name: common-hashicorp-vault-ui namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault-ui app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -168,7 +168,7 @@ spec: template: metadata: labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault component: server @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -348,7 +348,7 @@ metadata: name: common-hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -375,7 +375,7 @@ spec: containers: - name: common-hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/common-hashicorp-vault-naked.expected.yaml b/tests/common-hashicorp-vault-naked.expected.yaml index e6933c44..1a62b9c0 100644 --- a/tests/common-hashicorp-vault-naked.expected.yaml +++ b/tests/common-hashicorp-vault-naked.expected.yaml @@ -6,7 +6,7 @@ metadata: name: common-hashicorp-vault namespace: default labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -18,7 +18,7 @@ metadata: name: common-hashicorp-vault-config namespace: default labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -43,7 +43,7 @@ kind: ClusterRoleBinding metadata: name: common-hashicorp-vault-server-binding labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -64,7 +64,7 @@ metadata: name: common-hashicorp-vault-internal namespace: default labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -96,7 +96,7 @@ metadata: name: common-hashicorp-vault namespace: default labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -127,7 +127,7 @@ metadata: name: common-hashicorp-vault-ui namespace: default labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault-ui app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -168,7 +168,7 @@ spec: template: metadata: labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault component: server @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -348,7 +348,7 @@ metadata: name: common-hashicorp-vault namespace: default labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -375,7 +375,7 @@ spec: containers: - name: common-hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/common-hashicorp-vault-normal.expected.yaml b/tests/common-hashicorp-vault-normal.expected.yaml index 9838c4a7..19cef108 100644 --- a/tests/common-hashicorp-vault-normal.expected.yaml +++ b/tests/common-hashicorp-vault-normal.expected.yaml @@ -6,7 +6,7 @@ metadata: name: common-hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -18,7 +18,7 @@ metadata: name: common-hashicorp-vault-config namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -43,7 +43,7 @@ kind: ClusterRoleBinding metadata: name: common-hashicorp-vault-server-binding labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -64,7 +64,7 @@ metadata: name: common-hashicorp-vault-internal namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -96,7 +96,7 @@ metadata: name: common-hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -127,7 +127,7 @@ metadata: name: common-hashicorp-vault-ui namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault-ui app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -168,7 +168,7 @@ spec: template: metadata: labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault component: server @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -348,7 +348,7 @@ metadata: name: common-hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: common-hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -375,7 +375,7 @@ spec: containers: - name: common-hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.1-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/common-operator-install-industrial-edge-factory.expected.yaml b/tests/common-operator-install-industrial-edge-factory.expected.yaml index b04d071e..755b244f 100644 --- a/tests/common-operator-install-industrial-edge-factory.expected.yaml +++ b/tests/common-operator-install-industrial-edge-factory.expected.yaml @@ -25,9 +25,6 @@ spec: gitSpec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main - gitOpsSpec: - operatorChannel: gitops-1.12 - operatorSource: redhat-operators multiSourceConfig: enabled: false --- diff --git a/tests/common-operator-install-industrial-edge-hub.expected.yaml b/tests/common-operator-install-industrial-edge-hub.expected.yaml index b04d071e..755b244f 100644 --- a/tests/common-operator-install-industrial-edge-hub.expected.yaml +++ b/tests/common-operator-install-industrial-edge-hub.expected.yaml @@ -25,9 +25,6 @@ spec: gitSpec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main - gitOpsSpec: - operatorChannel: gitops-1.12 - operatorSource: redhat-operators multiSourceConfig: enabled: false --- diff --git a/tests/common-operator-install-medical-diagnosis-hub.expected.yaml b/tests/common-operator-install-medical-diagnosis-hub.expected.yaml index b04d071e..755b244f 100644 --- a/tests/common-operator-install-medical-diagnosis-hub.expected.yaml +++ b/tests/common-operator-install-medical-diagnosis-hub.expected.yaml @@ -25,9 +25,6 @@ spec: gitSpec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main - gitOpsSpec: - operatorChannel: gitops-1.12 - operatorSource: redhat-operators multiSourceConfig: enabled: false --- diff --git a/tests/common-operator-install-naked.expected.yaml b/tests/common-operator-install-naked.expected.yaml index ada9ab18..937fb6a2 100644 --- a/tests/common-operator-install-naked.expected.yaml +++ b/tests/common-operator-install-naked.expected.yaml @@ -25,9 +25,6 @@ spec: gitSpec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main - gitOpsSpec: - operatorChannel: gitops-1.12 - operatorSource: redhat-operators multiSourceConfig: enabled: false --- diff --git a/tests/common-operator-install-normal.expected.yaml b/tests/common-operator-install-normal.expected.yaml index b04d071e..755b244f 100644 --- a/tests/common-operator-install-normal.expected.yaml +++ b/tests/common-operator-install-normal.expected.yaml @@ -25,9 +25,6 @@ spec: gitSpec: targetRepo: https://github.com/pattern-clone/mypattern targetRevision: main - gitOpsSpec: - operatorChannel: gitops-1.12 - operatorSource: redhat-operators multiSourceConfig: enabled: false --- From 0c0a1f545516c8cae62ac44890c6bd2efdfeeb36 Mon Sep 17 00:00:00 2001 From: Martin Jackson Date: Mon, 29 Jul 2024 08:49:29 -0500 Subject: [PATCH 74/77] Discover blockdevices and securitygroups for greater compatibility --- ansible/deploy_kubevirt_worker.yml | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/ansible/deploy_kubevirt_worker.yml b/ansible/deploy_kubevirt_worker.yml index 756ec048..4b854f53 100644 --- a/ansible/deploy_kubevirt_worker.yml +++ b/ansible/deploy_kubevirt_worker.yml @@ -7,11 +7,6 @@ gather_facts: false vars: kubeconfig: "{{ lookup('env', 'KUBECONFIG') }}" - machineset_blockdevices: - - ebs: - iops: 0 - volumeSize: 120 - volumeType: gp2 machineset_instance_type: m5.metal machineset_machine_role: worker machineset_machine_type: worker @@ -47,6 +42,8 @@ machineset_ami_id: "{{ cluster_machinesets.resources[0].spec.template.spec.providerSpec.value.ami.id }}" machineset_subnet: "{{ cluster_machinesets.resources[0].spec.template.spec.providerSpec.value.subnet.filters[0]['values'][0] }}" machineset_tags: "{{ cluster_machinesets.resources[0].spec.template.spec.providerSpec.value.tags }}" + machineset_blockdevices: "{{ cluster_machinesets.resources[0].spec.template.spec.providerSpec.value.blockDevices }}" + machineset_securitygroups: "{{ cluster_machinesets.resources[0].spec.template.spec.providerSpec.value.securityGroups }}" machineset_zone: "{{ cluster_machinesets.resources[0].spec.template.spec.providerSpec.value.placement.availabilityZone }}" infrastructure_name: "{{ cluster_info.resources[0].status.infrastructureName }}" infrastructure_region: "{{ cluster_info.resources[0].status.platformStatus.aws.region }}" @@ -97,11 +94,7 @@ placement: availabilityZone: "{{ machineset_zone }}" region: "{{ infrastructure_region }}" - securityGroups: - - filters: - - name: tag:Name - values: - - "{{ infrastructure_name }}-worker-sg" + securityGroups: {{ machineset_securitygroups }} subnet: filters: - name: tag:Name From 832ba345e57f8e729707f2e8c098f74b3898114c Mon Sep 17 00:00:00 2001 From: Martin Jackson Date: Mon, 29 Jul 2024 09:01:57 -0500 Subject: [PATCH 75/77] Update Changes in anticipation of v1.4 branch --- Changes.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Changes.md b/Changes.md index ce1d1036..b08b2710 100644 --- a/Changes.md +++ b/Changes.md @@ -43,8 +43,10 @@ * Update platform level override using new templated valuefile name feature in common * Skip multicloud gateway (noobaa) installation in ODF by default -## Changes in main (July 25, 2024) +## Changes for v1.4 (July 29, 2024) * Introduce clean-golden-images job to imperative. This is a workaround for a bug in CNV 4.15/ODF 4.15 where if the default StorageClass is not the same as the default virtualization storage class, CNV cannot properly provision datavolumes. * Default storageclass for edge-gitops-vms to "ocs-storagecluster-ceph-rbd-virtualization", available since ODF 4.14. * Use api_version for Route queries when discovering credentials for AAP instance. +* Update common. +* Update deploy_kubevirt_worker.yml Ansible playbook to copy securityGroups and blockDevices config from first machineSet. Tag naming schemes changed from OCP 4.15 to 4.16; this method ensures forward and backward compatibility. From e4b85059b79310ba5e6d0905a391609089cb7fda Mon Sep 17 00:00:00 2001 From: Martin Jackson Date: Mon, 29 Jul 2024 10:02:48 -0500 Subject: [PATCH 76/77] Add 0 to make log prettier --- charts/hub/edge-gitops-vms/templates/job-waitForMetalNode.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/charts/hub/edge-gitops-vms/templates/job-waitForMetalNode.yaml b/charts/hub/edge-gitops-vms/templates/job-waitForMetalNode.yaml index 0318004d..c60c90fb 100644 --- a/charts/hub/edge-gitops-vms/templates/job-waitForMetalNode.yaml +++ b/charts/hub/edge-gitops-vms/templates/job-waitForMetalNode.yaml @@ -18,7 +18,7 @@ spec: while [ 1 ]; do nodes=$(oc get machineset -n openshift-machine-api -l 'edge-gitops-role=kubevirt-worker' -o jsonpath='{.items[*].status.availableReplicas}') - if [ "$nodes" -ge "1" ]; then + if [ "0$nodes" -ge "1" ]; then echo "Node is ready, exiting" exit 0 fi From c85b811cd347213c1b20449a44a612dc9783c430 Mon Sep 17 00:00:00 2001 From: Martin Jackson Date: Mon, 29 Jul 2024 10:14:04 -0500 Subject: [PATCH 77/77] Update tests --- tests/hub-edge-gitops-vms-industrial-edge-factory.expected.yaml | 2 +- tests/hub-edge-gitops-vms-industrial-edge-hub.expected.yaml | 2 +- tests/hub-edge-gitops-vms-medical-diagnosis-hub.expected.yaml | 2 +- tests/hub-edge-gitops-vms-naked.expected.yaml | 2 +- tests/hub-edge-gitops-vms-normal.expected.yaml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/hub-edge-gitops-vms-industrial-edge-factory.expected.yaml b/tests/hub-edge-gitops-vms-industrial-edge-factory.expected.yaml index a9761701..dd291d51 100644 --- a/tests/hub-edge-gitops-vms-industrial-edge-factory.expected.yaml +++ b/tests/hub-edge-gitops-vms-industrial-edge-factory.expected.yaml @@ -63,7 +63,7 @@ spec: while [ 1 ]; do nodes=$(oc get machineset -n openshift-machine-api -l 'edge-gitops-role=kubevirt-worker' -o jsonpath='{.items[*].status.availableReplicas}') - if [ "$nodes" -ge "1" ]; then + if [ "0$nodes" -ge "1" ]; then echo "Node is ready, exiting" exit 0 fi diff --git a/tests/hub-edge-gitops-vms-industrial-edge-hub.expected.yaml b/tests/hub-edge-gitops-vms-industrial-edge-hub.expected.yaml index a9761701..dd291d51 100644 --- a/tests/hub-edge-gitops-vms-industrial-edge-hub.expected.yaml +++ b/tests/hub-edge-gitops-vms-industrial-edge-hub.expected.yaml @@ -63,7 +63,7 @@ spec: while [ 1 ]; do nodes=$(oc get machineset -n openshift-machine-api -l 'edge-gitops-role=kubevirt-worker' -o jsonpath='{.items[*].status.availableReplicas}') - if [ "$nodes" -ge "1" ]; then + if [ "0$nodes" -ge "1" ]; then echo "Node is ready, exiting" exit 0 fi diff --git a/tests/hub-edge-gitops-vms-medical-diagnosis-hub.expected.yaml b/tests/hub-edge-gitops-vms-medical-diagnosis-hub.expected.yaml index a9761701..dd291d51 100644 --- a/tests/hub-edge-gitops-vms-medical-diagnosis-hub.expected.yaml +++ b/tests/hub-edge-gitops-vms-medical-diagnosis-hub.expected.yaml @@ -63,7 +63,7 @@ spec: while [ 1 ]; do nodes=$(oc get machineset -n openshift-machine-api -l 'edge-gitops-role=kubevirt-worker' -o jsonpath='{.items[*].status.availableReplicas}') - if [ "$nodes" -ge "1" ]; then + if [ "0$nodes" -ge "1" ]; then echo "Node is ready, exiting" exit 0 fi diff --git a/tests/hub-edge-gitops-vms-naked.expected.yaml b/tests/hub-edge-gitops-vms-naked.expected.yaml index a9761701..dd291d51 100644 --- a/tests/hub-edge-gitops-vms-naked.expected.yaml +++ b/tests/hub-edge-gitops-vms-naked.expected.yaml @@ -63,7 +63,7 @@ spec: while [ 1 ]; do nodes=$(oc get machineset -n openshift-machine-api -l 'edge-gitops-role=kubevirt-worker' -o jsonpath='{.items[*].status.availableReplicas}') - if [ "$nodes" -ge "1" ]; then + if [ "0$nodes" -ge "1" ]; then echo "Node is ready, exiting" exit 0 fi diff --git a/tests/hub-edge-gitops-vms-normal.expected.yaml b/tests/hub-edge-gitops-vms-normal.expected.yaml index a9761701..dd291d51 100644 --- a/tests/hub-edge-gitops-vms-normal.expected.yaml +++ b/tests/hub-edge-gitops-vms-normal.expected.yaml @@ -63,7 +63,7 @@ spec: while [ 1 ]; do nodes=$(oc get machineset -n openshift-machine-api -l 'edge-gitops-role=kubevirt-worker' -o jsonpath='{.items[*].status.availableReplicas}') - if [ "$nodes" -ge "1" ]; then + if [ "0$nodes" -ge "1" ]; then echo "Node is ready, exiting" exit 0 fi

e9?vX&2{P`z*yEQ@&1J8iL1Z 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 Ls1SjK0N4Zo6jePG diff --git a/hashicorp-vault/charts/vault-0.28.1.tgz b/hashicorp-vault/charts/vault-0.28.1.tgz new file mode 100644 index 0000000000000000000000000000000000000000..ef0f05f52e28759a71fd4a2f08aa88d239748ec8 GIT binary patch literal 49807 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 z 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 N=){|%&2WQ-0RUykeRBW+ literal 0 HcmV?d00001 diff --git a/hashicorp-vault/values.yaml b/hashicorp-vault/values.yaml index 691f7094..6029a2f0 100644 --- a/hashicorp-vault/values.yaml +++ b/hashicorp-vault/values.yaml @@ -48,4 +48,4 @@ vault: termination: "reencrypt" image: repository: "registry.connect.redhat.com/hashicorp/vault" - tag: "1.16.2-ubi" + tag: "1.17.2-ubi" diff --git a/tests/hashicorp-vault-industrial-edge-factory.expected.yaml b/tests/hashicorp-vault-industrial-edge-factory.expected.yaml index 8156e2af..a17a6974 100644 --- a/tests/hashicorp-vault-industrial-edge-factory.expected.yaml +++ b/tests/hashicorp-vault-industrial-edge-factory.expected.yaml @@ -6,7 +6,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -18,7 +18,7 @@ metadata: name: hashicorp-vault-config namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -43,7 +43,7 @@ kind: ClusterRoleBinding metadata: name: hashicorp-vault-server-binding labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -64,7 +64,7 @@ metadata: name: hashicorp-vault-internal namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -96,7 +96,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -127,7 +127,7 @@ metadata: name: hashicorp-vault-ui namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault-ui app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -168,7 +168,7 @@ spec: template: metadata: labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault component: server @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -348,7 +348,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-industrial-edge-hub.expected.yaml b/tests/hashicorp-vault-industrial-edge-hub.expected.yaml index 8156e2af..a17a6974 100644 --- a/tests/hashicorp-vault-industrial-edge-hub.expected.yaml +++ b/tests/hashicorp-vault-industrial-edge-hub.expected.yaml @@ -6,7 +6,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -18,7 +18,7 @@ metadata: name: hashicorp-vault-config namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -43,7 +43,7 @@ kind: ClusterRoleBinding metadata: name: hashicorp-vault-server-binding labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -64,7 +64,7 @@ metadata: name: hashicorp-vault-internal namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -96,7 +96,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -127,7 +127,7 @@ metadata: name: hashicorp-vault-ui namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault-ui app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -168,7 +168,7 @@ spec: template: metadata: labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault component: server @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -348,7 +348,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml b/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml index 8156e2af..a17a6974 100644 --- a/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml +++ b/tests/hashicorp-vault-medical-diagnosis-hub.expected.yaml @@ -6,7 +6,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -18,7 +18,7 @@ metadata: name: hashicorp-vault-config namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -43,7 +43,7 @@ kind: ClusterRoleBinding metadata: name: hashicorp-vault-server-binding labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -64,7 +64,7 @@ metadata: name: hashicorp-vault-internal namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -96,7 +96,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -127,7 +127,7 @@ metadata: name: hashicorp-vault-ui namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault-ui app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -168,7 +168,7 @@ spec: template: metadata: labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault component: server @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -348,7 +348,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-naked.expected.yaml b/tests/hashicorp-vault-naked.expected.yaml index 8727ef0e..c3950b6d 100644 --- a/tests/hashicorp-vault-naked.expected.yaml +++ b/tests/hashicorp-vault-naked.expected.yaml @@ -6,7 +6,7 @@ metadata: name: hashicorp-vault namespace: default labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -18,7 +18,7 @@ metadata: name: hashicorp-vault-config namespace: default labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -43,7 +43,7 @@ kind: ClusterRoleBinding metadata: name: hashicorp-vault-server-binding labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -64,7 +64,7 @@ metadata: name: hashicorp-vault-internal namespace: default labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -96,7 +96,7 @@ metadata: name: hashicorp-vault namespace: default labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -127,7 +127,7 @@ metadata: name: hashicorp-vault-ui namespace: default labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault-ui app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -168,7 +168,7 @@ spec: template: metadata: labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault component: server @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -348,7 +348,7 @@ metadata: name: hashicorp-vault namespace: default labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR diff --git a/tests/hashicorp-vault-normal.expected.yaml b/tests/hashicorp-vault-normal.expected.yaml index 8156e2af..a17a6974 100644 --- a/tests/hashicorp-vault-normal.expected.yaml +++ b/tests/hashicorp-vault-normal.expected.yaml @@ -6,7 +6,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -18,7 +18,7 @@ metadata: name: hashicorp-vault-config namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -43,7 +43,7 @@ kind: ClusterRoleBinding metadata: name: hashicorp-vault-server-binding labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -64,7 +64,7 @@ metadata: name: hashicorp-vault-internal namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -96,7 +96,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -127,7 +127,7 @@ metadata: name: hashicorp-vault-ui namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault-ui app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -168,7 +168,7 @@ spec: template: metadata: labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault component: server @@ -206,7 +206,7 @@ spec: containers: - name: vault - image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent command: - "/bin/sh" @@ -348,7 +348,7 @@ metadata: name: hashicorp-vault namespace: pattern-namespace labels: - helm.sh/chart: vault-0.28.0 + helm.sh/chart: vault-0.28.1 app.kubernetes.io/name: vault app.kubernetes.io/instance: hashicorp-vault app.kubernetes.io/managed-by: Helm @@ -375,7 +375,7 @@ spec: containers: - name: hashicorp-vault-server-test - image: registry.connect.redhat.com/hashicorp/vault:1.16.2-ubi + image: registry.connect.redhat.com/hashicorp/vault:1.17.2-ubi imagePullPolicy: IfNotPresent env: - name: VAULT_ADDR From 0b45eeada9359aeb447301799206859228dc4f2f Mon Sep 17 00:00:00 2001 From: Michele Baldessari Date: Mon, 15 Jul 2024 11:20:54 -0600 Subject: [PATCH 71/77] Update ESO to 0.9.20 --- golang-external-secrets/Chart.yaml | 2 +- .../charts/external-secrets-0.9.19.tgz | Bin 76457 -> 0 bytes .../charts/external-secrets-0.9.20.tgz | Bin 0 -> 81759 bytes golang-external-secrets/values.yaml | 6 +- ...rets-industrial-edge-factory.expected.yaml | 505 ++++++++++++++++-- ...-secrets-industrial-edge-hub.expected.yaml | 505 ++++++++++++++++-- ...ecrets-medical-diagnosis-hub.expected.yaml | 505 ++++++++++++++++-- ...olang-external-secrets-naked.expected.yaml | 505 ++++++++++++++++-- ...lang-external-secrets-normal.expected.yaml | 505 ++++++++++++++++-- 9 files changed, 2279 insertions(+), 254 deletions(-) delete mode 100644 golang-external-secrets/charts/external-secrets-0.9.19.tgz create mode 100644 golang-external-secrets/charts/external-secrets-0.9.20.tgz diff --git a/golang-external-secrets/Chart.yaml b/golang-external-secrets/Chart.yaml index b304d092..802979b4 100644 --- a/golang-external-secrets/Chart.yaml +++ b/golang-external-secrets/Chart.yaml @@ -6,6 +6,6 @@ name: golang-external-secrets version: 0.1.0 dependencies: - name: external-secrets - version: "0.9.19" + version: "0.9.20" repository: "https://charts.external-secrets.io" #"https://external-secrets.github.io/kubernetes-external-secrets" diff --git a/golang-external-secrets/charts/external-secrets-0.9.19.tgz b/golang-external-secrets/charts/external-secrets-0.9.19.tgz deleted file mode 100644 index 66fffaa0b08d686867fc9e4307204eaae1e22964..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 76457 zcmV)gK%~DPiwFP!000001ML0#cH2glFpBrzehM6BX4(0EB565})1TMLH={^STJ4*b zq}Zp|tXXl9ghWIjzyUzXN;;2qUf?|0Z|_|f6z)|dNYS0bn(0_Xp)R|s_Wk02&io`| z;V|{5iJzt8zx4k+h3C6(zs3I^e)sKD{lD`0%i;4E-#mTs^y#w5o%K7M)skLN7OM)zzH_BIA?@Qdfq8~6Xar-!)z&%S%{ z;+yZD;{LxleERG!-qYS@(DMAr_n$3;4}OvcarDx=efEegm-(MhNB?_t_`e^`{B)WG z%Zz?}CC-b-&x^NU5xe#mew2AvapJvRP2jbk`RSv1yzpOo^DJAYFURBSAe*lyqiMVt zSB_lyheyE_hmxNr>~6$AU!{HmuQC|Ttf%pU1<{zLDZNbNVHjV-|FGoRA1$NnM>qcc zU7XC)myd?tjhgzfGNGX-|Anm-gdYE&@4Z6+(dg;$>ElN@RtEnMZ?Qig{tjPyH+~of z(PGMOSC{_@quDEpjkIz|`%e{uMtg#W*Lad_zP|1O^L{(Ezl zdK2G|yqUiY<9mPRrK{=GPt&Va7~Xq9M2IV0vZ?R={<|lSi#I6uG*ayb-pKpokN@k@ zqtnO(Z0jdp7Q-0V(AO#rqH9G|F8G%R-hI6C?t(D%A|ECItpS01tEI<0-sB>S6aNv= zo8u7n&rh^py#(<5DuLNOL4xFeW-vkjz?(=kM-`p9zA;W7CQ(c z_;5kk)`S1c=Ds%zuCDw9i5w#2)Qhk5FH?_2GjAT>;Y@)(T?N-G=m$PrJeslymI}0S z1x;YVFg5QdB4#fUd?U_o{S9a(fM`=>-oyTD_x~3-?@ORIqineuFW7$n51&7O{$26@ zKYRMEyZ^g+e*b;^zaG8%yu=fXCmk;>9&h~jl+Na(|22k_`TOrfzzA2s-89_vfj7*X z;pLKN`yKW;`oO}K&s)9+7A6U1zV}ZrOIFd;d+`nZGgw@#uC9X5-e5TJL|;Bk3;y|t zrg@C_*N59HN8l*we^x9Et^z<5z$eiHMvp%Fyl-ls;Rv`G#B5UrT%?!ch0B>$zHI0t zoWW&=yBh|JAmgYfn+K`)1keY94z3hXG0pvL8&i3sQEdo|0h3vCwy;m>Ib)k_V@rd6<|yP z&;sBS4D&{uilTg!8eSwpGHdo(y=~g)#s)gT3J~Ix>{z+DciMqQY#{^@Jj`^c#SP)D zLN@V3lY>po^VODjQ$J|@-$M9;olF3Z{Q7n8Q7zfc(H(vXsRZg!yEFs0x4LG z()pOCPn0}}rr~PVvcwUeL`%aIHf9P8#TzluNV`X3^+!rR$9I75M!DEJ3gWSn4s+f@ z`{bX1E90!Z-_>5YP(K?^?s-S@#9a8vZIGXrJK$r~*_#qH`P9Wqv-lru5$4ONJzvcL zAKv+sc^uzt9q?)(w*j?q87_RdPSfHISRbG@%jNyQ^akR?!A_Pp^^Y&GS2n6Rs%*LGLl;=OJoj%tcwjNQ=J2osI*t3j9Q@^