Instantly share code, notes, and snippets.
Last active
September 2, 2023 13:12
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
Save augustohp/97916c2a103a0827bfc2430142a4608d to your computer and use it in GitHub Desktop.
Lists tags for a Docker image
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env sh | |
# | |
# Helps listing remote tags for a given repository, going through all available | |
# pages using Docker Hub API. | |
# | |
# TODO Support official images | |
# TODO Output formating (date, humanize image size) | |
# TODO Allow different columns to be specified as output | |
# TODO Support other registries (with the same API, just different host) | |
# | |
# shellcheck disable=SC3043 | |
APP_NAME=$(basename "$0") | |
APP_VERSION="1.1.0" | |
APP_AUTHOR="[email protected]" | |
APP_DEPENDENCIES="curl jq grep sed" | |
set -e # Stop on failure | |
OPTION_PAGE="" | |
OPTION_PAGE_LIMIT="" | |
OPTION_TAG_PATTERN="" | |
assert_env() | |
{ | |
for dep in $APP_DEPENDENCIES | |
do | |
if [ -n "$(command -v "$dep")" ] | |
then | |
continue | |
fi | |
echo "Error: Missing '$dep'" >&2 | |
exit 2 | |
done | |
} | |
# ----------------------------------------------------------------------------- | |
# Helpers | |
join_3_consecutive_lines() | |
{ | |
sed 'N;N;s/\n/|/g' | |
} | |
remove_double_quotes() | |
{ | |
sed 's/"//g' | |
} | |
# ----------------------------------------------------------------------------- | |
# Context | |
# Usage: count_tags <repository> | |
count_tags() | |
{ | |
local repository="$1" | |
curl -s "https://hub.docker.com/v2/repositories/${repository}/tags?page_size=${page_size}&page=${page}" \ | |
| jq '.count' | |
} | |
# Usage: list_tags_single_page <repository> <page> | |
list_tags_single_page() | |
{ | |
local repository="$1" | |
local page="$2" | |
curl -s "https://hub.docker.com/v2/repositories/${repository}/tags?page_size=${page_size}&page=${page}" \ | |
| jq -c '.results | .[] | .name,.last_updated,.full_size' \ | |
| join_3_consecutive_lines \ | |
| remove_double_quotes | |
} | |
# Usage: list_tags_all_pages <repository> [page_limit] | |
list_tags_all_pages () | |
{ | |
local repository="$1" | |
local page_limit="${2:-}" | |
local page_size=100 | |
local total_tags=1 | |
local pages=1 | |
local page=1 | |
total_tags="$(count_tags "$1")" | |
pages=$((total_tags/page_size)) | |
if [ "$pages" -gt "$page_limit" ] | |
then | |
pages=$page_limit | |
fi | |
while [ "$page" -le "$pages" ] | |
do | |
list_tags_single_page "$repository" "$page" | |
page=$((page+1)) | |
done | |
} | |
# ----------------------------------------------------------------------------- | |
# Program | |
# Usage: display_help | |
display_help() | |
{ | |
cat <<-EOT | |
Usage: $APP_NAME [options] <image name> | |
$APP_NAME --help | |
$APP_NAME --page 2 --tag-pattern "^2023" jupyter/scipy-notebook | |
Displays tags for a Docker Image in a remote Docker Repository. Output is | |
formatted in a table for ease reading and manipulating on CLI. | |
Options: | |
-h, --help Prints this message. | |
-v, --version Prints version. | |
-x, --debug Displays debug (-x) information. | |
-p, --page <number> Single page to fetch from remote repository. | |
-l, --pages <limit> How many pages to fetch from remote repository. | |
Defaults to all of them. | |
-t, --tag-pattern <regex> Pattern passed to "grep" to filter lines. | |
Bugs and/or suggestions to $APP_AUTHOR. | |
EOT | |
} | |
# Usage: main "$@" | |
main() | |
{ | |
local repository="" | |
while :; do | |
case "${1:-}" in | |
# Parsing options --------------- | |
-h|--help) | |
display_help | |
exit 0 | |
;; | |
-v|--version) | |
echo "$APP_VERSION" | |
exit 0 | |
;; | |
-x|--debug) | |
set -x | |
;; | |
-p|--page) | |
OPTION_PAGE="$2" | |
shift | |
;; | |
-l|--pages|--page-limit) | |
OPTION_PAGE_LIMIT="$2" | |
shift | |
;; | |
-t|--tag-pattern) | |
OPTION_TAG_PATTERN="$2" | |
shift | |
;; | |
# Treating mistakes ------------- | |
-?*) | |
echo "Error: Unknown '$1' option." >&2 | |
exit 3 | |
;; | |
*) | |
# Stops parsing options | |
break | |
;; | |
esac | |
shift | |
done | |
repository="$1" | |
if [ -n "$OPTION_PAGE" ] | |
then | |
list_tags_single_page "$repository" | |
exit 0 | |
fi | |
list_tags_all_pages "$repository" "$OPTION_PAGE_LIMIT" \ | |
| grep "${OPTION_TAG_PATTERN}" \ | |
| column --table --separator "|" --table-columns "Tag Name,Last Updated,Size" | |
return 0 | |
} | |
assert_env | |
main "$@" | |
# vim: set ft=sh ts=4 sw=4 tw=0 noet: |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment