apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: test-hello-world-appset
  namespace: argocd
  # To preserve this annotation and label we can use the preservedFields property 
  preservedFields:
    # This annotation and label exists only on this Application, and not in 
    # the parent ApplicationSet template:
    # ignoreApplicationDifferences is the preferred way to accomplish this now.
    annotations: 
      my-custom-annotation: some-value
    labels:
      my-custom-label: some-value

spec:
  generators:

    # Using a generator plugin without combining it with Matrix or Merge
    # Plugins allow you to provide your own generator
    - plugin:
      # Specify the configMap where the plugin configuration is located.
      configMapRef:
        name: my-plugin
      # You can pass arbitrary parameters to the plugin. `input.parameters` is a map, but values may be any type.
      # These parameters will also be available on the generator's output under the `generator.input.parameters` key.
      input:
        parameters:
          key1: "value1"
          key2: "value2"
          list: ["list", "of", "values"]
          boolean: true
          map:
            key1: "value1"
            key2: "value2"
            key3: "value3"
        # You can also attach arbitrary values to the generator's output under the `values` key. These values will be
        # available in templates under the `values` key.
        values:
          value1: something
        # When using a Plugin generator, the ApplicationSet controller polls every `requeueAfterSeconds` interval (defaulting to every 30 minutes) to detect changes.
        requeueAfterSeconds: 30

    # to automatically discover repositories within an organization
    - scmProvider:
        # Which protocol to clone using.
        cloneProtocol: ssh
        # The GitHub mode uses the GitHub API to scan an organization in either github.com or GitHub Enterprise
        github:
          # The GitHub organization to scan.
          organization: myorg
          # For GitHub Enterprise:
          api: https://git.example.com/
          # If true, scan every branch of every repository. If false, scan only the default branch. Defaults to false.
          allBranches: true
          # Reference to a Secret containing an access token. (optional)
          tokenRef:
            secretName: github-token
            key: token
          # (optional) use a GitHub App to access the API instead of a PAT.
          appSecretName: gh-app-repo-creds
          #Pass additional key-value pairs via values field
          values:
            name: "{{organization}}-{{repository}}"

        #The GitLab mode uses the GitLab API to scan and organization in either gitlab.com or self-hosted GitLab.  
        gitlab:
        #The Gitea mode uses the Gitea API to scan organizations in your instance
        gitea:
        #Use the Bitbucket Server API (1.0) to scan repos in a project.
        bitbucketServer:
        #Uses the Azure DevOps API to look up eligible repositories 
        azureDevOps:
        # The Bitbucket mode uses the Bitbucket API V2 to scan a workspace in bitbucket.org
        bitbucket:
        #Uses AWS ResourceGroupsTagging and AWS CodeCommit APIs to scan repos across AWS accounts and regionsz
        awsCodeCommit:

        #Filters allow selecting which repositories to generate for. 
        filters:
        # Include any repository starting with "myapp" AND including a Kustomize config AND labeled with "deploy-ok" ...
        - repositoryMatch: ^myapp
          pathsExist: [kubernetes/kustomization.yaml]
          labelMatch: deploy-ok
        # ... OR include any repository starting with "otherapp" AND a Helm folder and doesn't have file disabledrepo.txt.
        - repositoryMatch: ^otherapp
          pathsExist: [helm]
          pathsDoNotExist: [disabledrepo.txt]
    # matrix 'parent' generator
    - matrix:
        generators:
        # any of the top-level generators may be used here instead.
  
    # merge 'parent' generator
    # Use the selector set by both child generators to combine them.
    - merge:
        mergeKeys:
          - server
          # Note that this would not work with goTemplate enabled,
          # nested merge keys are not supported there.
          - values.selector
        generators:
          - clusters:
              values:
                kafka: 'true'
                redis: 'false'
          # For clusters with a specific label, enable Kafka.
          - clusters:
              selector:
                matchLabels:
                  use-kafka: 'false'
              values:
                kafka: 'false'
          # For a specific cluster, enable Redis.
          - list:
              elements: 
                - server: https://2.4.6.8
                  values.redis: 'true'
                
              
  # Determines whether go templating will be used in the `template` field below.
  goTemplate: true
  # Optional list of go templating options, see https://pkg.go.dev/text/template#Template.Option
  # This is only relevant if `goTemplate` is true
  goTemplateOptions: ["missingkey=error"]

  # These fields are identical to the Application spec.
  # The generator's template field takes precedence over the spec's template fields
  template:
    metadata:
      name: test-hello-world-app
    spec:
      project: my-project
      syncPolicy: 
        automated:
          selfHeal: true    
        syncOptions:
        - CreateNamespace=true  
      # defines from which Git repository to extract the desired Application manifests
      source:
        - chart: '{{.chart}}'
        # developers may customize app details using JSON files from above repo URL
          repoURL: https://github.com/argoproj/argo-cd.git
          targetRevision: HEAD
          # Path within the repository where Kubernetes manifests are located
          path: applicationset/examples/list-generator/guestbook/{{cluster}}
          helm:
            useCredentials: "{{.useCredentials}}"  # This field may NOT be templated, because it is a boolean field
          parameters:
          - name: "image.tag"
            value: "pull-{{head_sha}}"
          - name: "{{.name}}"
            value: "{{.value}}"
          - name: throw-away
            value: "{{end}}"
      destination:
        # Only one of name or server may be specified: if both are specified, an error is returned.
        #  Name of the cluster (within Argo CD) to deploy to
        name: production-cluster # cluster is restricted
        #  API Server URL for the cluster
        server: '{{.url}}'
        # Target namespace in which to deploy the manifests from source 
        namespace: dev-team-one # namespace is restricted

  # This sync policy pertains to the ApplicationSet, not to the Applications it creates.
  syncPolicy:
    # Prevents ApplicationSet controller from modifying or deleting Applications
    applicationsSync: create-only

    # Prevents ApplicationSet controller from deleting Applications. Update is allowed
  # applicationsSync: create-update

    # Prevents ApplicationSet controller from modifying Applications. Delete is allowed.
  # applicationsSync: create-delete

    syncOptions:
    - CreateNamespace=true
    # Prevent an Application's child resources from being deleted, when the parent Application is deleted
    preserveResourcesOnDeletion: true

    # which fields of the ApplicationSet should be ignored when comparing Applications.
    ignoreApplicationDifferences:
    - jsonPointers:
        - /spec/source/targetRevision
    - name: some-app
      jqExpressions:
        - .spec.source.helm.values

  strategy:
  # This field lets you define fields which should be ignored when applying Application resources. This is helpful if you
  # want to use ApplicationSets to create apps, but also want to allow users to modify those apps without having their
  # changes overwritten by the ApplicationSet.
     # This update strategy allows you to group Applications by labels present on the generated Application resources
     type: RollingSync
     rollingSync:
      steps:
        # Application groups are selected using their labels and matchExpressions
        - matchExpressions:
            - key: envLabel
              operator: In
              values:
                - env-dev
        # maxUpdate: 100%  # if undefined, all applications matched are updated together (default is 100%)
        - matchExpressions:
            - key: envLabel
              operator: In
              values:
                - env-qa
          maxUpdate: 0      # if 0, no matched applications will be synced unless they're synced manually
        - matchExpressions:
            - key: envLabel
              operator: In
              values:
                - env-prod
          maxUpdate: 10%    # maxUpdate supports both integer and percentage string values (rounds down, but floored at 1 Application for >0%)

  ignoreApplicationDifferences:
  - jsonPointers:
    - /spec/source/targetRevision
  - name: some-app
    jqPathExpressions:
    - .spec.source.helm.values

  # Cluster-decision-resource-based ApplicationSet generator
  - clusterDecisionResource:
    # ConfigMap with GVK information for the duck type resource
    configMapRef: my-configmap  
    name: quak           # Choose either "name" of the resource or "labelSelector"
    labelSelector:
      matchLabels:       # OPTIONAL
        duck: spotted
      matchExpressions:  # OPTIONAL
      - key: duck
        operator: In
        values:
        - "spotted"
        - "canvasback"   
    # OPTIONAL: Checks for changes every 60sec (default 3min)
    requeueAfterSeconds: 60
  
  # The Pull Request generator uses the API of an SCMaaS provider to automatically discover open pull requests within a repository
  - pullRequest:
      # When using a Pull Request generator, the ApplicationSet controller polls every `requeueAfterSeconds` interval (defaulting to every 30 minutes) to detect changes.
      requeueAfterSeconds: 1800
      # See below for provider specific options.
      # Specify the repository from which to fetch the GitHub Pull requests.
      github:
        # The GitHub organization or user.
        owner: myorg
        # The Github repository
        repo: myrepository
        # For GitHub Enterprise (optional)
        api: https://git.example.com/
        # Reference to a Secret containing an access token. (optional)
        tokenRef:
          secretName: github-token
          key: token
        # (optional) use a GitHub App to access the API instead of a PAT.
        appSecretName: github-app-repo-creds
        # Labels is used to filter the PRs that you want to target. (optional)
        labels:
        - preview

      # Filters allow selecting which pull requests to generate for
      # Include any pull request ending with "argocd". (optional)
      filters:
      - branchMatch: ".*-argocd"

      # Specify the project from which to fetch the GitLab merge requests.
      gitlab:
      # Specify the repository from which to fetch the Gitea Pull requests.
      gitea:
      # Fetch pull requests from a repo hosted on a Bitbucket Server (not the same as Bitbucket Cloud).
      bitbucketServer:
      # Fetch pull requests from a repo hosted on a Bitbucket Cloud.
      bitbucket:
      # Specify the organization, project and repository from which you want to fetch pull requests.
      azuredevops:
      # Fetch pull requests from AWS CodeCommit repositories.
      awsCodeCommit:

# The list generator generates a set of two application which then filter by the key value to only select the env with value staging
  - list:
      elements:
        - cluster: engineering-dev
          url: https://kubernetes.default.svc
          env: staging
        - cluster: engineering-prod
          url: https://kubernetes.default.svc
          env: prod
      # The generator's template field takes precedence over the spec's template fields
      template:
        metadata: {}
        spec:
          project: "default"
          source:
            revision: HEAD
            repoURL: https://github.com/argoproj/argo-cd.git
            # New path value is generated here:
            path: 'applicationset/examples/template-override/{{cluster}}-override'
          destination: {}

    selector:
      matchLabels:
        env: staging
  # It is also possible to use matchExpressions for more powerful selectors
  - clusters: {}
    selector:
      matchExpressions:
        - key: server
          operator: In
          values:
            - https://kubernetes.default.svc
            - https://some-other-cluster