Sfoglia il codice sorgente

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>
Tianon Gravi 8 anni fa
parent
commit
4bbdc0b8f7
1 ha cambiato i file con 40 aggiunte e 16 eliminazioni
  1. 40 16
      contrib/download-frozen-image-v2.sh

+ 40 - 16
contrib/download-frozen-image-v2.sh

@@ -44,17 +44,42 @@ if [ "$(go env GOHOSTOS)" = 'windows' ]; then
 	fi
 	fi
 fi
 fi
 
 
+registryBase='https://registry-1.docker.io'
+authBase='https://auth.docker.io'
+authService='registry.docker.io'
+
+# https://github.com/moby/moby/issues/33700
 fetch_blob() {
 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"
+	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
 while [ $# -gt 0 ]; do
 	imageTag="$1"
 	imageTag="$1"
 	shift
 	shift
@@ -70,14 +95,14 @@ while [ $# -gt 0 ]; do
 
 
 	imageFile="${image//\//_}" # "/" can't be in filenames :)
 	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="$(
 	manifestJson="$(
 		curl -fsSL \
 		curl -fsSL \
 			-H "Authorization: Bearer $token" \
 			-H "Authorization: Bearer $token" \
 			-H 'Accept: application/vnd.docker.distribution.manifest.v2+json' \
 			-H 'Accept: application/vnd.docker.distribution.manifest.v2+json' \
 			-H 'Accept: application/vnd.docker.distribution.manifest.v1+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
 	if [ "${manifestJson:0:1}" != '{' ]; then
 		echo >&2 "error: /v2/$image/manifests/$digest returned something unexpected:"
 		echo >&2 "error: /v2/$image/manifests/$digest returned something unexpected:"
@@ -98,7 +123,7 @@ while [ $# -gt 0 ]; do
 					imageId="${configDigest#*:}" # strip off "sha256:"
 					imageId="${configDigest#*:}" # strip off "sha256:"
 
 
 					configFile="$imageId.json"
 					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[]')"
 					layersFs="$(echo "$manifestJson" | jq --raw-output --compact-output '.layers[]')"
 					IFS="$newlineIFS"
 					IFS="$newlineIFS"
@@ -165,8 +190,8 @@ while [ $# -gt 0 ]; do
 									echo "skipping existing ${layerId:0:12}"
 									echo "skipping existing ${layerId:0:12}"
 									continue
 									continue
 								fi
 								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}"
 					echo "skipping existing ${layerId:0:12}"
 					continue
 					continue
 				fi
 				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
 			done
 			;;
 			;;