You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

common.sh 20 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. #!/usr/bin/env bash
  2. # Copyright © 2023 OpenIM. All rights reserved.
  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. # shellcheck disable=SC2034 # Variables sourced in other scripts.
  16. # Common utilities, variables and checks for all build scripts.
  17. set -o errexit
  18. set -o nounset
  19. set -o pipefail
  20. # Unset CDPATH, having it set messes up with script import paths
  21. unset CDPATH
  22. USER_ID=$(id -u)
  23. GROUP_ID=$(id -g)
  24. DOCKER_OPTS=${DOCKER_OPTS:-""}
  25. IFS=" " read -r -a DOCKER <<< "docker ${DOCKER_OPTS}"
  26. DOCKER_HOST=${DOCKER_HOST:-""}
  27. DOCKER_MACHINE_NAME=${DOCKER_MACHINE_NAME:-"openim-dev"}
  28. readonly DOCKER_MACHINE_DRIVER=${DOCKER_MACHINE_DRIVER:-"virtualbox --virtualbox-cpu-count -1"}
  29. # This will canonicalize the path
  30. OPENIM_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. && pwd -P)
  31. source "${OPENIM_ROOT}/scripts/lib/init.sh"
  32. # Constants
  33. readonly OPENIM_BUILD_IMAGE_REPO=openim-build
  34. #readonly OPENIM_BUILD_IMAGE_CROSS_TAG="$(cat "${OPENIM_ROOT}/build/build-image/cross/VERSION")"
  35. readonly OPENIM_DOCKER_REGISTRY="${OPENIM_DOCKER_REGISTRY:-k8s.gcr.io}"
  36. readonly OPENIM_BASE_IMAGE_REGISTRY="${OPENIM_BASE_IMAGE_REGISTRY:-us.gcr.io/k8s-artifacts-prod/build-image}"
  37. # This version number is used to cause everyone to rebuild their data containers
  38. # and build image. This is especially useful for automated build systems like
  39. # Jenkins.
  40. #
  41. # Increment/change this number if you change the build image (anything under
  42. # build/build-image) or change the set of volumes in the data container.
  43. #readonly OPENIM_BUILD_IMAGE_VERSION_BASE="$(cat "${OPENIM_ROOT}/build/build-image/VERSION")"
  44. #readonly OPENIM_BUILD_IMAGE_VERSION="${OPENIM_BUILD_IMAGE_VERSION_BASE}-${OPENIM_BUILD_IMAGE_CROSS_TAG}"
  45. # Here we map the output directories across both the local and remote _output
  46. # directories:
  47. #
  48. # *_OUTPUT_ROOT - the base of all output in that environment.
  49. # *_OUTPUT_SUBPATH - location where golang stuff is built/cached. Also
  50. # persisted across docker runs with a volume mount.
  51. # *_OUTPUT_BINPATH - location where final binaries are placed. If the remote
  52. # is really remote, this is the stuff that has to be copied
  53. # back.
  54. # OUT_DIR can come in from the Makefile, so honor it.
  55. readonly LOCAL_OUTPUT_ROOT="${OPENIM_ROOT}/${OUT_DIR:-_output}"
  56. readonly LOCAL_OUTPUT_SUBPATH="${LOCAL_OUTPUT_ROOT}/platforms"
  57. readonly LOCAL_OUTPUT_BINPATH="${LOCAL_OUTPUT_SUBPATH}"
  58. readonly LOCAL_OUTPUT_GOPATH="${LOCAL_OUTPUT_SUBPATH}/go"
  59. readonly LOCAL_OUTPUT_IMAGE_STAGING="${LOCAL_OUTPUT_ROOT}/images"
  60. # This is the port on the workstation host to expose RSYNC on. Set this if you
  61. # are doing something fancy with ssh tunneling.
  62. readonly OPENIM_RSYNC_PORT="${OPENIM_RSYNC_PORT:-}"
  63. # This is the port that rsync is running on *inside* the container. This may be
  64. # mapped to OPENIM_RSYNC_PORT via docker networking.
  65. readonly OPENIM_CONTAINER_RSYNC_PORT=8730
  66. # Get the set of master binaries that run in Docker (on Linux)
  67. # Entry format is "<name-of-binary>,<base-image>".
  68. # Binaries are placed in /usr/local/bin inside the image.
  69. #
  70. # $1 - server architecture
  71. openim::build::get_docker_wrapped_binaries() {
  72. local arch=$1
  73. local debian_base_version=v2.1.0
  74. local debian_iptables_version=v12.1.0
  75. ### If you change any of these lists, please also update DOCKERIZED_BINARIES
  76. ### in build/BUILD. And openim::golang::server_image_targets
  77. local targets=(
  78. "openim-apiserver,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
  79. "openim-controller-manager,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
  80. "openim-scheduler,${OPENIM_BASE_IMAGE_REGISTRY}/debian-base-${arch}:${debian_base_version}"
  81. "openim-proxy,${OPENIM_BASE_IMAGE_REGISTRY}/debian-iptables-${arch}:${debian_iptables_version}"
  82. )
  83. echo "${targets[@]}"
  84. }
  85. # ---------------------------------------------------------------------------
  86. # Basic setup functions
  87. # Verify that the right utilities and such are installed for building openim. Set
  88. # up some dynamic constants.
  89. # Args:
  90. # $1 - boolean of whether to require functioning docker (default true)
  91. #
  92. # Vars set:
  93. # OPENIM_ROOT_HASH
  94. # OPENIM_BUILD_IMAGE_TAG_BASE
  95. # OPENIM_BUILD_IMAGE_TAG
  96. # OPENIM_BUILD_IMAGE
  97. # OPENIM_BUILD_CONTAINER_NAME_BASE
  98. # OPENIM_BUILD_CONTAINER_NAME
  99. # OPENIM_DATA_CONTAINER_NAME_BASE
  100. # OPENIM_DATA_CONTAINER_NAME
  101. # OPENIM_RSYNC_CONTAINER_NAME_BASE
  102. # OPENIM_RSYNC_CONTAINER_NAME
  103. # DOCKER_MOUNT_ARGS
  104. # LOCAL_OUTPUT_BUILD_CONTEXT
  105. function openim::build::verify_prereqs() {
  106. local -r require_docker=${1:-true}
  107. openim::log::status "Verifying Prerequisites...."
  108. openim::build::ensure_tar || return 1
  109. openim::build::ensure_rsync || return 1
  110. if ${require_docker}; then
  111. openim::build::ensure_docker_in_path || return 1
  112. openim::util::ensure_docker_daemon_connectivity || return 1
  113. if (( OPENIM_VERBOSE > 3 )); then
  114. openim::log::status "Docker Version:"
  115. "${DOCKER[@]}" version | openim::log::info_from_stdin
  116. fi
  117. fi
  118. OPENIM_GIT_BRANCH=$(git symbolic-ref --short -q HEAD 2>/dev/null || true)
  119. OPENIM_ROOT_HASH=$(openim::build::short_hash "${HOSTNAME:-}:${OPENIM_ROOT}:${OPENIM_GIT_BRANCH}")
  120. OPENIM_BUILD_IMAGE_TAG_BASE="build-${OPENIM_ROOT_HASH}"
  121. #OPENIM_BUILD_IMAGE_TAG="${OPENIM_BUILD_IMAGE_TAG_BASE}-${OPENIM_BUILD_IMAGE_VERSION}"
  122. #OPENIM_BUILD_IMAGE="${OPENIM_BUILD_IMAGE_REPO}:${OPENIM_BUILD_IMAGE_TAG}"
  123. OPENIM_BUILD_CONTAINER_NAME_BASE="openim-build-${OPENIM_ROOT_HASH}"
  124. #OPENIM_BUILD_CONTAINER_NAME="${OPENIM_BUILD_CONTAINER_NAME_BASE}-${OPENIM_BUILD_IMAGE_VERSION}"
  125. OPENIM_RSYNC_CONTAINER_NAME_BASE="openim-rsync-${OPENIM_ROOT_HASH}"
  126. #OPENIM_RSYNC_CONTAINER_NAME="${OPENIM_RSYNC_CONTAINER_NAME_BASE}-${OPENIM_BUILD_IMAGE_VERSION}"
  127. OPENIM_DATA_CONTAINER_NAME_BASE="openim-build-data-${OPENIM_ROOT_HASH}"
  128. #OPENIM_DATA_CONTAINER_NAME="${OPENIM_DATA_CONTAINER_NAME_BASE}-${OPENIM_BUILD_IMAGE_VERSION}"
  129. #DOCKER_MOUNT_ARGS=(--volumes-from "${OPENIM_DATA_CONTAINER_NAME}")
  130. #LOCAL_OUTPUT_BUILD_CONTEXT="${LOCAL_OUTPUT_IMAGE_STAGING}/${OPENIM_BUILD_IMAGE}"
  131. openim::version::get_version_vars
  132. #openim::version::save_version_vars "${OPENIM_ROOT}/.dockerized-openim-version-defs"
  133. }
  134. # ---------------------------------------------------------------------------
  135. # Utility functions
  136. function openim::build::docker_available_on_osx() {
  137. if [[ -z "${DOCKER_HOST}" ]]; then
  138. if [[ -S "/var/run/docker.sock" ]]; then
  139. openim::log::status "Using Docker for MacOS"
  140. return 0
  141. fi
  142. openim::log::status "No docker host is set. Checking options for setting one..."
  143. if [[ -z "$(which docker-machine)" ]]; then
  144. openim::log::status "It looks like you're running Mac OS X, yet neither Docker for Mac nor docker-machine can be found."
  145. openim::log::status "See: https://docs.docker.com/engine/installation/mac/ for installation instructions."
  146. return 1
  147. elif [[ -n "$(which docker-machine)" ]]; then
  148. openim::build::prepare_docker_machine
  149. fi
  150. fi
  151. }
  152. function openim::build::prepare_docker_machine() {
  153. openim::log::status "docker-machine was found."
  154. local available_memory_bytes
  155. available_memory_bytes=$(sysctl -n hw.memsize 2>/dev/null)
  156. local bytes_in_mb=1048576
  157. # Give virtualbox 1/2 the system memory. Its necessary to divide by 2, instead
  158. # of multiple by .5, because bash can only multiply by ints.
  159. local memory_divisor=2
  160. local virtualbox_memory_mb=$(( available_memory_bytes / (bytes_in_mb * memory_divisor) ))
  161. docker-machine inspect "${DOCKER_MACHINE_NAME}" &> /dev/null || {
  162. openim::log::status "Creating a machine to build IAM"
  163. docker-machine create --driver "${DOCKER_MACHINE_DRIVER}" \
  164. --virtualbox-memory "${virtualbox_memory_mb}" \
  165. --engine-env HTTP_PROXY="${IAMRNETES_HTTP_PROXY:-}" \
  166. --engine-env HTTPS_PROXY="${IAMRNETES_HTTPS_PROXY:-}" \
  167. --engine-env NO_PROXY="${IAMRNETES_NO_PROXY:-127.0.0.1}" \
  168. "${DOCKER_MACHINE_NAME}" > /dev/null || {
  169. openim::log::error "Something went wrong creating a machine."
  170. openim::log::error "Try the following: "
  171. openim::log::error "docker-machine create -d ${DOCKER_MACHINE_DRIVER} --virtualbox-memory ${virtualbox_memory_mb} ${DOCKER_MACHINE_NAME}"
  172. return 1
  173. }
  174. }
  175. docker-machine start "${DOCKER_MACHINE_NAME}" &> /dev/null
  176. # it takes `docker-machine env` a few seconds to work if the machine was just started
  177. local docker_machine_out
  178. while ! docker_machine_out=$(docker-machine env "${DOCKER_MACHINE_NAME}" 2>&1); do
  179. if [[ ${docker_machine_out} =~ "Error checking TLS connection" ]]; then
  180. echo "${docker_machine_out}"
  181. docker-machine regenerate-certs "${DOCKER_MACHINE_NAME}"
  182. else
  183. sleep 1
  184. fi
  185. done
  186. eval "$(docker-machine env "${DOCKER_MACHINE_NAME}")"
  187. openim::log::status "A Docker host using docker-machine named '${DOCKER_MACHINE_NAME}' is ready to go!"
  188. return 0
  189. }
  190. function openim::build::is_gnu_sed() {
  191. [[ $(sed --version 2>&1) == *GNU* ]]
  192. }
  193. function openim::build::ensure_rsync() {
  194. if [[ -z "$(which rsync)" ]]; then
  195. openim::log::error "Can't find 'rsync' in PATH, please fix and retry."
  196. return 1
  197. fi
  198. }
  199. function openim::build::update_dockerfile() {
  200. if openim::build::is_gnu_sed; then
  201. sed_opts=(-i)
  202. else
  203. sed_opts=(-i '')
  204. fi
  205. sed "${sed_opts[@]}" "s/OPENIM_BUILD_IMAGE_CROSS_TAG/${OPENIM_BUILD_IMAGE_CROSS_TAG}/" "${LOCAL_OUTPUT_BUILD_CONTEXT}/Dockerfile"
  206. }
  207. function openim::build::set_proxy() {
  208. if [[ -n "${IAMRNETES_HTTPS_PROXY:-}" ]]; then
  209. echo "ENV https_proxy $IAMRNETES_HTTPS_PROXY" >> "${LOCAL_OUTPUT_BUILD_CONTEXT}/Dockerfile"
  210. fi
  211. if [[ -n "${IAMRNETES_HTTP_PROXY:-}" ]]; then
  212. echo "ENV http_proxy $IAMRNETES_HTTP_PROXY" >> "${LOCAL_OUTPUT_BUILD_CONTEXT}/Dockerfile"
  213. fi
  214. if [[ -n "${IAMRNETES_NO_PROXY:-}" ]]; then
  215. echo "ENV no_proxy $IAMRNETES_NO_PROXY" >> "${LOCAL_OUTPUT_BUILD_CONTEXT}/Dockerfile"
  216. fi
  217. }
  218. function openim::build::ensure_docker_in_path() {
  219. if [[ -z "$(which docker)" ]]; then
  220. openim::log::error "Can't find 'docker' in PATH, please fix and retry."
  221. openim::log::error "See https://docs.docker.com/installation/#installation for installation instructions."
  222. return 1
  223. fi
  224. }
  225. function openim::build::ensure_tar() {
  226. if [[ -n "${TAR:-}" ]]; then
  227. return
  228. fi
  229. # Find gnu tar if it is available, bomb out if not.
  230. TAR=tar
  231. if which gtar &>/dev/null; then
  232. TAR=gtar
  233. else
  234. if which gnutar &>/dev/null; then
  235. TAR=gnutar
  236. fi
  237. fi
  238. if ! "${TAR}" --version | grep -q GNU; then
  239. echo " !!! Cannot find GNU tar. Build on Linux or install GNU tar"
  240. echo " on Mac OS X (brew install gnu-tar)."
  241. return 1
  242. fi
  243. }
  244. function openim::build::has_docker() {
  245. which docker &> /dev/null
  246. }
  247. function openim::build::has_ip() {
  248. which ip &> /dev/null && ip -Version | grep 'iproute2' &> /dev/null
  249. }
  250. # Detect if a specific image exists
  251. #
  252. # $1 - image repo name
  253. # $2 - image tag
  254. function openim::build::docker_image_exists() {
  255. [[ -n $1 && -n $2 ]] || {
  256. openim::log::error "Internal error. Image not specified in docker_image_exists."
  257. exit 2
  258. }
  259. [[ $("${DOCKER[@]}" images -q "${1}:${2}") ]]
  260. }
  261. # Delete all images that match a tag prefix except for the "current" version
  262. #
  263. # $1: The image repo/name
  264. # $2: The tag base. We consider any image that matches $2*
  265. # $3: The current image not to delete if provided
  266. function openim::build::docker_delete_old_images() {
  267. # In Docker 1.12, we can replace this with
  268. # docker images "$1" --format "{{.Tag}}"
  269. for tag in $("${DOCKER[@]}" images "${1}" | tail -n +2 | awk '{print $2}') ; do
  270. if [[ "${tag}" != "${2}"* ]] ; then
  271. V=3 openim::log::status "Keeping image ${1}:${tag}"
  272. continue
  273. fi
  274. if [[ -z "${3:-}" || "${tag}" != "${3}" ]] ; then
  275. V=2 openim::log::status "Deleting image ${1}:${tag}"
  276. "${DOCKER[@]}" rmi "${1}:${tag}" >/dev/null
  277. else
  278. V=3 openim::log::status "Keeping image ${1}:${tag}"
  279. fi
  280. done
  281. }
  282. # Stop and delete all containers that match a pattern
  283. #
  284. # $1: The base container prefix
  285. # $2: The current container to keep, if provided
  286. function openim::build::docker_delete_old_containers() {
  287. # In Docker 1.12 we can replace this line with
  288. # docker ps -a --format="{{.Names}}"
  289. for container in $("${DOCKER[@]}" ps -a | tail -n +2 | awk '{print $NF}') ; do
  290. if [[ "${container}" != "${1}"* ]] ; then
  291. V=3 openim::log::status "Keeping container ${container}"
  292. continue
  293. fi
  294. if [[ -z "${2:-}" || "${container}" != "${2}" ]] ; then
  295. V=2 openim::log::status "Deleting container ${container}"
  296. openim::build::destroy_container "${container}"
  297. else
  298. V=3 openim::log::status "Keeping container ${container}"
  299. fi
  300. done
  301. }
  302. # Takes $1 and computes a short has for it. Useful for unique tag generation
  303. function openim::build::short_hash() {
  304. [[ $# -eq 1 ]] || {
  305. openim::log::error "Internal error. No data based to short_hash."
  306. exit 2
  307. }
  308. local short_hash
  309. if which md5 >/dev/null 2>&1; then
  310. short_hash=$(md5 -q -s "$1")
  311. else
  312. short_hash=$(echo -n "$1" | md5sum)
  313. fi
  314. echo "${short_hash:0:10}"
  315. }
  316. # Pedantically kill, wait-on and remove a container. The -f -v options
  317. # to rm don't actually seem to get the job done, so force kill the
  318. # container, wait to ensure it's stopped, then try the remove. This is
  319. # a workaround for bug https://github.com/docker/docker/issues/3968.
  320. function openim::build::destroy_container() {
  321. "${DOCKER[@]}" kill "$1" >/dev/null 2>&1 || true
  322. if [[ $("${DOCKER[@]}" version --format '{{.Server.Version}}') = 17.06.0* ]]; then
  323. # Workaround https://github.com/moby/moby/issues/33948.
  324. # TODO: remove when 17.06.0 is not relevant anymore
  325. DOCKER_API_VERSION=v1.29 "${DOCKER[@]}" wait "$1" >/dev/null 2>&1 || true
  326. else
  327. "${DOCKER[@]}" wait "$1" >/dev/null 2>&1 || true
  328. fi
  329. "${DOCKER[@]}" rm -f -v "$1" >/dev/null 2>&1 || true
  330. }
  331. # ---------------------------------------------------------------------------
  332. # Building
  333. function openim::build::clean() {
  334. if openim::build::has_docker ; then
  335. openim::build::docker_delete_old_containers "${OPENIM_BUILD_CONTAINER_NAME_BASE}"
  336. openim::build::docker_delete_old_containers "${OPENIM_RSYNC_CONTAINER_NAME_BASE}"
  337. openim::build::docker_delete_old_containers "${OPENIM_DATA_CONTAINER_NAME_BASE}"
  338. openim::build::docker_delete_old_images "${OPENIM_BUILD_IMAGE_REPO}" "${OPENIM_BUILD_IMAGE_TAG_BASE}"
  339. V=2 openim::log::status "Cleaning all untagged docker images"
  340. "${DOCKER[@]}" rmi "$("${DOCKER[@]}" images -q --filter 'dangling=true')" 2> /dev/null || true
  341. fi
  342. if [[ -d "${LOCAL_OUTPUT_ROOT}" ]]; then
  343. openim::log::status "Removing _output directory"
  344. rm -rf "${LOCAL_OUTPUT_ROOT}"
  345. fi
  346. }
  347. # Set up the context directory for the openim-build image and build it.
  348. function openim::build::build_image() {
  349. mkdir -p "${LOCAL_OUTPUT_BUILD_CONTEXT}"
  350. # Make sure the context directory owned by the right user for syncing sources to container.
  351. chown -R "${USER_ID}":"${GROUP_ID}" "${LOCAL_OUTPUT_BUILD_CONTEXT}"
  352. cp /etc/localtime "${LOCAL_OUTPUT_BUILD_CONTEXT}/"
  353. cp "${OPENIM_ROOT}/build/build-image/Dockerfile" "${LOCAL_OUTPUT_BUILD_CONTEXT}/Dockerfile"
  354. cp "${OPENIM_ROOT}/build/build-image/rsyncd.sh" "${LOCAL_OUTPUT_BUILD_CONTEXT}/"
  355. dd if=/dev/urandom bs=512 count=1 2>/dev/null | LC_ALL=C tr -dc 'A-Za-z0-9' | dd bs=32 count=1 2>/dev/null > "${LOCAL_OUTPUT_BUILD_CONTEXT}/rsyncd.password"
  356. chmod go= "${LOCAL_OUTPUT_BUILD_CONTEXT}/rsyncd.password"
  357. openim::build::update_dockerfile
  358. openim::build::set_proxy
  359. openim::build::docker_build "${OPENIM_BUILD_IMAGE}" "${LOCAL_OUTPUT_BUILD_CONTEXT}" 'false'
  360. # Clean up old versions of everything
  361. openim::build::docker_delete_old_containers "${OPENIM_BUILD_CONTAINER_NAME_BASE}" "${OPENIM_BUILD_CONTAINER_NAME}"
  362. openim::build::docker_delete_old_containers "${OPENIM_RSYNC_CONTAINER_NAME_BASE}" "${OPENIM_RSYNC_CONTAINER_NAME}"
  363. openim::build::docker_delete_old_containers "${OPENIM_DATA_CONTAINER_NAME_BASE}" "${OPENIM_DATA_CONTAINER_NAME}"
  364. openim::build::docker_delete_old_images "${OPENIM_BUILD_IMAGE_REPO}" "${OPENIM_BUILD_IMAGE_TAG_BASE}" "${OPENIM_BUILD_IMAGE_TAG}"
  365. openim::build::ensure_data_container
  366. openim::build::sync_to_container
  367. }
  368. # Build a docker image from a Dockerfile.
  369. # $1 is the name of the image to build
  370. # $2 is the location of the "context" directory, with the Dockerfile at the root.
  371. # $3 is the value to set the --pull flag for docker build; true by default
  372. function openim::build::docker_build() {
  373. local -r image=$1
  374. local -r context_dir=$2
  375. local -r pull="${3:-true}"
  376. local -ra build_cmd=("${DOCKER[@]}" build -t "${image}" "--pull=${pull}" "${context_dir}")
  377. openim::log::status "Building Docker image ${image}"
  378. local docker_output
  379. docker_output=$("${build_cmd[@]}" 2>&1) || {
  380. cat <<EOF >&2
  381. +++ Docker build command failed for ${image}
  382. ${docker_output}
  383. To retry manually, run:
  384. ${build_cmd[*]}
  385. EOF
  386. return 1
  387. }
  388. }
  389. function openim::build::ensure_data_container() {
  390. # If the data container exists AND exited successfully, we can use it.
  391. # Otherwise nuke it and start over.
  392. local ret=0
  393. local code=0
  394. code=$(docker inspect \
  395. -f '{{.State.ExitCode}}' \
  396. "${OPENIM_DATA_CONTAINER_NAME}" 2>/dev/null) || ret=$?
  397. if [[ "${ret}" == 0 && "${code}" != 0 ]]; then
  398. openim::build::destroy_container "${OPENIM_DATA_CONTAINER_NAME}"
  399. ret=1
  400. fi
  401. if [[ "${ret}" != 0 ]]; then
  402. openim::log::status "Creating data container ${OPENIM_DATA_CONTAINER_NAME}"
  403. # We have to ensure the directory exists, or else the docker run will
  404. # create it as root.
  405. mkdir -p "${LOCAL_OUTPUT_GOPATH}"
  406. # We want this to run as root to be able to chown, so non-root users can
  407. # later use the result as a data container. This run both creates the data
  408. # container and chowns the GOPATH.
  409. #
  410. # The data container creates volumes for all of the directories that store
  411. # intermediates for the Go build. This enables incremental builds across
  412. # Docker sessions. The *_cgo paths are re-compiled versions of the go std
  413. # libraries for true static building.
  414. local -ra docker_cmd=(
  415. "${DOCKER[@]}" run
  416. --volume "${REMOTE_ROOT}" # white-out the whole output dir
  417. --volume /usr/local/go/pkg/linux_386_cgo
  418. --volume /usr/local/go/pkg/linux_amd64_cgo
  419. --volume /usr/local/go/pkg/linux_arm_cgo
  420. --volume /usr/local/go/pkg/linux_arm64_cgo
  421. --volume /usr/local/go/pkg/linux_ppc64le_cgo
  422. --volume /usr/local/go/pkg/darwin_amd64_cgo
  423. --volume /usr/local/go/pkg/darwin_386_cgo
  424. --volume /usr/local/go/pkg/windows_amd64_cgo
  425. --volume /usr/local/go/pkg/windows_386_cgo
  426. --name "${OPENIM_DATA_CONTAINER_NAME}"
  427. --hostname "${HOSTNAME}"
  428. "${OPENIM_BUILD_IMAGE}"
  429. chown -R "${USER_ID}":"${GROUP_ID}"
  430. "${REMOTE_ROOT}"
  431. /usr/local/go/pkg/
  432. )
  433. "${docker_cmd[@]}"
  434. fi
  435. }
  436. # Build all openim commands.
  437. function openim::build::build_command() {
  438. openim::log::status "Running build command..."
  439. make -C "${OPENIM_ROOT}" build.multiarch BINS="openimctl openim-apiserver openim-authz-server openim-pump openim-watcher"
  440. }