Update "download-frozen-image-v2.sh" such that redirects are optional

If the registry responds directly with blob contents, use them,
otherwise follow the redirect without Authorization headers (which
likely aren't valid for the server being redirected to).

This preserves the basic structure of the previous output with up to one
additional progress bar per-layer (for the redirect request and then the
following blob request).

Signed-off-by: Tianon Gravi <admwiggin@gmail.com>
This commit is contained in:
Tianon Gravi 2017-06-20 10:56:13 -07:00 committed by Alexander Midlash
parent 5c38e4c16a
commit 4bbdc0b8f7
1 changed files with 41 additions and 17 deletions

View File

@ -44,16 +44,41 @@ if [ "$(go env GOHOSTOS)" = 'windows' ]; then
fi
fi
fetch_blob() {
url=$1
token=$2
dest=$3
echo "Attempting to download blob $url"
target=$(curl -sS -v -H "Authorization: Bearer $token" "$url" 2>&1 | grep "Location:" | sed 's/< Location: \(.*\)\r/\1/')
# curl blob (exclude auth token)
curl -fsS --progress "${target}" -o "$dest"
}
registryBase='https://registry-1.docker.io'
authBase='https://auth.docker.io'
authService='registry.docker.io'
# https://github.com/moby/moby/issues/33700
fetch_blob() {
local token="$1"; shift
local image="$1"; shift
local digest="$1"; shift
local targetFile="$1"; shift
local curlArgs=( "$@" )
local curlHeaders="$(
curl -S "${curlArgs[@]}" \
-H "Authorization: Bearer $token" \
"$registryBase/v2/$image/blobs/$digest" \
-o "$targetFile" \
-D-
)"
curlHeaders="$(echo "$curlHeaders" | tr -d '\r')"
if [ "$(echo "$curlHeaders" | awk 'NR == 1 { print $2; exit }')" != '200' ]; then
rm -f "$targetFile"
local blobRedirect="$(echo "$curlHeaders" | awk -F ': ' 'tolower($1) == "location" { print $2; exit }')"
if [ -z "$blobRedirect" ]; then
echo >&2 "error: failed fetching '$image' blob '$digest'"
echo "$curlHeaders" | head -1 >&2
return 1
fi
curl -fSL "${curlArgs[@]}" \
"$blobRedirect" \
-o "$targetFile"
fi
}
while [ $# -gt 0 ]; do
imageTag="$1"
@ -70,14 +95,14 @@ while [ $# -gt 0 ]; do
imageFile="${image//\//_}" # "/" can't be in filenames :)
token="$(curl -fsSL "https://auth.docker.io/token?service=registry.docker.io&scope=repository:$image:pull" | jq --raw-output '.token')"
token="$(curl -fsSL "$authBase/token?service=$authService&scope=repository:$image:pull" | jq --raw-output '.token')"
manifestJson="$(
curl -fsSL \
-H "Authorization: Bearer $token" \
-H 'Accept: application/vnd.docker.distribution.manifest.v2+json' \
-H 'Accept: application/vnd.docker.distribution.manifest.v1+json' \
"https://registry-1.docker.io/v2/$image/manifests/$digest"
"$registryBase/v2/$image/manifests/$digest"
)"
if [ "${manifestJson:0:1}" != '{' ]; then
echo >&2 "error: /v2/$image/manifests/$digest returned something unexpected:"
@ -98,7 +123,7 @@ while [ $# -gt 0 ]; do
imageId="${configDigest#*:}" # strip off "sha256:"
configFile="$imageId.json"
fetch_blob "https://registry-1.docker.io/v2/$image/blobs/$configDigest" $token "$dir/$configFile"
fetch_blob "$token" "$image" "$configDigest" "$dir/$configFile" -s
layersFs="$(echo "$manifestJson" | jq --raw-output --compact-output '.layers[]')"
IFS="$newlineIFS"
@ -165,8 +190,8 @@ while [ $# -gt 0 ]; do
echo "skipping existing ${layerId:0:12}"
continue
fi
token="$(curl -fsSL "https://auth.docker.io/token?service=registry.docker.io&scope=repository:$image:pull" | jq --raw-output '.token')"
fetch_blob "https://registry-1.docker.io/v2/$image/blobs/$layerDigest" $token "$dir/$layerTar"
token="$(curl -fsSL "$authBase/token?service=$authService&scope=repository:$image:pull" | jq --raw-output '.token')"
fetch_blob "$token" "$image" "$layerDigest" "$dir/$layerTar" --progress
;;
*)
@ -235,9 +260,8 @@ while [ $# -gt 0 ]; do
echo "skipping existing ${layerId:0:12}"
continue
fi
token="$(curl -fsSL "https://auth.docker.io/token?service=registry.docker.io&scope=repository:$image:pull" | jq --raw-output '.token')"
# find redirect using token:
fetch_blob "https://registry-1.docker.io/v2/$image/blobs/$imageLayer" $token "$dir/$layerId/layer.tar"
token="$(curl -fsSL "$authBase/token?service=$authService&scope=repository:$image:pull" | jq --raw-output '.token')"
fetch_blob "$token" "$image" "$imageLayer" "$dir/$layerId/layer.tar" --progress
done
;;