argoproj / applicationset

The ApplicationSet controller manages multiple Argo CD Applications as a single ApplicationSet unit, supporting deployments to large numbers of clusters, deployments of large monorepos, and enabling secure Application self-service.
https://argocd-applicationset.readthedocs.io/
Apache License 2.0
584 stars 278 forks source link

Git generator with condition #598

Open rshiva777 opened 2 years ago

rshiva777 commented 2 years ago

I am using git generator for deploying applications. I want to deploy an application on to a cluster only if the cluster has particular labels matched in applicationset, else ignore it

If i remove the cluster generator part from the manifest and keep only git generator, application are creating on all the cluster configs that are present on the below path

applicationsets/git-generator/cluster-config/**/config.yaml

I want an feature where i can restrict the app deployment to destination cluster, it should happen only when the secret of cluster in argocd has the below label:

app: testapp

Below is a sample manifest

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: bgd
  namespace: openshift-gitops
spec:
  generators:
  - git:
      repoURL: https://github.com/christianh814/gitops-examples
      revision: master
      files:
      - path: "applicationsets/git-generator/cluster-config/**/config.yaml"
  - clusters:
      selector:
        matchLabels:
          app: testapp
  template:
    metadata:
      name: '{{cluster.name}}-bgd'
    spec:
      project: default
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
      source:
        repoURL: https://github.com/christianh814/gitops-examples
        targetRevision: master
        path: applicationsets/git-generator/overlays/{{cluster.overlay}}
      destination:
        server: '{{cluster.server}}'
        namespace: bgd

Here is the sample config file of a single cluster: applicationsets/git-generator/cluster-config/testcluster/config.yaml

cluster:
  name: testcluster
  server: test.apiserver.com:6443
  overlay: testapp

The above applicationset should create an application on if the destination cluster has the below labels in argocd secret:

app: testapp

I tried to check on merge generator with git and cluster generators, but didnt find any clues to use.

rshiva777 commented 2 years ago

can anyone look into this please?

rishabh625 commented 2 years ago

Hi @rshiva777 try matrix generator it works perfectly for your usecase

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: cluster-git
spec:
  generators:
    # matrix 'parent' generator
    - matrix:
        generators:
          # git generator, 'child' #1
          - git:
              repoURL: https://github.com/argoproj-labs/applicationset.git
              revision: HEAD
              directories:
                - path: examples/matrix/cluster-addons/*
          # cluster generator, 'child' #2
          - clusters:
              selector:
                matchLabels:
                  app: testapp
  template:
    metadata:
      name: '{{path.basename}}-{{name}}'
    spec:
      project: '{{metadata.labels.environment}}'
      source:
        repoURL: https://github.com/argoproj-labs/applicationset.git
        targetRevision: HEAD
        path: '{{path}}'
      destination:
        server: '{{server}}'
        namespace: '{{path.basename}}'
rshiva777 commented 2 years ago

To make it more clear, please find the below structure

i have the below directory structure

test-applicationset.yaml
cluster-configs
  -- clusterA.yaml
  -- clusterB.yaml

content of clusterA.yaml
cluster:
  name: 'dev-clusterA'
  address: 'https://api.devclusterA:6443'

content of clusterB.yaml
cluster:
  name: 'dev-clusterB'
  address: 'https://api.devclusterB:6443'

test-applicationset.yaml

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: test-appset
  namespace: test
spec:
  generators:
    - matrix:
        generators:
         - clusters:
             selector:
               matchLabels:
                 app: test
         - git:
             repoURL: https://github.com/testrepo
             revision: main
             files:
             - path: 'cluster-configs/*.yaml'
  template:
    metadata:
      name: '{{cluster.name}}-test'
    spec:
      project: default
      source:
        chart: test
        helm:
          valueFiles:
          - values.yaml
        repoURL: https://harbourrepo
        targetRevision: 0.1.1
      destination:
        server: '{{cluster.address}}'
        namespace: testnew

Now i have to deploy the application on to the cluster which have "app: test" label in the argocd secret of cluster, even though both configs are present in the cluster-configs/*.yaml path

As per my testing, i added the label "app: test" on clusterA, and deployed the applicationset, but seems to be that test application is deployed on both clusterA and clusterB which is not expected.

rishabh625 commented 2 years ago

Since you have added matchLabels app: test in cluster genrator nested inside matrix generator

Your applications will be deployed on cluster which has app: test label

Since in argocd cluster is stored as secret , secret matching label app:test will be selected for deployment by applicationset

rshiva777 commented 2 years ago

Yes, but the application is deployed on the clusterB as well, where the label "app: test" is not added in the argocd secret. This is not the expected case, application should deploy to cluster only which has label "app: test"

leotomas837 commented 1 year ago

Any news on this ? @rishabh625 you matrix solution does not work, explanation below.

The typical directory structure for this issue is: one config file per cluster and one directory including all (root) charts per cluster too, with argocd apps always targeting HEAD (and avoid the ugliness and headaches of using git branches with argocd). In that case, let's say I want to deploy a new chart in clusterA (for example dev env cluster). Once a first release has been successfully coded for chart, I want to deploy chart to clusterB (for ex prod). I would like to be able to create the ApplicationSet from the beginning, but an issue appears when I want to deploy the chart in dev only:

1] With git generators only, I woud not be using the final ApplicationSet as I would have to change the path selector to only match the configurations I want to select (the dev one). Instead I can also create multiple Applications until all my envs are ready for chart to be deployed to them, but this is not convenient.

2] With your matrix suggestion and the directory structure, it is possible to filter the cluster we want the app to be deployed to, good point, but a matrix is generated: I would not have one application per environment/cluster, but numberOfConfigFiles Applications deployed for each cluster targeted by the cluster generator. Amongst these 'additional' Applications, one example would be chart deployed on staging cluster with dev config...

Now that the case is described, you see that this is a very common case, and this is the case of @rshiva777 as he inputted in his original post:

spec:
  generators:
  - git:
      ...
      files:
      - path: "applicationsets/git-generator/cluster-config/**/config.yaml"  <--- a config file per cluster
  template:
  ...
      source:
        ...
        path: applicationsets/git-generator/overlays/{{cluster.overlay}}   <--- a chart directory per cluster

Finally, the original suggestion of @rishabh625 would fix the issue: no matrix generated, and we would be able to filter the clusters we want an app to be deployed (not all envs, only dev for example if divided by envs).

leotomas837 commented 1 year ago

After checking, the merge generator is the solution to this problem. Simply set the cluster generator as parent, and the git generator as (only) child, merging on server for example and make sure that each secrets and configs pair matches on server field.

The issue can be closed.

mimartin12 commented 1 year ago

@leotomas837 , would you mind sharing an example of your working manifest using merge:?