image-util.sh 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #!/usr/bin/env bash
  2. # Copyright 2017 The Kubernetes Authors.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. set -o errexit
  16. set -o nounset
  17. set -o pipefail
  18. TASK=$1
  19. IMAGE=$2
  20. KUBE_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd -P)"
  21. source "${KUBE_ROOT}/hack/lib/util.sh"
  22. # Mapping of go ARCH to actual architectures shipped part of multiarch/qemu-user-static project
  23. declare -A QEMUARCHS=( ["amd64"]="x86_64" ["arm"]="arm" ["arm64"]="aarch64" ["ppc64le"]="ppc64le" ["s390x"]="s390x" )
  24. # Returns list of all supported architectures from BASEIMAGE file
  25. listArchs() {
  26. cut -d "=" -f 1 "${IMAGE}"/BASEIMAGE
  27. }
  28. # Returns baseimage need to used in Dockerfile for any given architecture
  29. getBaseImage() {
  30. arch=$1
  31. echo $(grep "${arch}=" BASEIMAGE | cut -d= -f2)
  32. }
  33. # This function will build test image for all the architectures
  34. # mentioned in BASEIMAGE file. In the absence of BASEIMAGE file,
  35. # it will build for all the supported arch list - amd64, arm,
  36. # arm64, ppc64le, s390x
  37. build() {
  38. if [[ -f ${IMAGE}/BASEIMAGE ]]; then
  39. archs=$(listArchs)
  40. else
  41. archs=${!QEMUARCHS[@]}
  42. fi
  43. kube::util::ensure-gnu-sed
  44. for arch in ${archs}; do
  45. echo "Building image for ${IMAGE} ARCH: ${arch}..."
  46. # Create a temporary directory for every architecture and copy the image content
  47. # and build the image from temporary directory
  48. mkdir -p "${KUBE_ROOT}"/_tmp
  49. temp_dir=$(mktemp -d "${KUBE_ROOT}"/_tmp/test-images-build.XXXXXX)
  50. kube::util::trap_add "rm -rf ${temp_dir}" EXIT
  51. cp -r "${IMAGE}"/* "${temp_dir}"
  52. if [[ -f ${IMAGE}/Makefile ]]; then
  53. # make bin will take care of all the prerequisites needed
  54. # for building the docker image
  55. make -C "${IMAGE}" bin ARCH="${arch}" TARGET="${temp_dir}"
  56. fi
  57. pushd "${temp_dir}"
  58. # image tag
  59. TAG=$(<VERSION)
  60. if [[ -f BASEIMAGE ]]; then
  61. BASEIMAGE=$(getBaseImage "${arch}")
  62. ${SED} -i "s|BASEIMAGE|${BASEIMAGE}|g" Dockerfile
  63. ${SED} -i "s|BASEARCH|${arch}|g" Dockerfile
  64. fi
  65. # copy the qemu-*-static binary to docker image to build the multi architecture image on x86 platform
  66. if [[ $(grep "CROSS_BUILD_" Dockerfile) ]]; then
  67. if [[ "${arch}" == "amd64" ]]; then
  68. ${SED} -i "/CROSS_BUILD_/d" Dockerfile
  69. else
  70. ${SED} -i "s|QEMUARCH|${QEMUARCHS[$arch]}|g" Dockerfile
  71. # Register qemu-*-static for all supported processors except the current one
  72. echo "Registering qemu-*-static binaries in the kernel"
  73. local sudo=""
  74. if [[ $(id -u) != 0 ]]; then
  75. sudo=sudo
  76. fi
  77. "${sudo}" "${KUBE_ROOT}/third_party/multiarch/qemu-user-static/register/register.sh" --reset
  78. curl -sSL https://github.com/multiarch/qemu-user-static/releases/download/"${QEMUVERSION}"/x86_64_qemu-"${QEMUARCHS[$arch]}"-static.tar.gz | tar -xz -C "${temp_dir}"
  79. # Ensure we don't get surprised by umask settings
  80. chmod 0755 "${temp_dir}/qemu-${QEMUARCHS[$arch]}-static"
  81. ${SED} -i "s/CROSS_BUILD_//g" Dockerfile
  82. fi
  83. fi
  84. docker build --pull -t "${REGISTRY}/${IMAGE}-${arch}:${TAG}" .
  85. popd
  86. done
  87. }
  88. docker_version_check() {
  89. # The reason for this version check is even though "docker manifest" command is available in 18.03, it does
  90. # not work properly in that version. So we insist on 18.06.0 or higher.
  91. docker_version=$(docker version --format '{{.Client.Version}}' | cut -d"-" -f1)
  92. if [[ ${docker_version} != 18.06.0 && ${docker_version} < 18.06.0 ]]; then
  93. echo "Minimum docker version 18.06.0 is required for creating and pushing manifest images[found: ${docker_version}]"
  94. exit 1
  95. fi
  96. }
  97. # This function will push the docker images
  98. push() {
  99. docker_version_check
  100. TAG=$(<"${IMAGE}"/VERSION)
  101. if [[ -f ${IMAGE}/BASEIMAGE ]]; then
  102. archs=$(listArchs)
  103. else
  104. archs=${!QEMUARCHS[@]}
  105. fi
  106. for arch in ${archs}; do
  107. docker push "${REGISTRY}/${IMAGE}-${arch}:${TAG}"
  108. done
  109. kube::util::ensure-gnu-sed
  110. # The manifest command is still experimental as of Docker 18.09.2
  111. export DOCKER_CLI_EXPERIMENTAL="enabled"
  112. # Make archs list into image manifest. Eg: 'amd64 ppc64le' to '${REGISTRY}/${IMAGE}-amd64:${TAG} ${REGISTRY}/${IMAGE}-ppc64le:${TAG}'
  113. manifest=$(echo "$archs" | ${SED} -e "s~[^ ]*~$REGISTRY\/$IMAGE\-&:$TAG~g")
  114. docker manifest create --amend "${REGISTRY}/${IMAGE}:${TAG}" ${manifest}
  115. for arch in ${archs}; do
  116. docker manifest annotate --arch "${arch}" "${REGISTRY}/${IMAGE}:${TAG}" "${REGISTRY}/${IMAGE}-${arch}:${TAG}"
  117. done
  118. docker manifest push --purge "${REGISTRY}/${IMAGE}:${TAG}"
  119. }
  120. # This function is for building the go code
  121. bin() {
  122. for SRC in $@;
  123. do
  124. docker run --rm -it -v "${TARGET}:${TARGET}:Z" -v "${KUBE_ROOT}":/go/src/k8s.io/kubernetes:Z \
  125. golang:"${GOLANG_VERSION}" \
  126. /bin/bash -c "\
  127. cd /go/src/k8s.io/kubernetes/test/images/${SRC_DIR} && \
  128. CGO_ENABLED=0 GOARM=${GOARM} GOARCH=${ARCH} go build -a -installsuffix cgo --ldflags '-w' -o ${TARGET}/${SRC} ./$(dirname "${SRC}")"
  129. done
  130. }
  131. shift
  132. eval "${TASK}" "$@"