image-util.sh 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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. WHAT=$2
  20. KUBE_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd -P)"
  21. source "${KUBE_ROOT}/hack/lib/logging.sh"
  22. source "${KUBE_ROOT}/hack/lib/util.sh"
  23. # Mapping of go ARCH to actual architectures shipped part of multiarch/qemu-user-static project
  24. declare -A QEMUARCHS=( ["amd64"]="x86_64" ["arm"]="arm" ["arm64"]="aarch64" ["ppc64le"]="ppc64le" ["s390x"]="s390x" )
  25. # Returns list of all supported architectures from BASEIMAGE file
  26. listArchs() {
  27. image=$1
  28. cut -d "=" -f 1 "${image}"/BASEIMAGE
  29. }
  30. # Returns baseimage need to used in Dockerfile for any given architecture
  31. getBaseImage() {
  32. arch=$1
  33. grep "${arch}=" BASEIMAGE | cut -d= -f2
  34. }
  35. # This function will build test image for all the architectures
  36. # mentioned in BASEIMAGE file. In the absence of BASEIMAGE file,
  37. # it will build for all the supported arch list - amd64, arm,
  38. # arm64, ppc64le, s390x
  39. build() {
  40. image=$1
  41. if [[ -f ${image}/BASEIMAGE ]]; then
  42. archs=$(listArchs "$image")
  43. else
  44. archs=${!QEMUARCHS[*]}
  45. fi
  46. kube::util::ensure-gnu-sed
  47. for arch in ${archs}; do
  48. echo "Building image for ${image} ARCH: ${arch}..."
  49. # Create a temporary directory for every architecture and copy the image content
  50. # and build the image from temporary directory
  51. mkdir -p "${KUBE_ROOT}"/_tmp
  52. temp_dir=$(mktemp -d "${KUBE_ROOT}"/_tmp/test-images-build.XXXXXX)
  53. kube::util::trap_add "rm -rf ${temp_dir}" EXIT
  54. cp -r "${image}"/* "${temp_dir}"
  55. if [[ -f ${image}/Makefile ]]; then
  56. # make bin will take care of all the prerequisites needed
  57. # for building the docker image
  58. make -C "${image}" bin ARCH="${arch}" TARGET="${temp_dir}"
  59. fi
  60. pushd "${temp_dir}"
  61. # image tag
  62. TAG=$(<VERSION)
  63. if [[ -f BASEIMAGE ]]; then
  64. BASEIMAGE=$(getBaseImage "${arch}")
  65. ${SED} -i "s|BASEIMAGE|${BASEIMAGE}|g" Dockerfile
  66. ${SED} -i "s|BASEARCH|${arch}|g" Dockerfile
  67. fi
  68. # copy the qemu-*-static binary to docker image to build the multi architecture image on x86 platform
  69. if grep -q "CROSS_BUILD_" Dockerfile; then
  70. if [[ "${arch}" == "amd64" ]]; then
  71. ${SED} -i "/CROSS_BUILD_/d" Dockerfile
  72. else
  73. ${SED} -i "s|QEMUARCH|${QEMUARCHS[$arch]}|g" Dockerfile
  74. # Register qemu-*-static for all supported processors except the current one
  75. echo "Registering qemu-*-static binaries in the kernel"
  76. local sudo=""
  77. if [[ $(id -u) != 0 ]]; then
  78. sudo=sudo
  79. fi
  80. ${sudo} "${KUBE_ROOT}/third_party/multiarch/qemu-user-static/register/register.sh" --reset
  81. 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}"
  82. # Ensure we don't get surprised by umask settings
  83. chmod 0755 "${temp_dir}/qemu-${QEMUARCHS[$arch]}-static"
  84. ${SED} -i "s/CROSS_BUILD_//g" Dockerfile
  85. fi
  86. fi
  87. docker build --pull -t "${REGISTRY}/${image}-${arch}:${TAG}" .
  88. popd
  89. done
  90. }
  91. docker_version_check() {
  92. # The reason for this version check is even though "docker manifest" command is available in 18.03, it does
  93. # not work properly in that version. So we insist on 18.06.0 or higher.
  94. docker_version=$(docker version --format '{{.Client.Version}}' | cut -d"-" -f1)
  95. if [[ ${docker_version} != 18.06.0 && ${docker_version} < 18.06.0 ]]; then
  96. echo "Minimum docker version 18.06.0 is required for creating and pushing manifest images[found: ${docker_version}]"
  97. exit 1
  98. fi
  99. }
  100. # This function will push the docker images
  101. push() {
  102. image=$1
  103. docker_version_check
  104. TAG=$(<"${image}"/VERSION)
  105. if [[ -f ${image}/BASEIMAGE ]]; then
  106. archs=$(listArchs "$image")
  107. else
  108. archs=${!QEMUARCHS[*]}
  109. fi
  110. for arch in ${archs}; do
  111. docker push "${REGISTRY}/${image}-${arch}:${TAG}"
  112. done
  113. kube::util::ensure-gnu-sed
  114. # The manifest command is still experimental as of Docker 18.09.2
  115. export DOCKER_CLI_EXPERIMENTAL="enabled"
  116. # reset manifest list; needed in case multiple images are being built / pushed.
  117. manifest=()
  118. # Make archs list into image manifest. Eg: 'amd64 ppc64le' to '${REGISTRY}/${image}-amd64:${TAG} ${REGISTRY}/${image}-ppc64le:${TAG}'
  119. while IFS='' read -r line; do manifest+=("$line"); done < <(echo "$archs" | ${SED} -e "s~[^ ]*~$REGISTRY\/$image\-&:$TAG~g")
  120. docker manifest create --amend "${REGISTRY}/${image}:${TAG}" "${manifest[@]}"
  121. for arch in ${archs}; do
  122. docker manifest annotate --arch "${arch}" "${REGISTRY}/${image}:${TAG}" "${REGISTRY}/${image}-${arch}:${TAG}"
  123. done
  124. docker manifest push --purge "${REGISTRY}/${image}:${TAG}"
  125. }
  126. # This function is for building the go code
  127. bin() {
  128. local arch_prefix=""
  129. if [[ "${ARCH:-}" == "arm" ]]; then
  130. arch_prefix="GOARM=${GOARM:-7}"
  131. fi
  132. for SRC in "$@";
  133. do
  134. docker run --rm -v "${TARGET}:${TARGET}:Z" -v "${KUBE_ROOT}":/go/src/k8s.io/kubernetes:Z \
  135. golang:"${GOLANG_VERSION}" \
  136. /bin/bash -c "\
  137. cd /go/src/k8s.io/kubernetes/test/images/${SRC_DIR} && \
  138. CGO_ENABLED=0 ${arch_prefix} GOARCH=${ARCH} go build -a -installsuffix cgo --ldflags '-w' -o ${TARGET}/${SRC} ./$(dirname "${SRC}")"
  139. done
  140. }
  141. shift
  142. if [[ "${WHAT}" == "all-conformance" ]]; then
  143. # NOTE(claudiub): Building *ALL* the images under the kubernetes/test/images folder takes an extremely
  144. # long time (especially some images), and some images are rarely used and rarely updated, so there's
  145. # no point in rebuilding all of them every time. This will only build the Conformance-related images.
  146. # Discussed during Conformance Office Hours Meeting (2019.12.17):
  147. # https://docs.google.com/document/d/1W31nXh9RYAb_VaYkwuPLd1hFxuRX3iU0DmaQ4lkCsX8/edit#heading=h.l87lu17xm9bh
  148. # echoserver image not included: https://github.com/kubernetes/kubernetes/issues/84158
  149. conformance_images=("agnhost" "jessie-dnsutils" "kitten" "nautilus" "nonewprivs" "resource-consumer" "sample-apiserver")
  150. for image in "${conformance_images[@]}"; do
  151. eval "${TASK}" "${image}"
  152. done
  153. else
  154. eval "${TASK}" "$@"
  155. fi