From f61784edb792b0617039a5bedc8385ddced7d2fa Mon Sep 17 00:00:00 2001 From: Doug Goldstein Date: Wed, 16 Apr 2025 18:30:39 -0500 Subject: [PATCH 1/5] feat(argocd): add new AppSet for OpenStack services This new AppSet for the OpenStack services is a no-op with the existing AppSet to allow for a transition over without deleting resources. This AppSet follows the split of the regional and global deployments. It further supports using the same AppSet definition for production environments and development environments by using kustomize to adjust how clusters are defined. --- apps/appsets/appset-understack-openstack.yaml | 120 ++++++++++++++++++ apps/kustomization.yaml | 25 ++++ apps/openstack/glance.yaml | 4 + apps/openstack/horizon.yaml | 4 + apps/openstack/ironic.yaml | 4 + apps/openstack/keystone.yaml | 13 ++ apps/openstack/neutron.yaml | 4 + apps/openstack/nova.yaml | 4 + apps/openstack/openvswitch.yaml | 4 + apps/openstack/ovn.yaml | 4 + apps/openstack/placement.yaml | 4 + apps/openstack/skyline.yaml | 4 + 12 files changed, 194 insertions(+) create mode 100644 apps/appsets/appset-understack-openstack.yaml create mode 100644 apps/openstack/glance.yaml create mode 100644 apps/openstack/horizon.yaml create mode 100644 apps/openstack/ironic.yaml create mode 100644 apps/openstack/keystone.yaml create mode 100644 apps/openstack/neutron.yaml create mode 100644 apps/openstack/nova.yaml create mode 100644 apps/openstack/openvswitch.yaml create mode 100644 apps/openstack/ovn.yaml create mode 100644 apps/openstack/placement.yaml create mode 100644 apps/openstack/skyline.yaml diff --git a/apps/appsets/appset-understack-openstack.yaml b/apps/appsets/appset-understack-openstack.yaml new file mode 100644 index 000000000..e4b819632 --- /dev/null +++ b/apps/appsets/appset-understack-openstack.yaml @@ -0,0 +1,120 @@ +--- +apiVersion: argoproj.io/v1alpha1 +kind: ApplicationSet +metadata: + name: understack-openstack +spec: + syncPolicy: + applicationsSync: create-update + # for infrastructure resources we don't want to delete things automatically + preserveResourcesOnDeletion: true + goTemplate: true + goTemplateOptions: ["missingkey=error"] + generators: + # matrixes clusters with the applications + - matrix: + generators: + # figure out the clusters and the source repos based on the clusters + - merge: + mergeKeys: + # merge cluster configs based on cluster name + - name + generators: + # load all clusters for regional or aio + - clusters: + selector: + matchExpressions: + - key: understack.rackspace.com/role + operator: In + values: + # openstack is deployed at the site level + - "site" + - "aio" + # dev clusters allow some overrides + - clusters: + selector: + matchLabels: + understack.rackspace.com/env: dev + values: + understack_url: '{{index .metadata.annotations "uc_repo_git_url"}}' + understack_ref: '{{index .metadata.annotations "uc_repo_ref"}}' + deploy_url: '{{index .metadata.annotations "uc_deploy_git_url"}}' + deploy_ref: '{{index .metadata.annotations "uc_deploy_ref"}}' + # now the applications matrixed with the clusters + - merge: + mergeKeys: + # merge config based on component name + - component + generators: + - git: + repoURL: '{{ .values.understack_url }}' + revision: '{{ .values.understack_ref }}' + files: + - path: "apps/openstack/*.yaml" + - git: + repoURL: '{{ .values.deploy_url }}' + revision: '{{ .values.deploy_ref }}' + files: + # due to https://github.com/argoproj/argo-cd/issues/22051 + # we need to do this workaround + - path: '{{ "{{.name}}" }}/apps.yaml' + selector: + matchExpressions: + # if you set skip to any value for the component in apps.yaml, this will disable it + - key: skip + operator: DoesNotExist + template: + metadata: + name: '{{.name}}-{{.component}}' + # we should never set the finalizer here as the applicationsSync policy will handle it + annotations: + argocd.argoproj.io/compare-options: ServerSideDiff=true,IncludeMutationWebhook=true + spec: + project: understack + sources: + - repoURL: '{{.repoURL}}' + chart: '{{.component}}' + targetRevision: '{{.chartVersion}}' + helm: + releaseName: '{{.component}}' + valueFiles: + # default upstream images + - $understack/components/images-openstack.yaml + # default values for each component + - $understack/components/{{.component}}/values.yaml + # current global secret data per deployment + - $deploy/{{.name}}/manifests/secret-openstack.yaml + # optional file to allow users to override upstream images + - $deploy/{{.name}}/manifests/images-openstack.yaml + # optional file to allow users to override component values + - $deploy/{{.name}}/helm-configs/{{.component}}.yaml + # don't require all the values files + ignoreMissingValueFiles: true + - repoURL: '{{ .values.understack_url }}' + path: components/{{.component}}/ + targetRevision: '{{ .values.understack_ref }}' + ref: understack + - repoURL: '{{ .values.deploy_url }}' + targetRevision: '{{ .values.deploy_ref }}' + path: '{{.name}}/manifests/{{.component}}' + ref: deploy + destination: + server: '{{.server}}' + namespace: openstack + syncPolicy: + automated: + selfHeal: true + syncOptions: + - CreateNamespace=true + - ServerSideApply=true + - RespectIgnoreDifferences=true + managedNamespaceMetadata: + annotations: + # ArgoCD can create our namespace but let's not delete it + argocd.argoproj.io/sync-options: Delete=false + labels: + kubernetes.io/metadata.name: openstack + name: openstack + templatePatch: | + spec: + ignoreDifferences: {{ dig "ignoreDifferences" list . | toJson }} diff --git a/apps/kustomization.yaml b/apps/kustomization.yaml index 0f927d168..0c26d6532 100644 --- a/apps/kustomization.yaml +++ b/apps/kustomization.yaml @@ -8,3 +8,28 @@ resources: - appsets/appset-understack-operators.yaml - appsets/components.yaml - appsets/openstack.yaml +- appsets/appset-understack-openstack.yaml + +# you can do something like below to allow your deployment repo +# to define the exact versions that you want to use +# you will need to replace your $DEPLOY_URL and $DEPLOY_REF +#patches: +# - target: +# group: argoproj.io +# version: v1alpha1 +# kind: ApplicationSet +# name: understack-openstack +# patch: +# - op: add +# path: /spec/generators/0/matrix/generators/0/merge/generators/1 +# value: | +# git: +# repoURL: $DEPLOY_URL +# revision: $DEPLOY_REF +# files: +# - path: "*/deploy.yaml" +# values: +# understack_url: '{{ get . "understack_url" }}' +# understack_ref: '{{ get . "understack_ref" }}' +# deploy_url: '{{ get . "deploy_url" }}' +# deploy_ref: '{{ get . "deploy_ref" }}' diff --git a/apps/openstack/glance.yaml b/apps/openstack/glance.yaml new file mode 100644 index 000000000..00f55166a --- /dev/null +++ b/apps/openstack/glance.yaml @@ -0,0 +1,4 @@ +--- +component: glance +repoURL: https://tarballs.opendev.org/openstack/openstack-helm +chartVersion: 0.5.2 diff --git a/apps/openstack/horizon.yaml b/apps/openstack/horizon.yaml new file mode 100644 index 000000000..1f4517513 --- /dev/null +++ b/apps/openstack/horizon.yaml @@ -0,0 +1,4 @@ +--- +component: horizon +repoURL: https://tarballs.opendev.org/openstack/openstack-helm +chartVersion: 2024.2.1+34d1672a-93ed069c diff --git a/apps/openstack/ironic.yaml b/apps/openstack/ironic.yaml new file mode 100644 index 000000000..ab69ef6ef --- /dev/null +++ b/apps/openstack/ironic.yaml @@ -0,0 +1,4 @@ +--- +component: ironic +repoURL: https://tarballs.opendev.org/openstack/openstack-helm +chartVersion: 0.2.21 diff --git a/apps/openstack/keystone.yaml b/apps/openstack/keystone.yaml new file mode 100644 index 000000000..4806044f5 --- /dev/null +++ b/apps/openstack/keystone.yaml @@ -0,0 +1,13 @@ +--- +component: keystone +repoURL: https://tarballs.opendev.org/openstack/openstack-helm +chartVersion: 2024.2.6+06d763432 +ignoreDifferences: + - kind: Secret + name: keystone-fernet-keys + jqPathExpressions: + - .data + - kind: Secret + name: keystone-credential-keys + jqPathExpressions: + - .data diff --git a/apps/openstack/neutron.yaml b/apps/openstack/neutron.yaml new file mode 100644 index 000000000..5ca01cd7e --- /dev/null +++ b/apps/openstack/neutron.yaml @@ -0,0 +1,4 @@ +--- +component: neutron +repoURL: https://tarballs.opendev.org/openstack/openstack-helm +chartVersion: 0.3.47 diff --git a/apps/openstack/nova.yaml b/apps/openstack/nova.yaml new file mode 100644 index 000000000..9d1bd427f --- /dev/null +++ b/apps/openstack/nova.yaml @@ -0,0 +1,4 @@ +--- +component: nova +repoURL: https://tarballs.opendev.org/openstack/openstack-helm +chartVersion: 2024.2.8+f37dd907f diff --git a/apps/openstack/openvswitch.yaml b/apps/openstack/openvswitch.yaml new file mode 100644 index 000000000..3c7e65913 --- /dev/null +++ b/apps/openstack/openvswitch.yaml @@ -0,0 +1,4 @@ +--- +component: openvswitch +repoURL: https://tarballs.opendev.org/openstack/openstack-helm-infra +chartVersion: 2024.2.0 diff --git a/apps/openstack/ovn.yaml b/apps/openstack/ovn.yaml new file mode 100644 index 000000000..b75d8e38c --- /dev/null +++ b/apps/openstack/ovn.yaml @@ -0,0 +1,4 @@ +--- +component: ovn +repoURL: https://tarballs.opendev.org/openstack/openstack-helm-infra +chartVersion: 2024.2.0 diff --git a/apps/openstack/placement.yaml b/apps/openstack/placement.yaml new file mode 100644 index 000000000..54205d82a --- /dev/null +++ b/apps/openstack/placement.yaml @@ -0,0 +1,4 @@ +--- +component: placement +repoURL: https://tarballs.opendev.org/openstack/openstack-helm +chartVersion: 2024.2.1+34d1672a-93ed069c diff --git a/apps/openstack/skyline.yaml b/apps/openstack/skyline.yaml new file mode 100644 index 000000000..f354cc243 --- /dev/null +++ b/apps/openstack/skyline.yaml @@ -0,0 +1,4 @@ +--- +component: skyline +repoURL: https://tarballs.opendev.org/openstack/openstack-helm +chartVersion: 2025.1.1+12830ffa1 From cc54f4f5c1ec96e622023ccc6d72ad102dca44be Mon Sep 17 00:00:00 2001 From: Doug Goldstein Date: Thu, 24 Apr 2025 19:26:40 -0500 Subject: [PATCH 2/5] feat(argocd): operators and infra AppSet feature parity In creating the site / global split AppSets there were a few changes in how cluster specific data can be passed down via config files in the deploy repo. This updates the operators and infra AppSet to behave the same way. --- apps/appsets/appset-understack-infra.yaml | 185 +++++++------- apps/appsets/appset-understack-operators.yaml | 227 ++++++++---------- apps/infra/cert-manager.yaml | 11 + apps/infra/cilium.yaml | 7 + apps/infra/etcbackup.yaml | 12 + apps/infra/ingress-nginx.yaml | 12 + apps/operators/cnpg-operator.yaml | 5 + apps/operators/external-secrets.yaml | 5 + apps/operators/kube-prometheus-stack.yaml | 15 ++ apps/operators/mariadb-operator.yaml | 5 + apps/operators/opentelemetry-operator.yaml | 15 ++ apps/operators/rabbitmq-operator.yaml | 5 + apps/operators/rook.yaml | 25 ++ 13 files changed, 323 insertions(+), 206 deletions(-) create mode 100644 apps/infra/cert-manager.yaml create mode 100644 apps/infra/cilium.yaml create mode 100644 apps/infra/etcbackup.yaml create mode 100644 apps/infra/ingress-nginx.yaml create mode 100644 apps/operators/cnpg-operator.yaml create mode 100644 apps/operators/external-secrets.yaml create mode 100644 apps/operators/kube-prometheus-stack.yaml create mode 100644 apps/operators/mariadb-operator.yaml create mode 100644 apps/operators/opentelemetry-operator.yaml create mode 100644 apps/operators/rabbitmq-operator.yaml create mode 100644 apps/operators/rook.yaml diff --git a/apps/appsets/appset-understack-infra.yaml b/apps/appsets/appset-understack-infra.yaml index f57c0a505..03efd1b7e 100644 --- a/apps/appsets/appset-understack-infra.yaml +++ b/apps/appsets/appset-understack-infra.yaml @@ -11,86 +11,58 @@ spec: goTemplate: true goTemplateOptions: ["missingkey=error"] generators: + # matrixes clusters with the applications - matrix: generators: - - clusters: - selector: - matchExpressions: - - key: understack.rackspace.com/role - operator: In + - merge: + mergeKeys: + # merge cluster configs based on cluster name + - name + generators: + # load all clusters + - clusters: + selector: + matchExpressions: + - key: understack.rackspace.com/role + operator: In + values: + - "global" + - "site" + - "aio" + # dev clusters allow some overrides + - clusters: + selector: + matchLabels: + understack.rackspace.com/env: dev values: - - "global" - - "regional" - - "aio" - values: - uc_skip_components: '{{ default "[]" (index .metadata.annotations "uc_skip_components") }}' - uc_repo_git_url: '{{index .metadata.annotations "uc_repo_git_url"}}' - uc_repo_ref: '{{index .metadata.annotations "uc_repo_ref"}}' - uc_deploy_git_url: '{{index .metadata.annotations "uc_deploy_git_url"}}' - uc_deploy_ref: '{{index .metadata.annotations "uc_deploy_ref"}}' - uc_role: '{{index .metadata.labels "understack.rackspace.com/role"}}' - uc_dns_zone: '{{index .metadata.annotations "dns_zone" }}' - uc_cluster_issuer: '{{index .metadata.annotations "uc_cluster_issuer" }}' - uc_global_dns_zone: '{{index .metadata.annotations "uc_global_dns_zone" }}' - - list: - elements: - - component: cert-manager - skipComponent: '{{has "cert-manager" (.values.uc_skip_components | fromJson)}}' - sources: - - repoURL: https://charts.jetstack.io - chart: cert-manager - targetRevision: '1.15.2' - helm: - releaseName: cert-manager - valuesObject: - crds: - enabled: true - - component: ingress-nginx - skipComponent: '{{has "ingress-nginx" (.values.uc_skip_components | fromJson)}}' - sources: - - repoURL: https://kubernetes.github.io/ingress-nginx - chart: ingress-nginx - targetRevision: 4.12.1 - helm: - releaseName: ingress-nginx - valueFiles: - - $deploy/{{.name}}/helm-configs/ingress-nginx.yaml - ignoreMissingValueFiles: true - - repoURL: '{{ .values.uc_deploy_git_url }}' - targetRevision: '{{ .values.uc_deploy_ref }}' - ref: deploy - - component: cilium - skipComponent: '{{or (has "cilium" (.values.uc_skip_components | fromJson)) (eq "global" .values.uc_role)}}' - sources: - # Cilium itself is deployed before ArgoCD so we only include project - # and environment specific stuff here - - repoURL: '{{ .values.uc_deploy_git_url }}' - targetRevision: '{{ .values.uc_deploy_ref }}' - path: '{{.name}}/manifests/cilium' - - component: etcdbackup - componentNamespace: kube-system - skipComponent: '{{has "etcdbackup" (.values.uc_skip_components | fromJson)}}' - sources: - - repoURL: '{{ .values.uc_repo_git_url }}' - targetRevision: '{{ .values.uc_repo_ref }}' - path: 'components/etcdbackup' - ref: understack - helm: - valueFiles: - - $understack/components/etcdbackup/values.yaml - - $deploy/{{.name}}/helm-configs/etcdbackup.yaml - ignoreMissingValueFiles: true - - repoURL: '{{ .values.uc_deploy_git_url }}' - targetRevision: '{{ .values.uc_deploy_ref }}' - ref: deploy - selector: - # by setting the key in the elements 'skipComponent' to 'true' it will skip installing it - # ArgoCD's templating operates with strings so it's the string "true" - matchExpressions: - - key: skipComponent - operator: NotIn - values: - - "true" + understack_url: '{{index .metadata.annotations "uc_repo_git_url"}}' + understack_ref: '{{index .metadata.annotations "uc_repo_ref"}}' + deploy_url: '{{index .metadata.annotations "uc_deploy_git_url"}}' + deploy_ref: '{{index .metadata.annotations "uc_deploy_ref"}}' + # now the applications matrixed with the clusters + - merge: + mergeKeys: + # merge config based on component name + - component + generators: + - git: + repoURL: '{{ .values.understack_url }}' + revision: '{{ .values.understack_ref }}' + files: + - path: "apps/infra/*.yaml" + - git: + repoURL: '{{ .values.deploy_url }}' + revision: '{{ .values.deploy_ref }}' + files: + # due to https://github.com/argoproj/argo-cd/issues/22051 + # we need to do this workaround. this reads the apps.yaml + # for per cluster + - path: '{{ "{{.name}}" }}/apps.yaml' + selector: + matchExpressions: + # if you set skip to any value for the component in apps.yaml, this will disable it + - key: skip + operator: DoesNotExist template: metadata: name: '{{.name}}-{{.component}}' @@ -115,12 +87,61 @@ spec: argocd.argoproj.io/sync-options: Delete=false templatePatch: | spec: + {{- $root := . }} + {{- if hasKey . "sources" }} sources: - {{- range $source := .sources }} - # indentation matters so collapse to single line with toJson to keep it - - {{ $source | toJson }} + {{- range $source := .sources }} + {{- if hasKey $source "ref" }} + - ref: {{ $source.ref }} + {{- if eq $source.ref "understack" }} + repoURL: {{ $root.values.understack_url }} + targetRevision: {{ $root.values.understack_ref }} + {{- else if eq $source.ref "deploy" }} + repoURL: {{ $root.values.deploy_url }} + targetRevision: {{ $root.values.deploy_ref }} + {{- end }} + {{- else }} + - repoURL: {{ $source.repoURL }} + targetRevision: {{ $source.targetRevision }} + {{- end }} + {{- if hasKey $source "chart" }} + chart: {{ $source.chart }} + {{- end }} + {{- if hasKey $source "helm" }} + helm: + {{- if hasKey $source "chart" }} + releaseName: {{ $source.chart }} + {{- end }} + {{- if hasKey $source.helm "valueFiles" }} + valueFiles: + {{- range $vf := $source.helm.valueFiles }} + # until dynamic parameters exist this must be done + - {{ $vf | replace "{{.name}}" $root.name }} + {{- end }} + ignoreMissingValueFiles: true + {{- end }} + {{- if hasKey $source.helm "fileParameters" }} + fileParameters: + {{- range $fp := $source.helm.fileParameters }} + # until dynamic parameters exist this must be done + - name: {{ $fp.name }} + path: {{ $fp.path | replace "{{.name}}" $root.name }} + {{- end }} + {{- end }} + {{- if hasKey $source.helm "valuesObject" }} + valuesObject: {{ $source.helm.valuesObject | toJson }} + # indentation matters so collapse to single line with toJson to keep it + {{- end }} + {{- end }} + {{- if hasKey $source "kustomize" }} + kustomize: {{ $source.kustomize | toJson }} + {{- end }} + {{- if hasKey $source "path" }} + path: {{ $source.path | replace "{{.name}}" $root.name }} + {{- end }} + {{- end }} {{- end }} - {{- if hasKey . "ignoreDifferences" }} + {{- if hasKey . "ignoreDifferences" }} # indentation matters so collapse to single line with toJson to keep it ignoreDifferences: {{ .ignoreDifferences | toJson }} - {{- end }} + {{- end }} diff --git a/apps/appsets/appset-understack-operators.yaml b/apps/appsets/appset-understack-operators.yaml index 523a64885..e2bee22ea 100644 --- a/apps/appsets/appset-understack-operators.yaml +++ b/apps/appsets/appset-understack-operators.yaml @@ -11,128 +11,58 @@ spec: goTemplate: true goTemplateOptions: ["missingkey=error"] generators: + # matrixes clusters with the applications - matrix: generators: - - clusters: - selector: - matchExpressions: - - key: understack.rackspace.com/role - operator: In + - merge: + mergeKeys: + # merge cluster configs based on cluster name + - name + generators: + # load all clusters + - clusters: + selector: + matchExpressions: + - key: understack.rackspace.com/role + operator: In + values: + - "global" + - "site" + - "aio" + # dev clusters allow some overrides + - clusters: + selector: + matchLabels: + understack.rackspace.com/env: dev values: - - "global" - - "regional" - - "aio" - values: - uc_skip_components: '{{ default "[]" (index .metadata.annotations "uc_skip_components") }}' - uc_repo_git_url: '{{index .metadata.annotations "uc_repo_git_url"}}' - uc_repo_ref: '{{index .metadata.annotations "uc_repo_ref"}}' - uc_deploy_git_url: '{{index .metadata.annotations "uc_deploy_git_url"}}' - uc_deploy_ref: '{{index .metadata.annotations "uc_deploy_ref"}}' - uc_role: '{{index .metadata.labels "understack.rackspace.com/role"}}' - uc_dns_zone: '{{index .metadata.annotations "dns_zone" }}' - uc_cluster_issuer: '{{index .metadata.annotations "uc_cluster_issuer" }}' - uc_global_dns_zone: '{{index .metadata.annotations "uc_global_dns_zone" }}' - - list: - elements: - - component: rook - componentNamespace: rook-ceph - skipComponent: '{{or (has "rook" (.values.uc_skip_components | fromJson)) (eq "global" .values.uc_role)}}' - sources: - - repoURL: https://charts.rook.io/release - chart: rook-ceph - targetRevision: v1.16.4 - helm: - releaseName: rook-ceph - valueFiles: - - $understack/operators/rook/values-operator.yaml - - $deploy/{{.name}}/helm-configs/rook-operator.yaml - ignoreMissingValueFiles: true - - repoURL: https://charts.rook.io/release - chart: rook-ceph-cluster - targetRevision: v1.16.4 - helm: - releaseName: rook-ceph-cluster - valueFiles: - - $understack/operators/rook/values-cluster.yaml - - $deploy/{{.name}}/helm-configs/rook-cluster.yaml - ignoreMissingValueFiles: true - - repoURL: '{{ .values.uc_repo_git_url }}' - targetRevision: '{{ .values.uc_repo_ref }}' - path: 'operators/rook' - ref: understack - - repoURL: '{{ .values.uc_deploy_git_url }}' - targetRevision: '{{ .values.uc_deploy_ref }}' - ref: deploy - - component: cnpg-system - skipComponent: '{{or (has "cnpg-system" (.values.uc_skip_components | fromJson)) (eq "regional" .values.uc_role)}}' - sources: - - repoURL: '{{ .values.uc_repo_git_url }}' - targetRevision: '{{ .values.uc_repo_ref }}' - path: 'operators/cnpg-system' - - component: external-secrets - skipComponent: '{{has "external-secrets" (.values.uc_skip_components | fromJson)}}' - sources: - - repoURL: '{{ .values.uc_repo_git_url }}' - targetRevision: '{{ .values.uc_repo_ref }}' - path: 'operators/external-secrets' - - component: mariadb-operator - skipComponent: '{{has "mariadb-operator" (.values.uc_skip_components | fromJson)}}' - sources: - - repoURL: '{{ .values.uc_repo_git_url }}' - targetRevision: '{{ .values.uc_repo_ref }}' - path: 'operators/mariadb-operator' - - component: rabbitmq-system - skipComponent: '{{has "rabbitmq-system" (.values.uc_skip_components | fromJson)}}' - sources: - - repoURL: '{{ .values.uc_repo_git_url }}' - targetRevision: '{{ .values.uc_repo_ref }}' - path: 'operators/rabbitmq-system' - - component: monitoring - skipComponent: '{{has "monitoring" (.values.uc_skip_components | fromJson)}}' - sources: - - repoURL: https://prometheus-community.github.io/helm-charts - chart: kube-prometheus-stack - targetRevision: 62.6.0 - helm: - releaseName: kube-prometheus-stack - valueFiles: - - $understack/operators/monitoring/values.yaml - - $deploy/{{.name}}/helm-configs/monitoring.yaml - ignoreMissingValueFiles: true - - repoURL: '{{ .values.uc_repo_git_url }}' - targetRevision: '{{ .values.uc_repo_ref }}' - path: 'operators/monitoring' - ref: understack - - repoURL: '{{ .values.uc_deploy_git_url }}' - targetRevision: '{{ .values.uc_deploy_ref }}' - ref: deploy - - component: opentelemetry-operator - skipComponent: '{{has "opentelemetry-operator" (.values.uc_skip_components | fromJson)}}' - sources: - - repoURL: https://open-telemetry.github.io/opentelemetry-helm-charts - chart: opentelemetry-operator - targetRevision: 0.79.0 - helm: - releaseName: opentelemetry-operator - valueFiles: - - $understack/operators/opentelemetry-operator/values.yaml - - $deploy/{{.name}}/helm-configs/opentelemetry-operator.yaml - ignoreMissingValueFiles: true - - repoURL: '{{ .values.uc_repo_git_url }}' - targetRevision: '{{ .values.uc_repo_ref }}' - ref: understack - path: 'operators/opentelemetry-operator' - - repoURL: '{{ .values.uc_deploy_git_url }}' - targetRevision: '{{ .values.uc_deploy_ref }}' - ref: deploy - selector: - # by setting the key in the elements 'skipComponent' to 'true' it will skip installing it - # ArgoCD's templating operates with strings so it's the string "true" - matchExpressions: - - key: skipComponent - operator: NotIn - values: - - "true" + understack_url: '{{index .metadata.annotations "uc_repo_git_url"}}' + understack_ref: '{{index .metadata.annotations "uc_repo_ref"}}' + deploy_url: '{{index .metadata.annotations "uc_deploy_git_url"}}' + deploy_ref: '{{index .metadata.annotations "uc_deploy_ref"}}' + # now the applications matrixed with the clusters + - merge: + mergeKeys: + # merge config based on component name + - component + generators: + - git: + repoURL: '{{ .values.understack_url }}' + revision: '{{ .values.understack_ref }}' + files: + - path: "apps/operators/*.yaml" + - git: + repoURL: '{{ .values.deploy_url }}' + revision: '{{ .values.deploy_ref }}' + files: + # due to https://github.com/argoproj/argo-cd/issues/22051 + # we need to do this workaround. this reads the apps.yaml + # for per cluster + - path: '{{ "{{.name}}" }}/apps.yaml' + selector: + matchExpressions: + # if you set skip to any value for the component in apps.yaml, this will disable it + - key: skip + operator: DoesNotExist template: metadata: name: '{{.name}}-{{.component}}' @@ -157,12 +87,61 @@ spec: argocd.argoproj.io/sync-options: Delete=false templatePatch: | spec: + {{- $root := . }} + {{- if hasKey . "sources" }} sources: - {{- range $source := .sources }} - # indentation matters so collapse to single line with toJson to keep it - - {{ $source | toJson }} + {{- range $source := .sources }} + {{- if hasKey $source "ref" }} + - ref: {{ $source.ref }} + {{- if eq $source.ref "understack" }} + repoURL: {{ $root.values.understack_url }} + targetRevision: {{ $root.values.understack_ref }} + {{- else if eq $source.ref "deploy" }} + repoURL: {{ $root.values.deploy_url }} + targetRevision: {{ $root.values.deploy_ref }} + {{- end }} + {{- else}} + - repoURL: {{ $source.repoURL }} + targetRevision: {{ $source.targetRevision }} + {{- end }} + {{- if hasKey $source "chart" }} + chart: {{ $source.chart }} + {{- end }} + {{- if hasKey $source "helm" }} + helm: + {{- if hasKey $source "chart" }} + releaseName: {{ $source.chart }} + {{- end }} + {{- if hasKey $source.helm "valueFiles" }} + valueFiles: + {{- range $vf := $source.helm.valueFiles }} + # until dynamic parameters exist this must be done + - {{ $vf | replace "{{.name}}" $root.name }} + {{- end }} + ignoreMissingValueFiles: true + {{- end }} + {{- if hasKey $source.helm "fileParameters" }} + fileParameters: + {{- range $fp := $source.helm.fileParameters }} + # until dynamic parameters exist this must be done + - name: {{ $fp.name }} + path: {{ $fp.path | replace "{{.name}}" $root.name }} + {{- end }} + {{- end }} + {{- if hasKey $source.helm "valuesObject" }} + valuesObject: {{ $source.helm.valuesObject | toJson }} + # indentation matters so collapse to single line with toJson to keep it + {{- end }} + {{- end }} + {{- if hasKey $source "kustomize" }} + kustomize: {{ $source.kustomize | toJson }} + {{- end }} + {{- if hasKey $source "path" }} + path: {{ $source.path | replace "{{.name}}" $root.name }} + {{- end }} + {{- end }} {{- end }} - {{- if hasKey . "ignoreDifferences" }} + {{- if hasKey . "ignoreDifferences" }} # indentation matters so collapse to single line with toJson to keep it ignoreDifferences: {{ .ignoreDifferences | toJson }} - {{- end }} + {{- end }} diff --git a/apps/infra/cert-manager.yaml b/apps/infra/cert-manager.yaml new file mode 100644 index 000000000..1aa585d6f --- /dev/null +++ b/apps/infra/cert-manager.yaml @@ -0,0 +1,11 @@ +--- +component: cert-manager +sources: + - repoURL: https://charts.jetstack.io + chart: cert-manager + targetRevision: '1.15.2' + helm: + releaseName: cert-manager + valuesObject: + crds: + enabled: true diff --git a/apps/infra/cilium.yaml b/apps/infra/cilium.yaml new file mode 100644 index 000000000..728d20a62 --- /dev/null +++ b/apps/infra/cilium.yaml @@ -0,0 +1,7 @@ +--- +component: cilium +sources: + # Cilium itself is deployed before ArgoCD so we only include project + # and environment specific stuff here + - ref: deploy + path: '{{.name}}/manifests/cilium' diff --git a/apps/infra/etcbackup.yaml b/apps/infra/etcbackup.yaml new file mode 100644 index 000000000..2707b2671 --- /dev/null +++ b/apps/infra/etcbackup.yaml @@ -0,0 +1,12 @@ +--- +component: etcdbackup +componentNamespace: kube-system +sources: + - ref: understack + path: 'components/etcdbackup' + helm: + valueFiles: + - $understack/components/etcdbackup/values.yaml + - $deploy/{{.name}}/helm-configs/etcdbackup.yaml + ignoreMissingValueFiles: true + - ref: deploy diff --git a/apps/infra/ingress-nginx.yaml b/apps/infra/ingress-nginx.yaml new file mode 100644 index 000000000..b49ee9557 --- /dev/null +++ b/apps/infra/ingress-nginx.yaml @@ -0,0 +1,12 @@ +--- +component: ingress-nginx +sources: + - repoURL: https://kubernetes.github.io/ingress-nginx + chart: ingress-nginx + targetRevision: 4.12.1 + helm: + releaseName: ingress-nginx + valueFiles: + - $deploy/{{.name}}/helm-configs/ingress-nginx.yaml + ignoreMissingValueFiles: true + - ref: deploy diff --git a/apps/operators/cnpg-operator.yaml b/apps/operators/cnpg-operator.yaml new file mode 100644 index 000000000..7c2c4bcaa --- /dev/null +++ b/apps/operators/cnpg-operator.yaml @@ -0,0 +1,5 @@ +--- +component: cnpg-system +sources: + - ref: understack + path: 'operators/cnpg-system' diff --git a/apps/operators/external-secrets.yaml b/apps/operators/external-secrets.yaml new file mode 100644 index 000000000..797289ccd --- /dev/null +++ b/apps/operators/external-secrets.yaml @@ -0,0 +1,5 @@ +--- +component: external-secrets +sources: + - ref: understack + path: 'operators/external-secrets' diff --git a/apps/operators/kube-prometheus-stack.yaml b/apps/operators/kube-prometheus-stack.yaml new file mode 100644 index 000000000..ea1a0798f --- /dev/null +++ b/apps/operators/kube-prometheus-stack.yaml @@ -0,0 +1,15 @@ +--- +component: monitoring +sources: + - repoURL: https://prometheus-community.github.io/helm-charts + chart: kube-prometheus-stack + targetRevision: 62.6.0 + helm: + releaseName: kube-prometheus-stack + valueFiles: + - $understack/operators/monitoring/values.yaml + - $deploy/{{.name}}/helm-configs/monitoring.yaml + ignoreMissingValueFiles: true + - ref: understack + path: 'operators/monitoring' + - ref: deploy diff --git a/apps/operators/mariadb-operator.yaml b/apps/operators/mariadb-operator.yaml new file mode 100644 index 000000000..20c8ff2fa --- /dev/null +++ b/apps/operators/mariadb-operator.yaml @@ -0,0 +1,5 @@ +--- +component: mariadb-operator +sources: + - ref: understack + path: 'operators/mariadb-operator' diff --git a/apps/operators/opentelemetry-operator.yaml b/apps/operators/opentelemetry-operator.yaml new file mode 100644 index 000000000..2b2fe53a9 --- /dev/null +++ b/apps/operators/opentelemetry-operator.yaml @@ -0,0 +1,15 @@ +--- +component: opentelemetry-operator +sources: + - repoURL: https://open-telemetry.github.io/opentelemetry-helm-charts + chart: opentelemetry-operator + targetRevision: 0.79.0 + helm: + releaseName: opentelemetry-operator + valueFiles: + - $understack/operators/opentelemetry-operator/values.yaml + - $deploy/{{.name}}/helm-configs/opentelemetry-operator.yaml + ignoreMissingValueFiles: true + - ref: understack + path: 'operators/opentelemetry-operator' + - ref: deploy diff --git a/apps/operators/rabbitmq-operator.yaml b/apps/operators/rabbitmq-operator.yaml new file mode 100644 index 000000000..1f9639cca --- /dev/null +++ b/apps/operators/rabbitmq-operator.yaml @@ -0,0 +1,5 @@ +--- +component: rabbitmq-system +sources: + - ref: understack + path: 'operators/rabbitmq-system' diff --git a/apps/operators/rook.yaml b/apps/operators/rook.yaml new file mode 100644 index 000000000..c34d3ae09 --- /dev/null +++ b/apps/operators/rook.yaml @@ -0,0 +1,25 @@ +--- +component: rook +componentNamespace: rook-ceph +sources: + - repoURL: https://charts.rook.io/release + chart: rook-ceph + targetRevision: v1.16.4 + helm: + releaseName: rook-ceph + valueFiles: + - $understack/operators/rook/values-operator.yaml + - $deploy/{{.name}}/helm-configs/rook-operator.yaml + ignoreMissingValueFiles: true + - repoURL: https://charts.rook.io/release + chart: rook-ceph-cluster + targetRevision: v1.16.4 + helm: + releaseName: rook-ceph-cluster + valueFiles: + - $understack/operators/rook/values-cluster.yaml + - $deploy/{{.name}}/helm-configs/rook-cluster.yaml + ignoreMissingValueFiles: true + - ref: understack + path: 'operators/rook' + - ref: deploy From 4bdd8c1ed3cb24993403d98e594680afe8663651 Mon Sep 17 00:00:00 2001 From: Doug Goldstein Date: Tue, 22 Apr 2025 13:15:23 -0500 Subject: [PATCH 3/5] feat(argocd): add new AppSets to split site/global services These new AppSets encompasses all the site and global services and are a no-op with the existing components AppSet to allow for transition over without deleting resources. These AppSets aims to make it easier to define the same deployment for production and development environments. --- apps/appsets/appset-understack-global.yaml | 146 +++++++++++++++++++++ apps/appsets/appset-understack-site.yaml | 146 +++++++++++++++++++++ apps/global/argo-events.yaml | 7 + apps/global/argo-workflows.yaml | 51 +++++++ apps/global/dex.yaml | 16 +++ apps/global/nautobot.yaml | 19 +++ apps/global/understack-workflows.yaml | 6 + apps/kustomization.yaml | 2 + apps/site/chrony.yaml | 6 + apps/site/openstack-exporter.yaml | 15 +++ apps/site/openstack.yaml | 7 + apps/site/otel-collector.yaml | 6 + apps/site/snmp-exporter.yaml | 14 ++ apps/site/understack-cluster-issuer.yaml | 6 + apps/site/undersync.yaml | 7 + 15 files changed, 454 insertions(+) create mode 100644 apps/appsets/appset-understack-global.yaml create mode 100644 apps/appsets/appset-understack-site.yaml create mode 100644 apps/global/argo-events.yaml create mode 100644 apps/global/argo-workflows.yaml create mode 100644 apps/global/dex.yaml create mode 100644 apps/global/nautobot.yaml create mode 100644 apps/global/understack-workflows.yaml create mode 100644 apps/site/chrony.yaml create mode 100644 apps/site/openstack-exporter.yaml create mode 100644 apps/site/openstack.yaml create mode 100644 apps/site/otel-collector.yaml create mode 100644 apps/site/snmp-exporter.yaml create mode 100644 apps/site/understack-cluster-issuer.yaml create mode 100644 apps/site/undersync.yaml diff --git a/apps/appsets/appset-understack-global.yaml b/apps/appsets/appset-understack-global.yaml new file mode 100644 index 000000000..b269e9832 --- /dev/null +++ b/apps/appsets/appset-understack-global.yaml @@ -0,0 +1,146 @@ +--- +apiVersion: argoproj.io/v1alpha1 +kind: ApplicationSet +metadata: + name: understack-global +spec: + syncPolicy: + applicationsSync: create-update + # for infrastructure resources we don't want to delete things automatically + preserveResourcesOnDeletion: true + goTemplate: true + goTemplateOptions: ["missingkey=error"] + generators: + # matrixes clusters with the applications + - matrix: + generators: + - merge: + mergeKeys: + # merge cluster configs based on cluster name + - name + generators: + # load all clusters for global or aio + - clusters: + selector: + matchExpressions: + - key: understack.rackspace.com/role + operator: In + values: + - "global" + - "aio" + # dev clusters allow some overrides + - clusters: + selector: + matchLabels: + understack.rackspace.com/env: dev + values: + understack_url: '{{index .metadata.annotations "uc_repo_git_url"}}' + understack_ref: '{{index .metadata.annotations "uc_repo_ref"}}' + deploy_url: '{{index .metadata.annotations "uc_deploy_git_url"}}' + deploy_ref: '{{index .metadata.annotations "uc_deploy_ref"}}' + # now the applications matrixed with the clusters + - merge: + mergeKeys: + # merge config based on component name + - component + generators: + - git: + repoURL: '{{ .values.understack_url }}' + revision: '{{ .values.understack_ref }}' + files: + - path: "apps/global/*.yaml" + - git: + repoURL: '{{ .values.deploy_url }}' + revision: '{{ .values.deploy_ref }}' + files: + # due to https://github.com/argoproj/argo-cd/issues/22051 + # we need to do this workaround. this reads the apps.yaml + # for per cluster + - path: '{{ "{{.name}}" }}/apps.yaml' + selector: + matchExpressions: + # if you set skip to any value for the component in apps.yaml, this will disable it + - key: skip + operator: DoesNotExist + template: + metadata: + name: '{{.name}}-{{.component}}' + # we should never set the finalizer here as the applicationsSync policy will handle it + annotations: + argocd.argoproj.io/compare-options: ServerSideDiff=true,IncludeMutationWebhook=true + spec: + project: understack + destination: + server: '{{.server}}' + namespace: '{{coalesce (get . "componentNamespace") .component}}' + syncPolicy: + automated: + selfHeal: true + syncOptions: + - CreateNamespace=true + - ServerSideApply=true + - RespectIgnoreDifferences=true + managedNamespaceMetadata: + annotations: + # ArgoCD can create our namespace but let's not delete it + argocd.argoproj.io/sync-options: Delete=false + templatePatch: | + spec: + {{- $root := . }} + {{- if hasKey . "sources" }} + sources: + {{- range $source := .sources }} + {{- if hasKey $source "ref" }} + - ref: {{ $source.ref }} + {{- if eq $source.ref "understack" }} + repoURL: {{ $root.values.understack_url }} + targetRevision: {{ $root.values.understack_ref }} + {{- else if eq $source.ref "deploy" }} + repoURL: {{ $root.values.deploy_url }} + targetRevision: {{ $root.values.deploy_ref }} + {{- end }} + {{- else}} + - repoURL: {{ $source.repoURL }} + targetRevision: {{ $source.targetRevision }} + {{- end }} + {{- if hasKey $source "chart" }} + chart: {{ $source.chart }} + {{- end }} + {{- if hasKey $source "helm" }} + helm: + {{- if hasKey $source "chart" }} + releaseName: {{ $source.chart }} + {{- end }} + {{- if hasKey $source.helm "valueFiles" }} + valueFiles: + {{- range $vf := $source.helm.valueFiles }} + # until dynamic parameters exist this must be done + - {{ $vf | replace "{{.name}}" $root.name }} + {{- end }} + ignoreMissingValueFiles: true + {{- end }} + {{- if hasKey $source.helm "fileParameters" }} + fileParameters: + {{- range $fp := $source.helm.fileParameters }} + # until dynamic parameters exist this must be done + - name: {{ $fp.name }} + path: {{ $fp.path | replace "{{.name}}" $root.name }} + {{- end }} + {{- end }} + {{- if hasKey $source.helm "valuesObject" }} + valuesObject: {{ $source.helm.valuesObject | toJson }} + # indentation matters so collapse to single line with toJson to keep it + {{- end }} + {{- end }} + {{- if hasKey $source "kustomize" }} + kustomize: {{ $source.kustomize | toJson }} + {{- end }} + {{- if hasKey $source "path" }} + path: {{ $source.path | replace "{{.name}}" $root.name }} + {{- end }} + {{- end }} + {{- end }} + {{- if hasKey . "ignoreDifferences" }} + # indentation matters so collapse to single line with toJson to keep it + ignoreDifferences: {{ .ignoreDifferences | toJson }} + {{- end }} diff --git a/apps/appsets/appset-understack-site.yaml b/apps/appsets/appset-understack-site.yaml new file mode 100644 index 000000000..8dfc4ddf1 --- /dev/null +++ b/apps/appsets/appset-understack-site.yaml @@ -0,0 +1,146 @@ +--- +apiVersion: argoproj.io/v1alpha1 +kind: ApplicationSet +metadata: + name: understack-site +spec: + syncPolicy: + applicationsSync: create-update + # for infrastructure resources we don't want to delete things automatically + preserveResourcesOnDeletion: true + goTemplate: true + goTemplateOptions: ["missingkey=error"] + generators: + # matrixes clusters with the applications + - matrix: + generators: + - merge: + mergeKeys: + # merge cluster configs based on cluster name + - name + generators: + # load all clusters for site or aio + - clusters: + selector: + matchExpressions: + - key: understack.rackspace.com/role + operator: In + values: + - "site" + - "aio" + # dev clusters allow some overrides + - clusters: + selector: + matchLabels: + understack.rackspace.com/env: dev + values: + understack_url: '{{index .metadata.annotations "uc_repo_git_url"}}' + understack_ref: '{{index .metadata.annotations "uc_repo_ref"}}' + deploy_url: '{{index .metadata.annotations "uc_deploy_git_url"}}' + deploy_ref: '{{index .metadata.annotations "uc_deploy_ref"}}' + # now the applications matrixed with the clusters + - merge: + mergeKeys: + # merge config based on component name + - component + generators: + - git: + repoURL: '{{ .values.understack_url }}' + revision: '{{ .values.understack_ref }}' + files: + - path: "apps/site/*.yaml" + - git: + repoURL: '{{ .values.deploy_url }}' + revision: '{{ .values.deploy_ref }}' + files: + # due to https://github.com/argoproj/argo-cd/issues/22051 + # we need to do this workaround. this reads the apps.yaml + # for per cluster + - path: '{{ "{{.name}}" }}/apps.yaml' + selector: + matchExpressions: + # if you set skip to any value for the component in apps.yaml, this will disable it + - key: skip + operator: DoesNotExist + template: + metadata: + name: '{{.name}}-{{.component}}' + # we should never set the finalizer here as the applicationsSync policy will handle it + annotations: + argocd.argoproj.io/compare-options: ServerSideDiff=true,IncludeMutationWebhook=true + spec: + project: understack + destination: + server: '{{.server}}' + namespace: '{{coalesce (get . "componentNamespace") .component}}' + syncPolicy: + automated: + selfHeal: true + syncOptions: + - CreateNamespace=true + - ServerSideApply=true + - RespectIgnoreDifferences=true + managedNamespaceMetadata: + annotations: + # ArgoCD can create our namespace but let's not delete it + argocd.argoproj.io/sync-options: Delete=false + templatePatch: | + spec: + {{- $root := . }} + {{- if hasKey . "sources" }} + sources: + {{- range $source := .sources }} + {{- if hasKey $source "ref" }} + - ref: {{ $source.ref }} + {{- if eq $source.ref "understack" }} + repoURL: {{ $root.values.understack_url }} + targetRevision: {{ $root.values.understack_ref }} + {{- else if eq $source.ref "deploy" }} + repoURL: {{ $root.values.deploy_url }} + targetRevision: {{ $root.values.deploy_ref }} + {{- end }} + {{- else}} + - repoURL: {{ $source.repoURL }} + targetRevision: {{ $source.targetRevision }} + {{- end }} + {{- if hasKey $source "chart" }} + chart: {{ $source.chart }} + {{- end }} + {{- if hasKey $source "helm" }} + helm: + {{- if hasKey $source "chart" }} + releaseName: {{ $source.chart }} + {{- end }} + {{- if hasKey $source.helm "valueFiles" }} + valueFiles: + {{- range $vf := $source.helm.valueFiles }} + # until dynamic parameters exist this must be done + - {{ $vf | replace "{{.name}}" $root.name }} + {{- end }} + ignoreMissingValueFiles: true + {{- end }} + {{- if hasKey $source.helm "fileParameters" }} + fileParameters: + {{- range $fp := $source.helm.fileParameters }} + # until dynamic parameters exist this must be done + - name: {{ $fp.name }} + path: {{ $fp.path | replace "{{.name}}" $root.name }} + {{- end }} + {{- end }} + {{- if hasKey $source.helm "valuesObject" }} + valuesObject: {{ $source.helm.valuesObject | toJson }} + # indentation matters so collapse to single line with toJson to keep it + {{- end }} + {{- end }} + {{- if hasKey $source "kustomize" }} + kustomize: {{ $source.kustomize | toJson }} + {{- end }} + {{- if hasKey $source "path" }} + path: {{ $source.path | replace "{{.name}}" $root.name }} + {{- end }} + {{- end }} + {{- end }} + {{- if hasKey . "ignoreDifferences" }} + # indentation matters so collapse to single line with toJson to keep it + ignoreDifferences: {{ .ignoreDifferences | toJson }} + {{- end }} diff --git a/apps/global/argo-events.yaml b/apps/global/argo-events.yaml new file mode 100644 index 000000000..5e67678fb --- /dev/null +++ b/apps/global/argo-events.yaml @@ -0,0 +1,7 @@ +--- +component: argo-events +sources: + - ref: understack + path: 'components/argo-events' + - ref: deploy + path: '{{.name}}/manifests/argo-events' diff --git a/apps/global/argo-workflows.yaml b/apps/global/argo-workflows.yaml new file mode 100644 index 000000000..844af9640 --- /dev/null +++ b/apps/global/argo-workflows.yaml @@ -0,0 +1,51 @@ +--- +component: argo +sources: + - ref: understack + path: 'components/argo' + kustomize: + patches: + - target: + kind: ConfigMap + name: workflow-controller-configmap + patch: |- + - op: replace + path: /data/sso + value: |- + # This is the root URL of the OIDC provider (required). + issuer: https://dex.{{index .metadata.annotations "dns_zone" }} + # This defines how long your login is valid for (in hours). (optional) + # If omitted, defaults to 10h. Example below is 10 days. + sessionExpiry: 240h + # This is name of the secret and the key in it that contain OIDC client + # ID issued to the application by the provider (required). + clientId: + name: argo-sso + key: client-id + # This is name of the secret and the key in it that contain OIDC client + # secret issued to the application by the provider (required). + clientSecret: + name: argo-sso + key: client-secret + # This is the redirect URL supplied to the provider (optional). It must + # be in the form /oauth2/callback. It must be + # browser-accessible. If omitted, will be automatically generated. + redirectUrl: https://workflows.{{index .metadata.annotations "dns_zone"}}/oauth2/callback + # Additional scopes to request. Typically needed for SSO RBAC. >= v2.12 + scopes: + - groups + - email + - profile + # RBAC Config. >= v2.12 + rbac: + enabled: false + - target: + kind: Ingress + name: argo-workflows + patch: |- + - op: replace + path: /spec/rules/0/host + value: workflows.{{index .metadata.annotations "dns_zone" }} + - op: replace + path: /spec/tls/0/hosts/0 + value: workflows.{{index .metadata.annotations "dns_zone" }} diff --git a/apps/global/dex.yaml b/apps/global/dex.yaml new file mode 100644 index 000000000..4ae5e4b81 --- /dev/null +++ b/apps/global/dex.yaml @@ -0,0 +1,16 @@ +--- +component: dex +sources: + - repoURL: https://charts.dexidp.io + chart: dex + targetRevision: 0.16.0 + helm: + releaseName: dex + valueFiles: + - $understack/components/dex/values.yaml + - $deploy/{{.name}}/helm-configs/dex.yaml + ignoreMissingValueFiles: true + - ref: understack + path: 'components/dex' + - ref: deploy + path: '{{.name}}/manifests/dex' diff --git a/apps/global/nautobot.yaml b/apps/global/nautobot.yaml new file mode 100644 index 000000000..4e49dd9d4 --- /dev/null +++ b/apps/global/nautobot.yaml @@ -0,0 +1,19 @@ +--- +component: nautobot +sources: + - repoURL: https://nautobot.github.io/helm-charts/ + chart: nautobot + targetRevision: 2.4.6 + helm: + releaseName: nautobot + valueFiles: + - $understack/components/nautobot/values.yaml + - $deploy/{{.name}}/helm-configs/nautobot.yaml + ignoreMissingValueFiles: true + fileParameters: + - name: nautobot.config + path: $understack/components/nautobot/nautobot_config.py + - ref: understack + path: 'components/nautobot' + - ref: deploy + path: '{{.name}}/manifests/nautobot' diff --git a/apps/global/understack-workflows.yaml b/apps/global/understack-workflows.yaml new file mode 100644 index 000000000..3be0fef2b --- /dev/null +++ b/apps/global/understack-workflows.yaml @@ -0,0 +1,6 @@ +--- +component: understack-workflows +componentNamespace: argo-events +sources: + - ref: understack + path: 'workflows' diff --git a/apps/kustomization.yaml b/apps/kustomization.yaml index 0c26d6532..761e1dfb5 100644 --- a/apps/kustomization.yaml +++ b/apps/kustomization.yaml @@ -8,6 +8,8 @@ resources: - appsets/appset-understack-operators.yaml - appsets/components.yaml - appsets/openstack.yaml +- appsets/appset-understack-global.yaml +- appsets/appset-understack-site.yaml - appsets/appset-understack-openstack.yaml # you can do something like below to allow your deployment repo diff --git a/apps/site/chrony.yaml b/apps/site/chrony.yaml new file mode 100644 index 000000000..c9c2680f7 --- /dev/null +++ b/apps/site/chrony.yaml @@ -0,0 +1,6 @@ +--- +component: chrony +componentNamespace: openstack +sources: + - ref: understack + path: 'components/chrony' diff --git a/apps/site/openstack-exporter.yaml b/apps/site/openstack-exporter.yaml new file mode 100644 index 000000000..f0f03bfbe --- /dev/null +++ b/apps/site/openstack-exporter.yaml @@ -0,0 +1,15 @@ +--- +component: openstack-exporter +componentNamespace: monitoring +sources: + - repoURL: registry.scs.community/openstack-exporter + chart: prometheus-openstack-exporter + targetRevision: 0.4.5 + helm: + releaseName: prometheus-openstack-exporter + valueFiles: + - $understack/components/openstack-exporter/values.yaml + - $deploy/{{.name}}/helm-configs/openstack-exporter.yaml + ignoreMissingValueFiles: true + - ref: understack + - ref: deploy diff --git a/apps/site/openstack.yaml b/apps/site/openstack.yaml new file mode 100644 index 000000000..509e25e9a --- /dev/null +++ b/apps/site/openstack.yaml @@ -0,0 +1,7 @@ +--- +component: openstack +sources: + - ref: understack + path: 'components/openstack' + - ref: deploy + path: '{{.name}}/manifests/openstack' diff --git a/apps/site/otel-collector.yaml b/apps/site/otel-collector.yaml new file mode 100644 index 000000000..f0f36f4be --- /dev/null +++ b/apps/site/otel-collector.yaml @@ -0,0 +1,6 @@ +--- +component: otel-collector +componentNamespace: otel-collector +sources: + - ref: deploy + path: '{{.name}}/manifests/otel-collector' diff --git a/apps/site/snmp-exporter.yaml b/apps/site/snmp-exporter.yaml new file mode 100644 index 000000000..9f1580420 --- /dev/null +++ b/apps/site/snmp-exporter.yaml @@ -0,0 +1,14 @@ +--- +component: snmp-exporter +componentNamespace: monitoring +sources: + - repoURL: https://prometheus-community.github.io/helm-charts + chart: prometheus-snmp-exporter + targetRevision: 5.6.0 + helm: + releaseName: prometheus-snmp-exporter + valueFiles: + - $deploy/{{.name}}/helm-configs/prometheus-snmp-exporter.yaml + ignoreMissingValueFiles: true + - ref: understack + - ref: deploy diff --git a/apps/site/understack-cluster-issuer.yaml b/apps/site/understack-cluster-issuer.yaml new file mode 100644 index 000000000..d118ee288 --- /dev/null +++ b/apps/site/understack-cluster-issuer.yaml @@ -0,0 +1,6 @@ +--- +component: understack-cluster-issuer +componentNamespace: cert-manager +sources: + - ref: deploy + path: '{{.name}}/manifests/cert-manager' diff --git a/apps/site/undersync.yaml b/apps/site/undersync.yaml new file mode 100644 index 000000000..844aedf54 --- /dev/null +++ b/apps/site/undersync.yaml @@ -0,0 +1,7 @@ +--- +component: undersync +sources: + - ref: understack + path: 'components/undersync' + - ref: deploy + path: '{{.name}}/manifests/undersync' From 132b73fc454215ada605ece53143aa14a175fdb3 Mon Sep 17 00:00:00 2001 From: Doug Goldstein Date: Wed, 4 Jun 2025 20:27:00 -0500 Subject: [PATCH 4/5] feat(argocd): workaround the inability to have authed components So want to use kustomize components for overriding kustomize things. Components work great and allow for URL based data fetching. However within ArgoCD authenticated URLs to components do not seem to work. That appears to be because kustomize wants URI style SSH paths while ArgoCD's repo secrets use the SSH style. Likely the best thing here would be to support cross-repo refs like the helm code does but this does not appear to be supported in upstream ArgoCD at this time. In an effort to land the updates to the deployment process this hack was made as a workaround. It should be retired and go away when components are properly handled. --- apps/appsets/appset-understack-global.yaml | 2 +- apps/global/argo-workflows.yaml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/appsets/appset-understack-global.yaml b/apps/appsets/appset-understack-global.yaml index b269e9832..5a31c795b 100644 --- a/apps/appsets/appset-understack-global.yaml +++ b/apps/appsets/appset-understack-global.yaml @@ -133,7 +133,7 @@ spec: {{- end }} {{- end }} {{- if hasKey $source "kustomize" }} - kustomize: {{ $source.kustomize | toJson }} + kustomize: {{ $source.kustomize | toJson | replace "{{.dns_zone}}" (index $root.metadata.annotations "dns_zone") }} {{- end }} {{- if hasKey $source "path" }} path: {{ $source.path | replace "{{.name}}" $root.name }} diff --git a/apps/global/argo-workflows.yaml b/apps/global/argo-workflows.yaml index 844af9640..08ec167d4 100644 --- a/apps/global/argo-workflows.yaml +++ b/apps/global/argo-workflows.yaml @@ -13,7 +13,7 @@ sources: path: /data/sso value: |- # This is the root URL of the OIDC provider (required). - issuer: https://dex.{{index .metadata.annotations "dns_zone" }} + issuer: https://dex.{{.dns_zone}} # This defines how long your login is valid for (in hours). (optional) # If omitted, defaults to 10h. Example below is 10 days. sessionExpiry: 240h @@ -30,7 +30,7 @@ sources: # This is the redirect URL supplied to the provider (optional). It must # be in the form /oauth2/callback. It must be # browser-accessible. If omitted, will be automatically generated. - redirectUrl: https://workflows.{{index .metadata.annotations "dns_zone"}}/oauth2/callback + redirectUrl: https://workflows.{{.dns_zone}}/oauth2/callback # Additional scopes to request. Typically needed for SSO RBAC. >= v2.12 scopes: - groups @@ -45,7 +45,7 @@ sources: patch: |- - op: replace path: /spec/rules/0/host - value: workflows.{{index .metadata.annotations "dns_zone" }} + value: workflows.{{.dns_zone}} - op: replace path: /spec/tls/0/hosts/0 - value: workflows.{{index .metadata.annotations "dns_zone" }} + value: workflows.{{.dns_zone}} From fc7f12315e5f8af2ae5f175eb654faa0e86bc31f Mon Sep 17 00:00:00 2001 From: Doug Goldstein Date: Fri, 6 Jun 2025 11:09:10 -0500 Subject: [PATCH 5/5] feat(argocd): remove old components and openstack AppSets These have been replaced with newer files which split the components out along the lines of site or global deployments. These are redundant now. --- apps/appsets/components.yaml | 270 ----------------------------------- apps/appsets/openstack.yaml | 110 -------------- apps/kustomization.yaml | 2 - 3 files changed, 382 deletions(-) delete mode 100644 apps/appsets/components.yaml delete mode 100644 apps/appsets/openstack.yaml diff --git a/apps/appsets/components.yaml b/apps/appsets/components.yaml deleted file mode 100644 index b6790a710..000000000 --- a/apps/appsets/components.yaml +++ /dev/null @@ -1,270 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: ApplicationSet -metadata: - name: components -spec: - syncPolicy: - preserveResourcesOnDeletion: true - applicationsSync: create-update - goTemplate: true - goTemplateOptions: ["missingkey=error"] - generators: - - matrix: - generators: - - clusters: - selector: - matchLabels: - argocd.argoproj.io/secret-type: cluster - - list: - elements: - - component: understack-cluster-issuer - componentNamespace: cert-manager - skipComponent: '{{has "understack-cluster-issuer" ((default "[]" (index .metadata.annotations "uc_skip_components") | fromJson))}}' - sources: - - repoURL: '{{index .metadata.annotations "uc_deploy_git_url"}}' - targetRevision: '{{index .metadata.annotations "uc_deploy_ref"}}' - path: '{{.name}}/manifests/cert-manager' - - component: dex - skipComponent: '{{has "dex" ((default "[]" (index .metadata.annotations "uc_skip_components") | fromJson))}}' - sources: - - repoURL: https://charts.dexidp.io - chart: dex - targetRevision: 0.16.0 - helm: - releaseName: dex - valuesObject: - config: - issuer: 'https://dex.{{index .metadata.annotations "dns_zone" }}' - env: - DNS_ZONE: '{{index .metadata.annotations "dns_zone" }}' - ingress: - hosts: - - host: dex.{{index .metadata.annotations "dns_zone" }} - paths: - - path: / - pathType: Prefix - tls: - - secretName: dex-ingress-tls - hosts: - - dex.{{index .metadata.annotations "dns_zone" }} - valueFiles: - - $understack/components/dex/values.yaml - - $deploy/{{.name}}/helm-configs/dex.yaml - ignoreMissingValueFiles: true - - repoURL: '{{index .metadata.annotations "uc_repo_git_url"}}' - targetRevision: '{{index .metadata.annotations "uc_repo_ref"}}' - path: 'components/dex' - ref: understack - - repoURL: '{{index .metadata.annotations "uc_deploy_git_url"}}' - targetRevision: '{{index .metadata.annotations "uc_deploy_ref"}}' - ref: deploy - path: '{{.name}}/manifests/dex' - - component: openstack - skipComponent: '{{has "openstack" ((default "[]" (index .metadata.annotations "uc_skip_components") | fromJson))}}' - sources: - - repoURL: '{{index .metadata.annotations "uc_repo_git_url"}}' - targetRevision: '{{index .metadata.annotations "uc_repo_ref"}}' - path: 'components/openstack' - - repoURL: '{{index .metadata.annotations "uc_deploy_git_url"}}' - targetRevision: '{{index .metadata.annotations "uc_deploy_ref"}}' - path: '{{.name}}/manifests/openstack' - - component: undersync - skipComponent: '{{has "undersync" ((default "[]" (index .metadata.annotations "uc_skip_components") | fromJson))}}' - sources: - - repoURL: '{{index .metadata.annotations "uc_repo_git_url"}}' - targetRevision: '{{index .metadata.annotations "uc_repo_ref"}}' - path: 'components/undersync' - - repoURL: '{{index .metadata.annotations "uc_deploy_git_url"}}' - targetRevision: '{{index .metadata.annotations "uc_deploy_ref"}}' - path: '{{.name}}/manifests/undersync' - - component: nautobot - skipComponent: '{{has "nautobot" ((default "[]" (index .metadata.annotations "uc_skip_components") | fromJson))}}' - sources: - - repoURL: https://nautobot.github.io/helm-charts/ - chart: nautobot - targetRevision: 2.4.6 - helm: - releaseName: nautobot - valuesObject: - ingress: - hostname: 'nautobot.{{index .metadata.annotations "dns_zone" }}' - valueFiles: - - $understack/components/nautobot/values.yaml - - $deploy/{{.name}}/helm-configs/nautobot.yaml - ignoreMissingValueFiles: true - fileParameters: - - name: nautobot.config - path: $understack/components/nautobot/nautobot_config.py - - repoURL: '{{index .metadata.annotations "uc_repo_git_url"}}' - targetRevision: '{{index .metadata.annotations "uc_repo_ref"}}' - path: 'components/nautobot' - ref: understack - - repoURL: '{{index .metadata.annotations "uc_deploy_git_url"}}' - targetRevision: '{{index .metadata.annotations "uc_deploy_ref"}}' - ref: deploy - path: '{{.name}}/manifests/nautobot' - - component: argo - skipComponent: '{{has "argo" ((default "[]" (index .metadata.annotations "uc_skip_components") | fromJson))}}' - source: - repoURL: '{{index .metadata.annotations "uc_repo_git_url"}}' - targetRevision: '{{index .metadata.annotations "uc_repo_ref"}}' - path: 'components/argo' - kustomize: - patches: - - target: - kind: ConfigMap - name: workflow-controller-configmap - patch: |- - - op: replace - path: /data/sso - value: |- - # This is the root URL of the OIDC provider (required). - issuer: https://dex.{{index .metadata.annotations "dns_zone" }} - # This defines how long your login is valid for (in hours). (optional) - # If omitted, defaults to 10h. Example below is 10 days. - sessionExpiry: 240h - # This is name of the secret and the key in it that contain OIDC client - # ID issued to the application by the provider (required). - clientId: - name: argo-sso - key: client-id - # This is name of the secret and the key in it that contain OIDC client - # secret issued to the application by the provider (required). - clientSecret: - name: argo-sso - key: client-secret - # This is the redirect URL supplied to the provider (optional). It must - # be in the form /oauth2/callback. It must be - # browser-accessible. If omitted, will be automatically generated. - redirectUrl: https://workflows.{{index .metadata.annotations "dns_zone"}}/oauth2/callback - # Additional scopes to request. Typically needed for SSO RBAC. >= v2.12 - scopes: - - groups - - email - - profile - # RBAC Config. >= v2.12 - rbac: - enabled: false - - target: - kind: Ingress - name: argo-workflows - patch: |- - - op: replace - path: /spec/rules/0/host - value: workflows.{{index .metadata.annotations "dns_zone" }} - - op: replace - path: /spec/tls/0/hosts/0 - value: workflows.{{index .metadata.annotations "dns_zone" }} - - component: argo-events - skipComponent: '{{has "argo-events" ((default "[]" (index .metadata.annotations "uc_skip_components") | fromJson))}}' - sources: - - repoURL: '{{index .metadata.annotations "uc_repo_git_url"}}' - targetRevision: '{{index .metadata.annotations "uc_repo_ref"}}' - path: 'components/argo-events' - - repoURL: '{{index .metadata.annotations "uc_deploy_git_url"}}' - targetRevision: '{{index .metadata.annotations "uc_deploy_ref"}}' - path: '{{.name}}/manifests/argo-events' - - component: understack-workflows - componentNamespace: argo-events - skipComponent: '{{has "understack-workflows" ((default "[]" (index .metadata.annotations "uc_skip_components") | fromJson))}}' - sources: - - repoURL: '{{index .metadata.annotations "uc_repo_git_url"}}' - targetRevision: '{{index .metadata.annotations "uc_repo_ref"}}' - path: 'workflows' - - component: chrony - componentNamespace: openstack - skipComponent: '{{has "chrony" ((default "[]" (index .metadata.annotations "uc_skip_components") | fromJson))}}' - sources: - - repoURL: '{{index .metadata.annotations "uc_repo_git_url"}}' - targetRevision: '{{index .metadata.annotations "uc_repo_ref"}}' - path: 'components/chrony' - - component: openstack-exporter - componentNamespace: monitoring - skipComponent: '{{has "openstack-exporter" ((default "[]" (index .metadata.annotations "uc_skip_components") | fromJson))}}' - sources: - - repoURL: registry.scs.community/openstack-exporter - chart: prometheus-openstack-exporter - targetRevision: 0.4.5 - helm: - releaseName: prometheus-openstack-exporter - valueFiles: - - $deploy/{{.name}}/helm-configs/openstack-exporter.yaml - ignoreMissingValueFiles: true - - repoURL: '{{index .metadata.annotations "uc_repo_git_url"}}' - targetRevision: '{{index .metadata.annotations "uc_repo_ref"}}' - ref: understack - - repoURL: '{{index .metadata.annotations "uc_deploy_git_url"}}' - targetRevision: '{{index .metadata.annotations "uc_deploy_ref"}}' - ref: deploy - - component: snmp-exporter - componentNamespace: monitoring - skipComponent: '{{has "snmp-exporter" ((default "[]" (index .metadata.annotations "uc_skip_components") | fromJson))}}' - sources: - - repoURL: https://prometheus-community.github.io/helm-charts - chart: prometheus-snmp-exporter - targetRevision: 5.6.0 - helm: - releaseName: prometheus-snmp-exporter - valueFiles: - - $deploy/{{.name}}/helm-configs/prometheus-snmp-exporter.yaml - ignoreMissingValueFiles: true - - repoURL: '{{index .metadata.annotations "uc_repo_git_url"}}' - targetRevision: '{{index .metadata.annotations "uc_repo_ref"}}' - ref: understack - - repoURL: '{{index .metadata.annotations "uc_deploy_git_url"}}' - targetRevision: '{{index .metadata.annotations "uc_deploy_ref"}}' - ref: deploy - - component: otel-collector - componentNamespace: otel-collector - skipComponent: '{{has "otel-collector" ((default "[]" (index .metadata.annotations "uc_skip_components") | fromJson))}}' - sources: - - repoURL: '{{index .metadata.annotations "uc_deploy_git_url"}}' - targetRevision: '{{index .metadata.annotations "uc_deploy_ref"}}' - path: '{{.name}}/manifests/otel-collector' - selector: - # by setting the key in the elements 'skipComponent' to 'true' it will skip installing it - # ArgoCD's templating operates with strings so it's the string "true" - matchExpressions: - - key: skipComponent - operator: NotIn - values: - - "true" - template: - metadata: - name: '{{.name}}-{{.component}}' - # we should never set the finalizer here as the applicationsSync policy will handle it - annotations: - argocd.argoproj.io/compare-options: ServerSideDiff=true,IncludeMutationWebhook=true - spec: - project: default - destination: - server: '{{.server}}' - namespace: '{{coalesce (get . "componentNamespace") .component}}' - syncPolicy: - automated: - selfHeal: true - syncOptions: - - CreateNamespace=true - - ServerSideApply=true - - RespectIgnoreDifferences=true - managedNamespaceMetadata: - annotations: - # ArgoCD can create our namespace but let's not delete it - argocd.argoproj.io/sync-options: Delete=false - templatePatch: | - spec: - {{- if hasKey . "source" }} - # indentation matters here. need to collapse to a single line to preserve it - source: {{ .source | toJson }} - {{- end }} - {{- if hasKey . "sources" }} - sources: - {{- range $source := .sources }} - # indentation matters so collapse to single line with toJson to keep it - - {{ $source | toJson }} - {{- end }} - {{- end }} - {{- if hasKey . "ignoreDifferences" }} - # indentation matters so collapse to single line with toJson to keep it - ignoreDifferences: {{ .ignoreDifferences | toJson }} - {{- end }} diff --git a/apps/appsets/openstack.yaml b/apps/appsets/openstack.yaml deleted file mode 100644 index f17f99d3e..000000000 --- a/apps/appsets/openstack.yaml +++ /dev/null @@ -1,110 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: ApplicationSet -metadata: - name: openstack -spec: - syncPolicy: - preserveResourcesOnDeletion: true - applicationsSync: create-update - goTemplate: true - goTemplateOptions: ["missingkey=error"] - generators: - - matrix: - generators: - - clusters: - selector: - matchLabels: - argocd.argoproj.io/secret-type: cluster - - list: - elements: - - component: keystone - repoURL: https://tarballs.opendev.org/openstack/openstack-helm - chartVersion: 2024.2.6+06d763432 - - component: openvswitch - repoURL: https://tarballs.opendev.org/openstack/openstack-helm-infra - chartVersion: 2024.2.0 - - component: ovn - repoURL: https://tarballs.opendev.org/openstack/openstack-helm-infra - chartVersion: 2024.2.0 - - component: ironic - repoURL: https://tarballs.opendev.org/openstack/openstack-helm - chartVersion: 0.2.21 - - component: placement - repoURL: https://tarballs.opendev.org/openstack/openstack-helm - chartVersion: 2024.2.1+34d1672a-93ed069c - - component: neutron - repoURL: https://tarballs.opendev.org/openstack/openstack-helm - chartVersion: 0.3.47 - - component: glance - repoURL: https://tarballs.opendev.org/openstack/openstack-helm - chartVersion: 0.5.2 - - component: nova - repoURL: https://tarballs.opendev.org/openstack/openstack-helm - chartVersion: 2024.2.8+f37dd907f - - component: horizon - repoURL: https://tarballs.opendev.org/openstack/openstack-helm - chartVersion: 2024.2.1+34d1672a-93ed069c - - component: skyline - repoURL: https://tarballs.opendev.org/openstack/openstack-helm - chartVersion: 2025.1.1+12830ffa1 - template: - metadata: - name: '{{.name}}-{{.component}}' - # we should never set the finalizer here as the applicationsSync policy will handle it - annotations: - argocd.argoproj.io/compare-options: ServerSideDiff=true,IncludeMutationWebhook=true - spec: - project: default - sources: - - repoURL: '{{.repoURL}}' - chart: '{{.component}}' - targetRevision: '{{.chartVersion}}' - helm: - releaseName: '{{.component}}' - valueFiles: - # default upstream images - - $understack/components/images-openstack.yaml - # default values for each component - - $understack/components/{{.component}}/values.yaml - # current global secret data per deployment - - $deploy/{{.name}}/manifests/secret-openstack.yaml - # optional file to allow users to override upstream images - - $deploy/{{.name}}/manifests/images-openstack.yaml - # optional file to allow users to override component values - - $deploy/{{.name}}/helm-configs/{{.component}}.yaml - # don't require all the values files - ignoreMissingValueFiles: true - - repoURL: '{{index .metadata.annotations "uc_repo_git_url"}}' - path: components/{{.component}}/ - targetRevision: '{{index .metadata.annotations "uc_repo_ref"}}' - ref: understack - - repoURL: '{{index .metadata.annotations "uc_deploy_git_url"}}' - targetRevision: '{{index .metadata.annotations "uc_deploy_ref"}}' - path: '{{.name}}/manifests/{{.component}}' - ref: deploy - ignoreDifferences: - - kind: Secret - name: keystone-fernet-keys - jqPathExpressions: - - .data - - kind: Secret - name: keystone-credential-keys - jqPathExpressions: - - .data - destination: - server: '{{.server}}' - namespace: openstack - syncPolicy: - automated: - selfHeal: true - syncOptions: - - CreateNamespace=true - - ServerSideApply=true - - RespectIgnoreDifferences=true - managedNamespaceMetadata: - annotations: - # ArgoCD can create our namespace but let's not delete it - argocd.argoproj.io/sync-options: Delete=false - labels: - kubernetes.io/metadata.name: openstack - name: openstack diff --git a/apps/kustomization.yaml b/apps/kustomization.yaml index 761e1dfb5..f5a0276c7 100644 --- a/apps/kustomization.yaml +++ b/apps/kustomization.yaml @@ -6,8 +6,6 @@ resources: - appsets/project-understack.yaml - appsets/appset-understack-infra.yaml - appsets/appset-understack-operators.yaml -- appsets/components.yaml -- appsets/openstack.yaml - appsets/appset-understack-global.yaml - appsets/appset-understack-site.yaml - appsets/appset-understack-openstack.yaml