Search code examples
kuberneteskubernetes-helm

How to get a list of docker images given some kubernetes template?


To simplify, I want to list all the docker images defined in a helm chart.

For eg, let's say I have the following set of templates:

$ helm template jenkins/jenkins

https://charts.jenkins.io/

Then, I want to somehow use kubectl to parse this result so I can apply a filter such as:

kubectl get pods -l k8s-app=kube-dns -o jsonpath={.items[*].spec.containers[*].name}

To return me the list. However, that command is to get pods. Any clue?

EDIT: I found a way:

❯ helm template jenkins/jenkins | kubectl apply -f - --dry-run=client -o jsonpath="{..image}" | tr -s '[[:space:]]' '\n' | sort | uniq
bats/bats:1.2.1
jenkins/jenkins:2.263.1
kiwigrid/k8s-sidecar:0.1.275

With one drawback: kubectl needs to be connected to a cluster. I would like to prevent that.


Solution

  • You can use a different jsonpath to get all images:

    kubectl get pods -A -o jsonpath="{..image}"

    If you just want unique images: kubectl get pods -A -o jsonpath="{..image}" | tr -s '[[:space:]]' '\n' | sort -u.

    Substituting -A for the namespace of your chart or manifests.

    If you have the manifests on your machine and not deployed, of course, you can just grep: grep 'image: ' *.yml

    You can also use Go template syntax:

    kubectl get pods -A -o go-template --template="{{range .items}}{{range .spec.containers}}{{.image}} {{end}}{{end}}"

    If you have more than one chart in a given namespace, I think grepping would be the best way: helm template some-chart | grep 'image:'

    EDIT:

    Since this will be running in CI, it would be better to use a little bit of code to avoid potential false positives. This Python script does the trick:

    #!/usr/bin/env python3
    import sys
    import yaml  # pip install PyYAML
    from nested_lookup import nested_lookup  # pip install nested-lookup
    
    template = ""
    
    for line in sys.stdin:
        template += line
    
    parts = template.split('---')
    for p in parts:
        y = yaml.safe_load(p)
        matches = nested_lookup("image", y)
        if (len(matches)):
            print("\n".join(matches))
    

    Usage: helm template jenkins/jenkins | ./this-script.py. It prints out each occurrence of images, so if you only want unique images you'd need to throw all the matches in a list, then unique that before printing (or pipe it to sort -u).