this repo has no description
1#!/usr/bin/env bash
2
3#
4# script to parse out any images from Kubernetes manifests,
5# helm values, flux helm releases, or docker compose files.
6# returns a object with an array of containers from the parsed file
7#
8
9set -o errexit
10set -o nounset
11set -o pipefail
12
13show_help() {
14cat << EOF
15Usage: $(basename "$0") <options>
16 -h, --help Display help
17 -f, --file File to scan for container images
18 --nothing Enable nothing mode
19EOF
20}
21
22main() {
23 local file=
24 local nothing=
25 parse_command_line "$@"
26 check "jo"
27 check "jq"
28 check "yq"
29 parse_files
30}
31
32parse_command_line() {
33 while :; do
34 case "${1:-}" in
35 -h|--help)
36 show_help
37 exit
38 ;;
39 -f|--file)
40 if [[ -n "${2:-}" ]]; then
41 file="$2"
42 shift
43 else
44 echo "ERROR: '-f|--file' cannot be empty." >&2
45 show_help
46 exit 1
47 fi
48 ;;
49 --nothing)
50 nothing=1
51 ;;
52 *)
53 break
54 ;;
55 esac
56 shift
57 done
58
59 if [[ -z "$file" ]]; then
60 echo "ERROR: '-f|--file' is required." >&2
61 show_help
62 exit 1
63 fi
64
65 if [[ -z "$nothing" ]]; then
66 nothing=0
67 fi
68}
69
70check() {
71 command -v "${1}" >/dev/null 2>&1 || {
72 echo >&2 "ERROR: ${1} is not installed or not found in \$PATH" >&2
73 exit 1
74 }
75}
76
77parse_files() {
78 # create new array to hold the images
79 images=()
80
81 # look in hydrated flux helm releases
82 chart_registry_url=$(sed -nr 's|.*registryUrl=(.+)$|\1|p' "${file}")
83 chart_name=$(yq eval .spec.chart.spec.chart "${file}" 2>/dev/null)
84 if [[ -n ${chart_registry_url} && -n "${chart_name}" ]]; then
85 chart_version=$(yq eval .spec.chart.spec.version "${file}" 2>/dev/null)
86 chart_values=$(yq eval .spec.values "${file}" 2>/dev/null)
87 pushd "$(mktemp -d)" > /dev/null 2>&1
88 helm repo add ci "${chart_registry_url}" > /dev/null 2>&1
89 helm pull "ci/${chart_name}" --untar --version "${chart_version}"
90 resources=$(echo "${chart_values}" | helm template "${chart_name}" "${chart_name}" --version "${chart_version}" -f -)
91 popd > /dev/null 2>&1
92 images+=("$(echo "${resources}" | yq eval-all '.spec.template.spec.containers.[].image' -)")
93 fi
94
95 # look in helm values
96 images+=("$(yq eval-all '[.. | select(has("repository")) | select(has("tag"))] | .[] | .repository + ":" + .tag' "${file}" 2>/dev/null)")
97
98 # look in kubernetes deployments, statefulsets and daemonsets
99 images+=("$(yq eval-all '.spec.template.spec.containers.[].image' "${file}" 2>/dev/null)")
100
101 # look in kubernetes pods
102 images+=("$(yq eval-all '.spec.containers.[].image' "${file}" 2>/dev/null)")
103
104 # look in kubernetes cronjobs
105 images+=("$(yq eval-all '.spec.jobTemplate.spec.template.spec.containers.[].image' "${file}" 2>/dev/null)")
106
107 # look in docker compose
108 images+=("$(yq eval-all '.services.*.image' "${file}" 2>/dev/null)")
109
110 # remove duplicate values xD
111 IFS=" " read -r -a images <<< "$(tr ' ' '\n' <<< "${images[@]}" | sort -u | tr '\n' ' ')"
112
113 # create new array to hold the parsed images
114 parsed_images=()
115 # loop thru the images removing any invalid items
116 for i in "${images[@]}"; do
117 # loop thru each image and split on new lines (for when yq finds multiple containers in the same file)
118 for b in ${i//\\n/ }; do
119 if [[ -z "${b}" || "${b}" == "null" || "${b}" == "---" ]]; then
120 continue
121 fi
122 parsed_images+=("${b}")
123 done
124 done
125 # check if parsed_images array has items
126 if (( ${#parsed_images[@]} )); then
127 # convert the bash array to json and wrap array in an containers object
128 jo -a "${parsed_images[@]}" | jq -c '{containers: [(.[])]}'
129 fi
130}
131
132main "$@"