Skip to content

Instantly share code, notes, and snippets.

@miminar
Last active September 29, 2017 11:46
Show Gist options
  • Save miminar/a20c4eb42f5543a84e2d679a039a40d2 to your computer and use it in GitHub Desktop.
Save miminar/a20c4eb42f5543a84e2d679a039a40d2 to your computer and use it in GitHub Desktop.
Print image layout in OpenShift namespace

About

The script attempts to collect what images are used in current (or given namespace) and what objects reference them.

Requisities

jq utility needs to be installed on machine running this command

Usage

Run this as cluster administrator or at least as a user with system:registry-viewer, run:

./image-layout.sh $NAMESPACE

Limitations

The script inspects just the current namespace. Any reference outside of the namespace won't be collected/shown.

TODOs

  • Process all the namespaces.
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'
NAMESPACE=`oc project -q`
if [[ "$#" -gt 0 ]]; then
NAMESPACE="$1"
fi
oc project "${NAMESPACE}"
function get_istags() {
tmpl=$'{{range $isindex, $is := .items}}'
tmpl+=$'{{range $tag, $value := $is.status.tags}}'
tmpl+=$'{{if and ($value.items) (not $value.conditions)}}'
tmpl+=$'{{range $index, $item := $value.items}}'
tmpl+=$'{{$is.metadata.namespace}}/{{$is.metadata.name}}'
tmpl+=$':{{$value.tag}}#{{$index}}#{{.image}}#{{.dockerImageReference}}\n{{end}}'
tmpl+=$'{{end}}{{end}}{{end}}'
oc get is --all-namespaces -o "go-template=${tmpl}"
}
tmpdir="$(mktemp -d)"
function cleanup() {
rm -rf "${tmpdir}"
}
trap cleanup EXIT
oc get --all-namespaces -o json rc >"${tmpdir}/rcs.json"
oc get --all-namespaces -o json pod >"${tmpdir}/pods.json"
oc get --all-namespaces -o json dc >"${tmpdir}/dcs.json"
oc get --all-namespaces -o json bc >"${tmpdir}/bcs.json"
function make_image_refs_jq_expr() {
local image="$1"
printf '%s' '.items | map(select(@json | contains('
printf '"%s"' "${image}"
printf '))) | '
printf '%s | ' 'map(@text "\(.metadata.namespace)/\(.metadata.name)(app=\(.metadata.labels.app),created=\(.metadata.creationTimestamp))")'
printf '%s\n' 'join("#")'
}
function count_arr_items() {
echo "$1" | tr '#' '\n' | grep -v '^\s*$' | wc -l ||:
}
function print_references() {
local podrefs="$1"
local dcrefs="$2"
local rcrefs="$3"
local bcrefs="$4"
local titles=( "pod" "dc" "rc" "bc" )
local index=0
for refs in "${podrefs:-}" "${dcrefs:-}" "${rcrefs:-}" "${bcrefs:-}"; do
echo "${refs}" | tr '#' '\n' | while read -r ref; do
if [[ "${ref}" =~ (.+),created=([^\)]*) ]]; then
printf " ref'd by %s %s\t-\t-\t%s\t-\t-\n" "${titles[$index]}" "${BASH_REMATCH[1]})" "${BASH_REMATCH[2]}" ||:
fi
done
index="$((${index} + 1))"
done
}
function sort_images() {
declare -A imagetags
declare -A imagecreated
declare -A imagerefs
declare -A imagesizes
declare -A refcounts
declare -A podrefs
declare -A dcrefs
declare -A rcrefs
declare -A bcrefs
while read -r -u 3 ist; do
IFS='#' read -r istag index image ref <<<"${ist}"
if [[ "${istag}" == "END_OF_INPUT" ]]; then
{
printf "ImageName\tRefCount\tSize\tCreated\tISTags\tDockerImageReference\n"
while read -u 4 -r line; do
img="$(echo "${line}" | cut -f 1)"
echo "${line}"
print_references "${podrefs[$img]:-}" "${dcrefs[$img]:-}" "${rcrefs[$img]:-}" "${bcrefs[$img]:-}"
done 4< <(for img in "${!imagetags[@]}"; do
tags="${imagetags[$img]##,}"
if ! [[ "${tags}" =~ (^|,)${NAMESPACE}/ ]]; then
continue
fi
size="${imagesizes[$img]}"
created="${imagecreated[$img]}"
refs="${imagerefs[$img]##,}"
refcount="${refcounts[$img]}"
printf '%s\t%s' "${img}" "${refcount}"
printf '\t%s\t%s\t%s\t%s\n' "${size}" "${created}" "${tags}" "${refs}"
done | sort -rnk 2)
} | column -t -s $'\t'
break
fi
tags="${imagetags[$image]:-}"
if ! echo "${tags:-}" | grep -qF ",${istag}"; then
imagetags[$image]="${tags},${istag}[${index}]"
refcounts[$image]="$((${refcounts[$image]:-0} + 1))"
fi
refs="${imagerefs[$image]:-}"
if [[ "${ref}" =~ ^([^@]+)(@[^@/]+|:[^/:]+)$ ]]; then
ref="${BASH_REMATCH[1]}"
fi
if ! echo "${refs:-}" | grep -qF ",${ref}"; then
imagerefs[$image]="${refs},${ref}"
fi
if [[ -z "${imagesizes[$image]:-}" ]]; then
IFS='%' read -r size created <<<"$(oc get image -o json "${image}" | \
jq -r '@text "\(.dockerImageMetadata.Size | tostring)%\(.dockerImageMetadata.Created)"')"
[[ "${size}" == 'null' ]] && size=0
imagesizes[$image]="${size}"
imagecreated[$image]="${created}"
refcount="${refcounts[$image]:-0}"
jq_expr="$(make_image_refs_jq_expr "${image}")"
podrefs[$image]="$(cat "${tmpdir}/pods.json" | jq -r "${jq_expr}")"
dcrefs[$image]="$(cat "${tmpdir}/dcs.json" | jq -r "${jq_expr}")"
rcrefs[$image]="$(cat "${tmpdir}/rcs.json" | jq -r "${jq_expr}")"
bcrefs[$image]="$(cat "${tmpdir}/bcs.json" | jq -r "${jq_expr}")"
for refs in "${podrefs[$image]}" "${dcrefs[$image]}" "${rcrefs[$image]}" "${bcrefs[$image]}"; do
cnt="$(count_arr_items "${refs}")"
refcount="$((${refcount} + ${cnt}))"
done
fi
done 3< <(cat <(get_istags) <(echo "END_OF_INPUT#-#-"))
}
sort_images
$ ./image-layout.sh test
Now using project "test" on server "https://192.168.122.93:8443".
ImageName RefCount Size Created ISTags DockerImageReference
sha256:3c2d3a69b56f5800aedc0f60ab96f671e8bd0d43047e9611ec0634cf29ea53d8 3 140756629 2017-09-19T08:47:23Z openshift/mysql:latest[0],openshift/mysql:5.7[0],test/mysql:latest[0] centos/mysql-57-centos7
ref'd by pod test/database-1-2w4sx(app=ruby-helloworld-sample) - - 2017-09-29T11:08:36Z - -
sha256:f248ca107455728a561bc260faecb08e9083ffde8cb39139122fdfd58738405a 2 208859508 2017-04-22T14:38:01Z pjoe/ose-deployer:latest[0],test/my-ose-deployer:2[0] 172.30.30.30:5000/pjoe/ose-deployer,172.30.30.30:5000/test/my-ose-deployer
sha256:344ca23118d05c9724791f44ce17eddc642a9ebe7fd6145d9ce181a3edcd4b4e 2 192982120 2017-09-20T17:34:22Z openshift/ruby:2.2[0],test/ruby-22-centos7:latest[0] centos/ruby-22-centos7
ref'd by pod test/ruby-sample-build-1-build(app=null) - - 2017-09-29T11:08:31Z - -
ref'd by bc test/ruby-sample-build(app=ruby-helloworld-sample) - - 2017-09-29T11:08:28Z - -
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment