Browse code

Allow download-frozen-images to work without `go`

Currently we use the `go` command to read GOARCH and use the value for
matching manifests.

This change allows:

1. Specifying the arch through `TARGETARCH`
2. Falling back to `dpkg` if `go` is not available
3. Falling back to `uname -m` if `dpkg` is not available
4. A default value (amd64) if none of these commands is available.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>

Brian Goff authored on 2020/09/19 07:40:45
Showing 2 changed files
... ...
@@ -7,7 +7,9 @@ ARG GO_VERSION=1.13.15
7 7
 ARG DEBIAN_FRONTEND=noninteractive
8 8
 ARG VPNKIT_VERSION=0.4.0
9 9
 ARG DOCKER_BUILDTAGS="apparmor seccomp selinux"
10
-ARG GOLANG_IMAGE="golang:${GO_VERSION}-buster"
10
+
11
+ARG BASE_DEBIAN_DISTRO="buster"
12
+ARG GOLANG_IMAGE="golang:${GO_VERSION}-${BASE_DEBIAN_DISTRO}"
11 13
 
12 14
 FROM ${GOLANG_IMAGE} AS base
13 15
 RUN echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
... ...
@@ -79,12 +81,13 @@ RUN --mount=type=cache,target=/root/.cache/go-build \
79 79
         && git checkout -q "$GO_SWAGGER_COMMIT" \
80 80
         && go build -o /build/swagger github.com/go-swagger/go-swagger/cmd/swagger
81 81
 
82
-FROM base AS frozen-images
82
+FROM debian:${BASE_DEBIAN_DISTRO} AS frozen-images
83 83
 ARG DEBIAN_FRONTEND
84 84
 RUN --mount=type=cache,sharing=locked,id=moby-frozen-images-aptlib,target=/var/lib/apt \
85 85
     --mount=type=cache,sharing=locked,id=moby-frozen-images-aptcache,target=/var/cache/apt \
86 86
        apt-get update && apt-get install -y --no-install-recommends \
87 87
            ca-certificates \
88
+           curl \
88 89
            jq
89 90
 # Get useful and necessary Hub images so we can "docker load" locally instead of pulling
90 91
 COPY contrib/download-frozen-image-v2.sh /
... ...
@@ -8,7 +8,7 @@ set -eo pipefail
8 8
 # debian                           latest              f6fab3b798be3174f45aa1eb731f8182705555f89c9026d8c1ef230cbf8301dd   10 weeks ago        85.1 MB
9 9
 
10 10
 # check if essential commands are in our PATH
11
-for cmd in curl jq go; do
11
+for cmd in curl jq; do
12 12
 	if ! command -v $cmd &> /dev/null; then
13 13
 		echo >&2 "error: \"$cmd\" not found!"
14 14
 		exit 1
... ...
@@ -36,13 +36,11 @@ manifestJsonEntries=()
36 36
 doNotGenerateManifestJson=
37 37
 # repositories[busybox]='"latest": "...", "ubuntu-14.04": "..."'
38 38
 
39
-# bash v4 on Windows CI requires CRLF separator
39
+# bash v4 on Windows CI requires CRLF separator... and linux doesn't seem to care either way
40 40
 newlineIFS=$'\n'
41
-if [ "$(go env GOHOSTOS)" = 'windows' ]; then
42
-	major=$(echo "${BASH_VERSION%%[^0.9]}" | cut -d. -f1)
43
-	if [ "$major" -ge 4 ]; then
44
-		newlineIFS=$'\r\n'
45
-	fi
41
+major=$(echo "${BASH_VERSION%%[^0.9]}" | cut -d. -f1)
42
+if [ "$major" -ge 4 ]; then
43
+	newlineIFS=$'\r\n'
46 44
 fi
47 45
 
48 46
 registryBase='https://registry-1.docker.io'
... ...
@@ -201,6 +199,68 @@ handle_single_manifest_v2() {
201 201
 	manifestJsonEntries=("${manifestJsonEntries[@]}" "$manifestJsonEntry")
202 202
 }
203 203
 
204
+get_target_arch() {
205
+	if [ -n "${TARGETARCH:-}" ]; then
206
+		echo "${TARGETARCH}"
207
+		return 0
208
+	fi
209
+
210
+	if type go > /dev/null; then
211
+		go env GOARCH
212
+		return 0
213
+	fi
214
+
215
+	if type dpkg > /dev/null; then
216
+		debArch="$(dpkg --print-architecture)"
217
+		case "${debArch}" in
218
+			armel | armhf)
219
+				echo "arm"
220
+				return 0
221
+				;;
222
+			*64el)
223
+				echo "${debArch%el}le"
224
+				return 0
225
+				;;
226
+			*)
227
+				echo "${debArch}"
228
+				return 0
229
+				;;
230
+		esac
231
+	fi
232
+
233
+	if type uname > /dev/null; then
234
+		uArch="$(uname -m)"
235
+		case "${uArch}" in
236
+			x86_64)
237
+				echo amd64
238
+				return 0
239
+				;;
240
+			arm | armv[0-9]*)
241
+				echo arm
242
+				return 0
243
+				;;
244
+			aarch64)
245
+				echo arm64
246
+				return 0
247
+				;;
248
+			mips*)
249
+				echo >&2 "I see you are running on mips but I don't know how to determine endianness yet, so I cannot select a correct arch to fetch."
250
+				echo >&2 "Consider installing \"go\" on the system which I can use to determine the correct arch or specify it explictly by setting TARGETARCH"
251
+				exit 1
252
+				;;
253
+			*)
254
+				echo "${uArch}"
255
+				return 0
256
+				;;
257
+		esac
258
+
259
+	fi
260
+
261
+	# default value
262
+	echo >&2 "Unable to determine CPU arch, falling back to amd64. You can specify a target arch by setting TARGETARCH"
263
+	echo amd64
264
+}
265
+
204 266
 while [ $# -gt 0 ]; do
205 267
 	imageTag="$1"
206 268
 	shift
... ...
@@ -250,11 +310,12 @@ while [ $# -gt 0 ]; do
250 250
 					unset IFS
251 251
 
252 252
 					found=""
253
+					targetArch="$(get_target_arch)"
253 254
 					# parse first level multi-arch manifest
254 255
 					for i in "${!layers[@]}"; do
255 256
 						layerMeta="${layers[$i]}"
256 257
 						maniArch="$(echo "$layerMeta" | jq --raw-output '.platform.architecture')"
257
-						if [ "$maniArch" = "$(go env GOARCH)" ]; then
258
+						if [ "$maniArch" = "${targetArch}" ]; then
258 259
 							digest="$(echo "$layerMeta" | jq --raw-output '.digest')"
259 260
 							# get second level single manifest
260 261
 							submanifestJson="$(