Abstract cos-gpu-installer's cloudbuild into template This is part of the effort for other container images to use same template to upload multi-arch container images with tags. BUG=b/397500013 TEST=presubmit Change-Id: Ib28be9064b4e9c4f1d2ec21a27bee14f3835f7cd Reviewed-on: https://cos-review.googlesource.com/c/cos/tools/+/97402 Reviewed-by: Robert Kolchmeyer <rkolchmeyer@google.com> Cloud-Build: GCB Service account <228075978874@cloudbuild.gserviceaccount.com> Tested-by: Chenglong Tang <chenglongtang@google.com>
diff --git a/src/cmd/cos_gpu_installer/cloudbuild.yaml b/src/cmd/cos_gpu_installer/cloudbuild.yaml index 626db0a..7716ed6 100644 --- a/src/cmd/cos_gpu_installer/cloudbuild.yaml +++ b/src/cmd/cos_gpu_installer/cloudbuild.yaml
@@ -1,140 +1,30 @@ +substitutions: + _IMAGE_NAME: cos-gpu-installer + options: env: - 'DOCKER_CLI_EXPERIMENTAL=enabled' + steps: -# This step is needed to add a new entry to /proc/sys/fs/binfmt_misc. Docker -# uses QEMU user emulation to run arm64 programs on x86 hosts. A QEMU -# interpreter needs to be added to /proc/sys/fs/binfmt_misc to run arm64 -# programs. -- name: 'gcr.io/cloud-builders/docker' - args: ['run', '--privileged', 'linuxkit/binfmt:v1.0.0'] -# The default builder (which appears to be the Docker daemon that implements -# the old, familiar `docker build` behavior) doesn't support the --platform -# flag, so we need to create a new builder. -- name: 'gcr.io/cloud-builders/docker' - args: ['buildx', 'create', '--name', 'builder'] -- name: 'gcr.io/cloud-builders/docker' - args: ['buildx', 'use', 'builder'] -# Images produced in this way do not appear in the Docker image registry shown -# by `docker images`, at least by default. We use the --push flag to push the -# image after building it, because a subsequent `docker push` won't find the -# image locally. - name: 'gcr.io/cloud-builders/docker' id: 'build-and-upload-artifacts' entrypoint: 'bash' - args: - - '-c' - - | - if [ "$_BUILD_TYPE" == "presubmit" ]; then - # If it's presubmit, push to us-docker.pkg.dev/cos-infra-prod/gcr-io-dev with sbom, TAG_NAME and presubmit-TAG_NAME tags - docker buildx build --platform 'linux/amd64,linux/arm64' --build-arg 'BUILDKIT_INLINE_CACHE=1' -f 'src/cmd/cos_gpu_installer/Dockerfile' -t 'us-docker.pkg.dev/${_OUTPUT_PROJECT}/gcr-io-dev/cos-gpu-installer:${_TAG_NAME}' -t 'us-docker.pkg.dev/${_OUTPUT_PROJECT}/gcr-io-dev/cos-gpu-installer:${_BUILD_TYPE}-${_TAG_NAME}' -t 'us-docker.pkg.dev/${_OUTPUT_PROJECT}/gcr-io-dev/cos-gpu-installer:sbom' --cache-from 'us-docker.pkg.dev/${_OUTPUT_PROJECT}/gcr-io-dev/cos-gpu-installer:latest' --push '.' - docker pull us-docker.pkg.dev/${_OUTPUT_PROJECT}/gcr-io-dev/cos-gpu-installer:${_TAG_NAME} - elif [ "$_BUILD_TYPE" == "official" ]; then - # If it's official, push to us-docker.pkg.dev/cos-infra-prod/gcr-io-dev with sbom, TAG_NAME, official-TAG_NAME and latest tags - docker buildx build --platform 'linux/amd64,linux/arm64' --build-arg 'BUILDKIT_INLINE_CACHE=1' -f 'src/cmd/cos_gpu_installer/Dockerfile' -t 'us-docker.pkg.dev/${_OUTPUT_PROJECT}/gcr-io-dev/cos-gpu-installer:${_TAG_NAME}' -t 'us-docker.pkg.dev/${_OUTPUT_PROJECT}/gcr-io-dev/cos-gpu-installer:${_BUILD_TYPE}-${_TAG_NAME}' -t 'us-docker.pkg.dev/${_OUTPUT_PROJECT}/gcr-io-dev/cos-gpu-installer:latest' -t 'us-docker.pkg.dev/${_OUTPUT_PROJECT}/gcr-io-dev/cos-gpu-installer:sbom' --cache-from 'us-docker.pkg.dev/${_OUTPUT_PROJECT}/gcr-io-dev/cos-gpu-installer:latest' --push '.' - docker pull us-docker.pkg.dev/${_OUTPUT_PROJECT}/gcr-io-dev/cos-gpu-installer:${_TAG_NAME} - # If it's official, also push to gcr.io - docker buildx build --platform 'linux/amd64,linux/arm64' --build-arg 'BUILDKIT_INLINE_CACHE=1' -f 'src/cmd/cos_gpu_installer/Dockerfile' -t 'gcr.io/${_OUTPUT_PROJECT}/cos-gpu-installer:latest' -t 'gcr.io/${_OUTPUT_PROJECT}/cos-gpu-installer:${_TAG_NAME}' -t 'gcr.io/${_OUTPUT_PROJECT}/cos-gpu-installer:sbom' --cache-from 'gcr.io/${_OUTPUT_PROJECT}/cos-gpu-installer:latest' --push '.' - docker pull gcr.io/${_OUTPUT_PROJECT}/cos-gpu-installer:${_TAG_NAME} - else - echo "Invalid BUILD_TYPE: $_BUILD_TYPE" - exit 1 - fi - - # Get digests for both amd64 and arm64 images uploaded to gcr.io and save to files. - if [ "$_BUILD_TYPE" == "official" ]; then - echo $(docker buildx imagetools inspect gcr.io/${_OUTPUT_PROJECT}/cos-gpu-installer:${_TAG_NAME} | grep -i -B 3 'platform: *linux/amd64' | grep -o 'sha256:[a-f0-9]*' 2>/dev/null) > GCR_AMD64_DIGEST - echo $(docker buildx imagetools inspect gcr.io/${_OUTPUT_PROJECT}/cos-gpu-installer:${_TAG_NAME} | grep -i -B 3 'platform: *linux/arm64' | grep -o 'sha256:[a-f0-9]*' 2>/dev/null) > GCR_ARM64_DIGEST - - # Print if we can successfully get the digest. Make sure the digest file is non-empty. - if [ -n "$(cat GCR_AMD64_DIGEST)" ]; then - echo "Successfully extracted AMD64 digest for gcr.io: $(cat GCR_AMD64_DIGEST)" - else - echo "Failed to extract AMD64 digest" - exit 1 - fi - - if [ -n "$(cat GCR_ARM64_DIGEST)" ]; then - echo "Successfully extracted ARM64 digest for gcr.io: $(cat GCR_AMD64_DIGEST)" - else - echo "Failed to extract ARM64 digest" - exit 1 - fi - else - echo "Skip finding amd/arm digests of gcr.io as BUILD_TYPE is not official" - fi - - # Get digests for both amd64 and arm64 images uploaded to gcr-io-dev and save to files. - # This step will be conducted by both presubmit and official. - echo $(docker buildx imagetools inspect us-docker.pkg.dev/${_OUTPUT_PROJECT}/gcr-io-dev/cos-gpu-installer:${_TAG_NAME} | grep -i -B 3 'platform: *linux/amd64' | grep -o 'sha256:[a-f0-9]*' 2>/dev/null) > AMD64_DIGEST - echo $(docker buildx imagetools inspect us-docker.pkg.dev/${_OUTPUT_PROJECT}/gcr-io-dev/cos-gpu-installer:${_TAG_NAME} | grep -i -B 3 'platform: *linux/arm64' | grep -o 'sha256:[a-f0-9]*' 2>/dev/null) > ARM64_DIGEST - - # Print if we can successfully get the digest. Make sure the digest file is non-empty. - if [ -n "$(cat AMD64_DIGEST)" ]; then - echo "Successfully extracted AMD64 digest: $(cat AMD64_DIGEST)" - else - echo "Failed to extract AMD64 digest" - exit 1 - fi - - if [ -n "$(cat ARM64_DIGEST)" ]; then - echo "Successfully extracted ARM64 digest: $(cat ARM64_DIGEST)" - else - echo "Failed to extract ARM64 digest" - exit 1 - fi + env: + - 'TAG_NAME=${_TAG_NAME}' + - 'OUTPUT_PROJECT=${_OUTPUT_PROJECT}' + - 'BUILD_TYPE=${_BUILD_TYPE}' + - 'IMAGE_NAME=${_IMAGE_NAME}' + args: [ './src/scripts/docker_buildx_push_with_tags.sh'] - name: 'gcr.io/cloud-builders/gcloud' + id: 'tag-multi-arch-images' entrypoint: 'bash' wait_for: ['build-and-upload-artifacts'] - args: - - '-c' - - | - # Apply sbom_amd64 and sbom_arm64 to GCR_AMD64_DIGEST and GCR_ARM64_DIGEST for gcr.io - if [ "$_BUILD_TYPE" == "official" ]; then - if [ -n "$(cat GCR_AMD64_DIGEST)" ]; then - echo "Applying sbom_amd64 tag to gcr.io AMD64 image with digest: $(cat GCR_AMD64_DIGEST)" - gcloud container images add-tag -q \ - gcr.io/${_OUTPUT_PROJECT}/cos-gpu-installer@$(cat GCR_AMD64_DIGEST) \ - gcr.io/${_OUTPUT_PROJECT}/cos-gpu-installer:sbom_amd64 - else - echo "GCR_AMD64_DIGEST is empty, cannot apply tag for gcr.io" - exit 1 - fi - - if [ -n "$(cat GCR_ARM64_DIGEST)" ]; then - echo "Applying sbom_arm64 tag to gcr.io ARM64 image with digest: $(cat GCR_ARM64_DIGEST)" - gcloud container images add-tag -q \ - gcr.io/${_OUTPUT_PROJECT}/cos-gpu-installer@$(cat GCR_ARM64_DIGEST) \ - gcr.io/${_OUTPUT_PROJECT}/cos-gpu-installer:sbom_arm64 - else - echo "GCR_ARM64_DIGEST is empty, cannot apply tag for gcr.io" - exit 1 - fi - else - echo "Skipping gcr.io sbom tagging as BUILD_TYPE is not official" - fi - - # Apply sbom_amd64 and sbom_arm64 to AMD64_DIGEST and ARM64_DIGEST for gcr-io-dev - # This step will be conducted by both presubmit and official - if [ -n "$(cat AMD64_DIGEST)" ]; then - echo "Applying sbom_amd64 tag to AMD64 image with digest: $(cat AMD64_DIGEST)" - gcloud container images add-tag -q \ - us-docker.pkg.dev/${_OUTPUT_PROJECT}/gcr-io-dev/cos-gpu-installer@$(cat AMD64_DIGEST) \ - us-docker.pkg.dev/${_OUTPUT_PROJECT}/gcr-io-dev/cos-gpu-installer:sbom_amd64 - else - echo "AMD64_DIGEST is empty, cannot apply tag for gcr-io-dev" - exit 1 - fi - - if [ -n "$(cat ARM64_DIGEST)" ]; then - echo "Applying sbom_arm64 tag to ARM64 image with digest: $(cat ARM64_DIGEST)" - gcloud container images add-tag -q \ - us-docker.pkg.dev/${_OUTPUT_PROJECT}/gcr-io-dev/cos-gpu-installer@$(cat ARM64_DIGEST) \ - us-docker.pkg.dev/${_OUTPUT_PROJECT}/gcr-io-dev/cos-gpu-installer:sbom_arm64 - else - echo "ARM64_DIGEST is empty, cannot apply tag for gcr-io-dev" - exit 1 - fi + env: + - 'TAG_NAME=${_TAG_NAME}' + - 'OUTPUT_PROJECT=${_OUTPUT_PROJECT}' + - 'BUILD_TYPE=${_BUILD_TYPE}' + - 'IMAGE_NAME=${_IMAGE_NAME}' + args: [ './src/scripts/gcloud_tag_multi_arch_images.sh'] timeout: 1800s
diff --git a/src/scripts/docker_buildx_push_with_tags.sh b/src/scripts/docker_buildx_push_with_tags.sh new file mode 100644 index 0000000..4e7e08c --- /dev/null +++ b/src/scripts/docker_buildx_push_with_tags.sh
@@ -0,0 +1,68 @@ +#!/bin/bash +# The script builds and uploads multi-arch container images to gcr-io-dev and gcr.io +# with tags. We attach different tags for presubmit and official builds. +# The upload to gcr.io will be depreciated after `Publishing to MOSS Exit Gates` is done. +set -eux + +# This step is needed to add a new entry to /proc/sys/fs/binfmt_misc. Docker +# uses QEMU user emulation to run arm64 programs on x86 hosts. A QEMU +# interpreter needs to be added to /proc/sys/fs/binfmt_misc to run arm64 +# programs. +docker run --privileged linuxkit/binfmt:v1.0.0 + +# The default builder (which appears to be the Docker daemon that implements +# the old, familiar `docker build` behavior) doesn't support the --platform +# flag, so we need to create a new builder. +docker buildx create --name builder --driver docker-container --platform linux/amd64,linux/arm64 +docker buildx use builder + +# Images produced in this way do not appear in the Docker image registry shown +# by `docker images`, at least by default. We use the --push flag to push the +# image after building it, because a subsequent `docker push` won't find the +# image locally. +if [ "$BUILD_TYPE" == "presubmit" ]; then + docker buildx build --platform 'linux/amd64,linux/arm64' --build-arg 'BUILDKIT_INLINE_CACHE=1' -f 'src/cmd/cos_gpu_installer/Dockerfile' -t "us-docker.pkg.dev/${OUTPUT_PROJECT}/gcr-io-dev/${IMAGE_NAME}:${TAG_NAME}" -t "us-docker.pkg.dev/${OUTPUT_PROJECT}/gcr-io-dev/${IMAGE_NAME}:${BUILD_TYPE}-${TAG_NAME}" -t "us-docker.pkg.dev/${OUTPUT_PROJECT}/gcr-io-dev/${IMAGE_NAME}:sbom" --cache-from "us-docker.pkg.dev/${OUTPUT_PROJECT}/gcr-io-dev/${IMAGE_NAME}:latest" --push '.' + docker pull us-docker.pkg.dev/${OUTPUT_PROJECT}/gcr-io-dev/${IMAGE_NAME}:${TAG_NAME} +elif [ "$BUILD_TYPE" == "official" ]; then + docker buildx build --platform 'linux/amd64,linux/arm64' --build-arg 'BUILDKIT_INLINE_CACHE=1' -f 'src/cmd/cos_gpu_installer/Dockerfile' -t "us-docker.pkg.dev/${OUTPUT_PROJECT}/gcr-io-dev/${IMAGE_NAME}:${TAG_NAME}" -t "us-docker.pkg.dev/${OUTPUT_PROJECT}/gcr-io-dev/${IMAGE_NAME}:${BUILD_TYPE}-${TAG_NAME}" -t "us-docker.pkg.dev/${OUTPUT_PROJECT}/gcr-io-dev/${IMAGE_NAME}:latest" -t "us-docker.pkg.dev/${OUTPUT_PROJECT}/gcr-io-dev/${IMAGE_NAME}:sbom" --cache-from "us-docker.pkg.dev/${OUTPUT_PROJECT}/gcr-io-dev/${IMAGE_NAME}:latest" --push '.' + docker pull us-docker.pkg.dev/${OUTPUT_PROJECT}/gcr-io-dev/${IMAGE_NAME}:${TAG_NAME} + docker buildx build --platform 'linux/amd64,linux/arm64' --build-arg 'BUILDKIT_INLINE_CACHE=1' -f 'src/cmd/cos_gpu_installer/Dockerfile' -t "gcr.io/${OUTPUT_PROJECT}/${IMAGE_NAME}:latest" -t "gcr.io/${OUTPUT_PROJECT}/${IMAGE_NAME}:${TAG_NAME}" -t "gcr.io/${OUTPUT_PROJECT}/${IMAGE_NAME}:sbom" --cache-from "gcr.io/${OUTPUT_PROJECT}/${IMAGE_NAME}:latest" --push '.' + docker pull gcr.io/${OUTPUT_PROJECT}/${IMAGE_NAME}:${TAG_NAME} +else + echo "Invalid BUILD_TYPE: $BUILD_TYPE" + exit 1 +fi + +if [ "$BUILD_TYPE" == "official" ]; then + echo "$(docker buildx imagetools inspect gcr.io/${OUTPUT_PROJECT}/${IMAGE_NAME}:${TAG_NAME} | grep -i -B 3 'platform: *linux/amd64' | grep -o 'sha256:[a-f0-9]*' 2>/dev/null)" > GCR_AMD64_DIGEST + echo "$(docker buildx imagetools inspect gcr.io/${OUTPUT_PROJECT}/${IMAGE_NAME}:${TAG_NAME} | grep -i -B 3 'platform: *linux/arm64' | grep -o 'sha256:[a-f0-9]*' 2>/dev/null)" > GCR_ARM64_DIGEST + if [ -n "$(cat GCR_AMD64_DIGEST)" ]; then + echo "Successfully extracted AMD64 digest for gcr.io: $(cat GCR_AMD64_DIGEST)" + else + echo "Failed to extract AMD64 digest for gcr.io" + exit 1 + fi + if [ -n "$(cat GCR_ARM64_DIGEST)" ]; then + echo "Successfully extracted ARM64 digest for gcr.io: $(cat GCR_ARM64_DIGEST)" + else + echo "Failed to extract ARM64 digest for gcr.io" + exit 1 + fi +else + echo "Skip finding amd/arm digests of gcr.io as BUILD_TYPE is not official" +fi + +echo "$(docker buildx imagetools inspect us-docker.pkg.dev/${OUTPUT_PROJECT}/gcr-io-dev/${IMAGE_NAME}:${TAG_NAME} | grep -i -B 3 'platform: *linux/amd64' | grep -o 'sha256:[a-f0-9]*' 2>/dev/null)" > AMD64_DIGEST +echo "$(docker buildx imagetools inspect us-docker.pkg.dev/${OUTPUT_PROJECT}/gcr-io-dev/${IMAGE_NAME}:${TAG_NAME} | grep -i -B 3 'platform: *linux/arm64' | grep -o 'sha256:[a-f0-9]*' 2>/dev/null)" > ARM64_DIGEST +if [ -n "$(cat AMD64_DIGEST)" ]; then + echo "Successfully extracted AMD64 digest: $(cat AMD64_DIGEST)" +else + echo "Failed to extract AMD64 digest for gcr-io-dev" + exit 1 +fi +if [ -n "$(cat ARM64_DIGEST)" ]; then + echo "Successfully extracted ARM64 digest: $(cat ARM64_DIGEST)" +else + echo "Failed to extract ARM64 digest for gcr-io-dev" + exit 1 +fi
diff --git a/src/scripts/gcloud_tag_multi_arch_images.sh b/src/scripts/gcloud_tag_multi_arch_images.sh new file mode 100644 index 0000000..2a15e1e --- /dev/null +++ b/src/scripts/gcloud_tag_multi_arch_images.sh
@@ -0,0 +1,53 @@ +#!/bin/bash +# This script tag multi-arch container images in gcr-io-dev and gcr.io with sbom_amd64 +# and sbom_arm64 which are used to generate SBOMs by louhi. It must be called after +# docker_buildx_push_with_tags.sh because it needs to use GCR_AMD64_DIGEST and GCR_ARM64_DIGEST. +# The script will eventually be depreciated when GCB supports generating SBOMs for +# contain images in docker deamon. The progress can be tracked in b/402720361. +set -eux + +if [ "$BUILD_TYPE" == "official" ]; then + if [ -f "GCR_AMD64_DIGEST" ] && [ -s "GCR_AMD64_DIGEST" ]; then + AMD64_GCR_DIGEST=$(cat GCR_AMD64_DIGEST) + echo "Applying sbom_amd64 tag to gcr.io AMD64 image with digest: $AMD64_GCR_DIGEST" + gcloud container images add-tag -q \ + gcr.io/${OUTPUT_PROJECT}/${IMAGE_NAME}@"$AMD64_GCR_DIGEST" \ + gcr.io/${OUTPUT_PROJECT}/${IMAGE_NAME}:sbom_amd64 + else + echo "GCR_AMD64_DIGEST is empty or missing, cannot apply tag for gcr.io" + exit 1 + fi + if [ -f "GCR_ARM64_DIGEST" ] && [ -s "GCR_ARM64_DIGEST" ]; then + ARM64_GCR_DIGEST=$(cat GCR_ARM64_DIGEST) + echo "Applying sbom_arm64 tag to gcr.io ARM64 image with digest: $ARM64_GCR_DIGEST" + gcloud container images add-tag -q \ + gcr.io/${OUTPUT_PROJECT}/${IMAGE_NAME}@"$ARM64_GCR_DIGEST" \ + gcr.io/${OUTPUT_PROJECT}/${IMAGE_NAME}:sbom_arm64 + else + echo "GCR_ARM64_DIGEST is empty or missing, cannot apply tag for gcr.io" + exit 1 + fi +else + echo "Skipping gcr.io sbom tagging as BUILD_TYPE is not official" +fi + +if [ -f "AMD64_DIGEST" ] && [ -s "AMD64_DIGEST" ]; then + AMD64_DEV_DIGEST=$(cat AMD64_DIGEST) + echo "Applying sbom_amd64 tag to AMD64 image with digest: $AMD64_DEV_DIGEST" + gcloud container images add-tag -q \ + us-docker.pkg.dev/${OUTPUT_PROJECT}/gcr-io-dev/${IMAGE_NAME}@"$AMD64_DEV_DIGEST" \ + us-docker.pkg.dev/${OUTPUT_PROJECT}/gcr-io-dev/${IMAGE_NAME}:sbom_amd64 +else + echo "AMD64_DIGEST is empty or missing, cannot apply tag for gcr-io-dev" + exit 1 +fi +if [ -f "ARM64_DIGEST" ] && [ -s "ARM64_DIGEST" ]; then + ARM64_DEV_DIGEST=$(cat ARM64_DIGEST) + echo "Applying sbom_arm64 tag to ARM64 image with digest: $ARM64_DEV_DIGEST" + gcloud container images add-tag -q \ + us-docker.pkg.dev/${OUTPUT_PROJECT}/gcr-io-dev/${IMAGE_NAME}@"$ARM64_DEV_DIGEST" \ + us-docker.pkg.dev/${OUTPUT_PROJECT}/gcr-io-dev/${IMAGE_NAME}:sbom_arm64 +else + echo "ARM64_DIGEST is empty or missing, cannot apply tag for gcr-io-dev" + exit 1 +fi