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 DEBIAN_FRONTEND=noninteractive
ARG VPNKIT_VERSION=0.4.0 ARG VPNKIT_VERSION=0.4.0
ARG DOCKER_BUILDTAGS="apparmor seccomp selinux" 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 FROM ${GOLANG_IMAGE} AS base
RUN echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache 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" \ && git checkout -q "$GO_SWAGGER_COMMIT" \
&& go build -o /build/swagger github.com/go-swagger/go-swagger/cmd/swagger && 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 ARG DEBIAN_FRONTEND
RUN --mount=type=cache,sharing=locked,id=moby-frozen-images-aptlib,target=/var/lib/apt \ 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 \ --mount=type=cache,sharing=locked,id=moby-frozen-images-aptcache,target=/var/cache/apt \
apt-get update && apt-get install -y --no-install-recommends \ apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \ ca-certificates \
curl \
jq jq
# Get useful and necessary Hub images so we can "docker load" locally instead of pulling # Get useful and necessary Hub images so we can "docker load" locally instead of pulling
COPY contrib/download-frozen-image-v2.sh / 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 # debian latest f6fab3b798be3174f45aa1eb731f8182705555f89c9026d8c1ef230cbf8301dd 10 weeks ago 85.1 MB
# check if essential commands are in our PATH # 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 if ! command -v $cmd &> /dev/null; then
echo >&2 "error: \"$cmd\" not found!" echo >&2 "error: \"$cmd\" not found!"
exit 1 exit 1
@ -36,13 +36,11 @@ manifestJsonEntries=()
doNotGenerateManifestJson= doNotGenerateManifestJson=
# repositories[busybox]='"latest": "...", "ubuntu-14.04": "..."' # 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' newlineIFS=$'\n'
if [ "$(go env GOHOSTOS)" = 'windows' ]; then major=$(echo "${BASH_VERSION%%[^0.9]}" | cut -d. -f1)
major=$(echo "${BASH_VERSION%%[^0.9]}" | cut -d. -f1) if [ "$major" -ge 4 ]; then
if [ "$major" -ge 4 ]; then newlineIFS=$'\r\n'
newlineIFS=$'\r\n'
fi
fi fi
registryBase='https://registry-1.docker.io' registryBase='https://registry-1.docker.io'
@ -201,6 +199,68 @@ handle_single_manifest_v2() {
manifestJsonEntries=("${manifestJsonEntries[@]}" "$manifestJsonEntry") 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 while [ $# -gt 0 ]; do
imageTag="$1" imageTag="$1"
shift shift
@ -250,11 +310,12 @@ while [ $# -gt 0 ]; do
unset IFS unset IFS
found="" found=""
targetArch="$(get_target_arch)"
# parse first level multi-arch manifest # parse first level multi-arch manifest
for i in "${!layers[@]}"; do for i in "${!layers[@]}"; do
layerMeta="${layers[$i]}" layerMeta="${layers[$i]}"
maniArch="$(echo "$layerMeta" | jq --raw-output '.platform.architecture')" 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')" digest="$(echo "$layerMeta" | jq --raw-output '.digest')"
# get second level single manifest # get second level single manifest
submanifestJson="$( submanifestJson="$(