Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show full app-of-apps/ApplicationSet tree in UI #21325

Open
Hobbit44 opened this issue Dec 29, 2024 · 1 comment
Open

Show full app-of-apps/ApplicationSet tree in UI #21325

Hobbit44 opened this issue Dec 29, 2024 · 1 comment
Labels
app-of-apps Issues about the app-of-apps pattern enhancement New feature or request

Comments

@Hobbit44
Copy link

Summary

I would like to see a full tree of my repo when looking at the top level app. I have a repo structure like the below:

services
├─ ci
│   └─ argocd.yaml
├─ data
│   ├─ postgres.yaml
│   └─ redis.yaml   
├─ monitoring
│   └─ prometheus.yaml
└─ system
     └─ metallb.yaml

I have each of the services in a namespace that corresponds with the namespace (e.g. redis and postgres are in data ns (i know its not best practice but its only a home cluster)). Each of the yaml files are argocd Apps as they are all helm charts and as i have pretty simple values setups I'm happy to store all the details in the applications files.

My ideal would be to see a layout like the below under the services app, as it clearly shows the resources in my tree. I can then look at the apps to see the resources created by the charts.

Screenshot 2024-12-29 140037

I have tried various different things to try and attain that kind of view:

ApplicationSet

    UI Tree

    image
    image

    services.yaml

    apiVersion: argoproj.io/v1alpha1
    kind: Application
    metadata:
      name: services
      namespace: ci
    spec:
      project: default
      source:
        repoURL: https://github.com/Hobbit44/services
        targetRevision: refs/heads/main
        path: '.'
        directory:
          include: 'appset.yaml'
      destination:
        name: home-k8s
        namespace: ci
      syncPolicy:
        automated: {}
    

    appset.yaml

    apiVersion: argoproj.io/v1alpha1
    kind: ApplicationSet
    metadata:
      name: appset
      namespace: ci
    spec:
      goTemplate: true
      goTemplateOptions: ["missingkey=error"]
      generators:
      - git:
          repoURL: https://github.com/Hobbit44/services
          revision: refs/heads/main
          directories:
          - path: '*'
      template:
        metadata:
          name: '{{ .path.basenameNormalized }}'
          namespace: ci
        spec:
          project: default
          source:
            repoURL: https://github.com/Hobbit44/services
            targetRevision: refs/heads/main
            path: '{{ .path.path }}'
          destination:
            name: home-k8s
            namespace: '{{ .path.basenameNormalized }}'
          syncPolicy:
            automated: {}
            syncOptions:
            - CreateNamespace=true
    

App of Apps

    UI Tree

    image

    services.yaml

    apiVersion: argoproj.io/v1alpha1
    kind: Application
    metadata:
      name: services
      namespace: ci
    spec:
      project: default
      source:
        repoURL: https://github.com/Hobbit44/services
        targetRevision: refs/heads/main
        path: '.'
        directory:
          recurse: true
          include: '**/*.yaml'
      destination:
        name: home-k8s
        namespace: ci
      syncPolicy:
        automated: {}
    

Config Management Plugin

    UI Tree

    image

    ArgoCD Helm Values

    configs:
      cm: 
        application.resourceTrackingMethod: annotation+label
      cmp:
        create: true
        plugins:
          ns-plugin:
            sync-hook: |
              apiVersion: batch/v1
              kind: Job
              metadata:
                name: ns-plugin-sync
                annotations:
                  argocd.argoproj.io/hook: PostSync
                  argocd.argoproj.io/hook-delete-policy: HookSucceeded
              spec:
                template:
                  spec:
                    serviceAccountName: argocd-application-controller
                    containers:
                    - name: hook
                      image: bitnami/kubectl:latest
                      command: [bash, -c]
                      args:
                      - |-
                        while read -r name; do 
                          namespace=$(kubectl get apps -n ci $name -o yaml | yq '.spec.destination.namespace')
                          if [[ ! -e /tmp/${namespace}.yaml ]]; then
                            kubectl get ns $namespace -o yaml | yq '{"metadata": {"ownerReferences": [{"apiVersion": .apiVersion, "kind": .kind, "name": .metadata.name, "uid": .metadata.uid}]}}' > /tmp/${namespace}.yaml
                          fi
                          kubectl patch app -n ci $name --type=merge --patch-file=/tmp/${namespace}.yaml
                        done <<< $(kubectl get apps -n ci services -o yaml | yq '.status.resources[] | select(.kind == "Application").name')
                      volumeMounts:
                      - mountPath: /tmp
                        name: tmp
                    volumes:
                    - name: tmp
                      emptyDir: {}
                    restartPolicy: Never
                backoffLimit: 2
            init:
              command: [bash, -c]
              args:
              - |-
                set -o pipefail
                mkdir .generated
                while read -r namespace; do 
                  export namespace
                  [[ "$namespace" == "null" ]] && continue
                  [[ -z "$namespace" ]] && continue
                  kubectl create ns --dry-run=client $namespace -o yaml > .generated/${namespace}.yaml
                  yq -i '.metadata.labels["app.kubernetes.io/instance"] |= env(ARGOCD_APP_NAME)' .generated/${namespace}.yaml
                  yq -i '.metadata.annotations["argocd.argoproj.io/tracking-id"] |= env(ARGOCD_APP_NAME)+":/Namespace:"+env(namespace)+"/"+env(namespace)' .generated/${namespace}.yaml
                done <<< $(find . -mindepth 2 -maxdepth 2 -type f -name "*.yaml" -exec yq '.spec.destination.namespace' {} ';' | sort | uniq)
                yq '.spec.sync-hook' /home/argocd/cmp-server/config/plugin.yaml > .generated/sync-hook.yaml
            generate:
              command: [bash, -c]
              args:
              - find . -mindepth 2 -maxdepth 2 -type f -name "*.yaml" | xargs yq eval-all
    repoServer:
      plugin:
        tar:
          exclusions: ".git/*"
      extraContainers:
      - name: ns-plugin
        command: [/var/run/argocd/argocd-cmp-server]
        args: [--loglevel, debug]
        image: bitnami/kubectl
        securityContext:
          runAsNonRoot: true
          runAsUser: 999
        volumeMounts:
          - mountPath: /var/run/argocd
            name: var-files
          - mountPath: /home/argocd/cmp-server/plugins
            name: plugins
          - mountPath: /home/argocd/cmp-server/config/plugin.yaml
            subPath: plugin.yaml
            name: argocd-cmp-cm
      volumes:
        - name: argocd-cmp-cm
          configMap:
            name: argocd-cmp-cm
            items:
              - key: "ns-plugin.yaml"
                path: "plugin.yaml"

    services.yaml

    apiVersion: argoproj.io/v1alpha1
    kind: Application
    metadata:
      name: services
      namespace: ci
    spec:
      project: default
      source:
        repoURL: https://github.com/Hobbit44/services
        targetRevision: refs/heads/main
        path: '.'
        plugin:
          name: ns-plugin
      destination:
        name: home-k8s
        namespace: ci
      syncPolicy:
        automated: {}

Proposal

My thinking is that if an application only contains other applications, the tree could extend to show the child apps.

I think there a few related issues that are related that i think could contribute to this end.

#11196 Would add visibility of the NSs to the UI but might not nessesarily add the dependency element.
#7437 Could add the ability to set exlicit dependencies via a dependsOn key.

@Hobbit44 Hobbit44 added the enhancement New feature or request label Dec 29, 2024
@andrii-korotkov-verkada andrii-korotkov-verkada added the app-of-apps Issues about the app-of-apps pattern label Jan 1, 2025
@andrii-korotkov-verkada
Copy link
Contributor

I think this would not work in a general case, as the number of child resources would explode quickly with the growing number of apps and UI would have a hard time rendering those.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
app-of-apps Issues about the app-of-apps pattern enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants