apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: k8s-apps-helm-application-set-v1
  namespace: argocd
  annotations:
    argocd.argoproj.io/debug: "true"
spec:
  goTemplate: true
  goTemplateOptions: ["missingkey=error"]
  applyNestedSelectors: true
  generators:
    # Create a matrix generator that will install all chart in all clusters
    - matrix:
        generators:
          - matrix:
              generators:
                # Get all clusters, that are appropriately labeled
                - clusters:
                    selector:
                      matchExpressions:
                        - key: stage-name
                          operator: Exists
                        - key: cluster-name
                          operator: Exists
                # In this repo, find all files named argocd.json.
                # The files are expected to contain {apiVersion: "ysoft.com/v1"}
                - git:
                    repoURL: https://github.com/ysoftdevs/argo-poc.git
                    revision: main
                    files:
                      - path: "apps/**/argocd.json"
                    values:
                      stageName: '{{ index .metadata.labels "stage-name" }}'
                      clusterName: '{{ index .metadata.labels "cluster-name" }}'
                      provider: '{{ index .metadata.labels "provider" | default "aws" }}'
                  selector:
                    matchLabels:
                      apiVersion: "ysoft.com/v1"
          - list:
              # List of one element is a workaround to Argo's inabilility to access '.values.enabled' (which is a result of git generator) in a selector.
              # The list generator transforms that into '.enabled', which works
              # As a side effect, it also allows access to previously defined values, like '.values.stageName'
              elements:
                # The selector also had troubles with booleans vs. strings, hence the 'yes' and not 'true'
                - enabled: '{{ dig "clusters" .values.stageName .values.clusterName "enabled" false . | ternary "yes" "" }}'
                  appName: "{{ .path.basename }}"
            selector:
              matchLabels:
                enabled: "yes"
  template:
    metadata:
      name: "{{ .path.basename }}-{{.values.stageName }}-{{ .values.clusterName }}"
    spec:
      project: default
      destination:
        server: "{{.server}}"
        namespace: "{{ .destination.namespace }}"
      syncPolicy:
        automated:
          prune: true
        syncOptions:
          - ServerSideApply={{ dig "syncPolicy" "syncOptions" "ServerSideApply" "true" . }}
          - CreateNamespace={{ dig "syncPolicy" "syncOptions" "CreateNamespace" "true" . }}
  templatePatch: |
    spec:
      sources:
        # First source is for value files
        # Default revision is HEAD but can be overriden with clusters.${name}.valuesRevision
        - repoURL: https://github.com/ysoftdevs/argo-poc.git
          targetRevision: '{{ dig "stages" .values.stageName "valuesRevision" (dig "valuesRevision" "" .source) . }}'
          ref: values
        # Second source is for chart
        # Default revision is .source.targetRevision but can be overriden with clusters.${name}.chartRevision
        - repoURL: "{{ .source.repoURL }}"
          targetRevision: '{{ dig "stages" .values.stageName "chartRevision" (dig "chartRevision" "" .source)  . }}'
          ref: chart
          chart: '{{ default "" .source.chart }}'
          path: '{{ default "" .source.path }}'
          helm:
            releaseName: "{{ .path.basename }}"
            valueFiles: {{- $v := .values }}{{- $ := . }}
            {{- range $valueFile := ( .valueFiles ) }}
              - $values/apps/{{$.appName}}/{{ $valueFile | replace "%provider%" $v.provider | replace "%stage%" $v.stageName | replace "%cluster%" $v.clusterName  }}
            {{- end }}
