{{- $top := . -}} {{- range $i, $config := .Values.appSpec }} --- {{- $appName := $config.name -}} {{- $appNameOverride := $config.nameOverride -}} {{- $clusterValues := $top.Values.clusterSpec -}} {{- $clusterName := $clusterValues.destination.name -}} {{- $clusterServer := $clusterValues.destination.server -}} {{- $teamValues := $top.Values.teamSpec.devops -}} {{- $labels := $teamValues.labels -}} {{- $bu := $labels.bu -}} {{- $cluster := $labels.cluster | replace "dp-" "#pqr#" | replace "backup" "#abc#" | replace "p-" "" | replace "prd-" "" | replace "int-" "" | replace "dev-" "" | replace "-cluster" "" | replace "prod-ops" "infra" | replace "-ase1c" "-c" | replace "-ase1a" "-a" | replace "-ase1" "" | replace "k8s-" "" | replace "gke-" "" | replace "#pqr#" "dp-" | replace "#abc#" "backup" -}} {{- $team := $labels.team -}} {{- $env := $labels.env -}} {{- $source := $teamValues.source -}} {{- $repoURL := $source.repoURL -}} {{- $targetRevision := $source.targetRevision -}} {{- $namespace := $config.namespace -}} {{- $path := printf "%s/%s" $source.path $config.chartDir -}} {{- $valueFiles := printf "%s/%s/custom-values.yaml" $source.valueFiles $config.valuesDir -}} {{- $additionalValueFiles := $config.additionalValueFiles | default list -}} {{ $argoAppNamespace := $top.Values.argocdSpec.namespace }} {{- $compareOptions := $config.compareOptions | default list -}} apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: '{{- if $appNameOverride }}{{ $appNameOverride }}{{- else }}{{ printf "%s-%s-%s" $appName $cluster $env }}{{- end }}' namespace: {{ $argoAppNamespace }} {{- if $compareOptions }} annotations: # Opt-in per appSpec entry, as a list of Argo CD compare options. # # The one that matters here is ServerSideDiff=true, which is the escape # hatch for "field not declared in schema" diff failures. Argo CD # normally computes the diff locally against a Kubernetes schema baked # into its own binary, so a cluster newer than Argo CD has fields Argo # CD has never heard of and the diff aborts. This option asks the API # server to compute the diff instead (a dry-run apply), and the API # server necessarily knows its own fields. argocd.argoproj.io/compare-options: {{ join "," $compareOptions | quote }} {{- end }} labels: {{ toYaml $labels | indent 4 }} finalizers: - resources-finalizer.argocd.argoproj.io spec: project: {{ $team }} source: repoURL: {{ $repoURL }} targetRevision: {{ $targetRevision }} path: {{ $path }} helm: valueFiles: - {{ $valueFiles }} {{- if $additionalValueFiles }} {{- range $additionalValueFiles }} - {{ . }} {{- end }} {{- end }} destination: name: {{ $clusterName }} server: {{ $clusterServer }} namespace: {{ $namespace }} syncPolicy: syncOptions: - CreateNamespace=true {{- if $config.replace }} # Opt-in per appSpec entry. Needed when adopting a resource that was # created outside Argo (no last-applied-configuration annotation for # a normal patch to diff against) and has a field the new manifest # changes type on (e.g. an env var moving from `value` to # `valueFrom`) — a patch can add the new field without clearing the # old one, which the API rejects either way, patch or SSA. Replace # does a full PUT of the whole object instead of a merge, so the # submitted spec never contains the stale field at all. - Replace=true {{- end }} {{- if $config.serverSideApply }} # Opt-in per appSpec entry. Distinct from `replace` above — this is # for CRDs whose full manifest (schema included) exceeds the 256KiB # limit Kubernetes puts on the last-applied-configuration annotation # a normal client-side apply writes (external-secrets' CRDs, e.g. # ClusterSecretStore, hit this — they embed large OpenAPI schemas to # cover many provider-specific fields). SSA doesn't use that # annotation at all, so there's no size ceiling to hit. Non- # destructive, unlike Replace — safe as a default reach-for for a # "CRD too large" error specifically. - ServerSideApply=true {{- end }} {{- end }}