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>
This commit is contained in:
Brian Goff 2020-09-18 22:40:45 +00:00
parent 2513da195e
commit dedf8528a5
2 changed files with 74 additions and 10 deletions

View File

@ -7,7 +7,9 @@ ARG GO_VERSION=1.13.15
ARG DEBIAN_FRONTEND=noninteractive
ARG VPNKIT_VERSION=0.4.0
ARG DOCKER_BUILDTAGS="apparmor seccomp selinux"
ARG GOLANG_IMAGE="golang:${GO_VERSION}-buster"
ARG BASE_DEBIAN_DISTRO="buster"
ARG GOLANG_IMAGE="golang:${GO_VERSION}-${BASE_DEBIAN_DISTRO}"
FROM ${GOLANG_IMAGE} AS base
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 \
&& git checkout -q "$GO_SWAGGER_COMMIT" \
&& go build -o /build/swagger github.com/go-swagger/go-swagger/cmd/swagger
FROM base AS frozen-images
FROM debian:${BASE_DEBIAN_DISTRO} AS frozen-images
ARG DEBIAN_FRONTEND
RUN --mount=type=cache,sharing=locked,id=moby-frozen-images-aptlib,target=/var/lib/apt \
--mount=type=cache,sharing=locked,id=moby-frozen-images-aptcache,target=/var/cache/apt \
apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
curl \
jq
# Get useful and necessary Hub images so we can "docker load" locally instead of pulling
COPY contrib/download-frozen-image-v2.sh /

View File

@ -8,7 +8,7 @@ set -eo pipefail
# debian latest f6fab3b798be3174f45aa1eb731f8182705555f89c9026d8c1ef230cbf8301dd 10 weeks ago 85.1 MB
# check if essential commands are in our PATH
for cmd in curl jq go; do
for cmd in curl jq; do
if ! command -v $cmd &> /dev/null; then
echo >&2 "error: \"$cmd\" not found!"
exit 1
@ -36,13 +36,11 @@ manifestJsonEntries=()
doNotGenerateManifestJson=
# repositories[busybox]='"latest": "...", "ubuntu-14.04": "..."'
# bash v4 on Windows CI requires CRLF separator
# bash v4 on Windows CI requires CRLF separator... and linux doesn't seem to care either way
newlineIFS=$'\n'
if [ "$(go env GOHOSTOS)" = 'windows' ]; then
major=$(echo "${BASH_VERSION%%[^0.9]}" | cut -d. -f1)
if [ "$major" -ge 4 ]; then
newlineIFS=$'\r\n'
fi
major=$(echo "${BASH_VERSION%%[^0.9]}" | cut -d. -f1)
if [ "$major" -ge 4 ]; then
newlineIFS=$'\r\n'
fi
registryBase='https://registry-1.docker.io'
@ -201,6 +199,68 @@ handle_single_manifest_v2() {
manifestJsonEntries=("${manifestJsonEntries[@]}" "$manifestJsonEntry")
}
get_target_arch() {
if [ -n "${TARGETARCH:-}" ]; then
echo "${TARGETARCH}"
return 0
fi
if type go > /dev/null; then
go env GOARCH
return 0
fi
if type dpkg > /dev/null; then
debArch="$(dpkg --print-architecture)"
case "${debArch}" in
armel | armhf)
echo "arm"
return 0
;;
*64el)
echo "${debArch%el}le"
return 0
;;
*)
echo "${debArch}"
return 0
;;
esac
fi
if type uname > /dev/null; then
uArch="$(uname -m)"
case "${uArch}" in
x86_64)
echo amd64
return 0
;;
arm | armv[0-9]*)
echo arm
return 0
;;
aarch64)
echo arm64
return 0
;;
mips*)
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."
echo >&2 "Consider installing \"go\" on the system which I can use to determine the correct arch or specify it explictly by setting TARGETARCH"
exit 1
;;
*)
echo "${uArch}"
return 0
;;
esac
fi
# default value
echo >&2 "Unable to determine CPU arch, falling back to amd64. You can specify a target arch by setting TARGETARCH"
echo amd64
}
while [ $# -gt 0 ]; do
imageTag="$1"
shift
@ -250,11 +310,12 @@ while [ $# -gt 0 ]; do
unset IFS
found=""
targetArch="$(get_target_arch)"
# parse first level multi-arch manifest
for i in "${!layers[@]}"; do
layerMeta="${layers[$i]}"
maniArch="$(echo "$layerMeta" | jq --raw-output '.platform.architecture')"
if [ "$maniArch" = "$(go env GOARCH)" ]; then
if [ "$maniArch" = "${targetArch}" ]; then
digest="$(echo "$layerMeta" | jq --raw-output '.digest')"
# get second level single manifest
submanifestJson="$(