#!/bin/bash -e # Copyright 2016 The Rook Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. scriptdir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" source "${scriptdir}/common.sh" check_git if [ ! -z $DOCKER_HOST ]; then echo ERROR: we only support the case where docker is running locally for now. exit 1 fi # build the the container if we've not done so already echo ==== building the cross container \(this could take minutes the first time\) make_cmd="make --no-print-directory -C ${scriptdir}/../images cross PULL=0" make_output=$($make_cmd 2>&1) || { cat <&2 === cross build image failed for ${CROSS_IMAGE} ${make_output} EOF exit 1 } # run the container with the same uid and gid of the user to avoid # permissions issues when sharing volumes with the host USER_ARGS="-e BUILDER_UID=$( id -u ) -e BUILDER_GID=$( id -g )" BUILDER_HOME=/home/rook # setup kubectl from the host if available if [ -d ${HOME}/.kube ]; then KUBE_ARGS="-v ${HOME}/.kube:${BUILDER_HOME}/.kube" fi if [ -x ${KUBEADM_DIND_DIR}/kubectl ]; then KUBEADM_DIND_ARGS="-v ${KUBEADM_DIND_DIR}/kubectl:/usr/bin/kubectl" fi if [ "`uname -s`" != "Linux" ]; then # On non-linux hosts, its is EXTREMELY slow to mount the source # tree inside the container. As such we use rsync to copy the source # tree to a new docker volumer on each run. The first rsync take a # little bit of time, but subsequent ones go by fast. This approach # is MUCH faster than using osxfs, NFS or other approaches. # create a new volume to hold our go workspace. NOTE: while concurrent # runs of the build container are supported they will share the same volume # and we will be rsyncing to it at different times. This could lead to # undefined behavior but this should be a rare case on non-linux envs. if [[ ! $(docker volume ls | grep ${CROSS_IMAGE_VOLUME}) ]]; then echo ==== Creating docker volume "${CROSS_IMAGE_VOLUME}" and syncing sources echo ==== for first time. This could take a few seconds. docker volume create --name ${CROSS_IMAGE_VOLUME} &> /dev/null fi # On non-linux the layout is as follows: # # /var/run/docker.sock (bind mounted to host /var/run/docker.sock) # /${BUILDER_HOME} (bind mounted to an independent docker volume) # /.netrc (bind mounted to host ${HOME}/.netrc) # /.aws (bind mounted to host ${HOME}/.aws) # /.docker (bind mounted to host ${HOME}/.docker) # /.cache (bind mounted to host ${CACHE_DIR} if set) # /.ccache # /go/src/github.com/rook/rook (rsync'd from host ) # now copy the source tree to the container volume. Note this also # copies the .git directory but not the index.lock files which # change frequently and sometimes cause rsync to fail. rsync_host_to_container \ --filter="- /.work/" \ --filter="- /.cache/" \ --filter="- /.vscode/" \ --filter="- index.lock" MOUNT_OPTS="${MOUNT_OPTS} -v ${CROSS_IMAGE_VOLUME}:${BUILDER_HOME}" CCACHE_ARGS="-e CCACHE_DIR=${BUILDER_HOME}/.ccache \ -e CCACHE_DIR_HOST=${BUILDER_HOME}/.ccache -e CCACHE_LOG" else # On linux bind mounts are cheap so we dont need to rsync # the layout is as follows: # # /var/run/docker.sock (bind mounted to host /var/run/docker.sock) # /${BUILDER_HOME} # /.netrc (bind mounted to host ${HOME}/.netrc) # /.aws (bind mounted to host ${HOME}/.aws) # /.docker (bind mounted to host ${HOME}/.docker) # /.cache (bind mounted to host ${CCACHE_DIR}) # /go # /pkg (bind mounted to /.work/cross_pkg) # /src/github.com/rook/rook (bind mounted to ) MOUNT_OPTS="${MOUNT_OPTS} \ -v ${scriptdir}/../.work/cross_pkg:${BUILDER_HOME}/go/pkg -v ${scriptdir}/..:${BUILDER_HOME}/go/src/${BUILD_REPO}" # if CCACHE_DIR is not set, set it to the default if [[ -z "${CCACHE_DIR}" ]]; then CCACHE_DIR="${HOME}/.ccache" fi if [[ -d "${CCACHE_DIR}" ]]; then CCACHE_ARGS="-e CCACHE_DIR=${BUILDER_HOME}/.ccache \ -e CCACHE_DIR_HOST=${CCACHE_DIR} \ -e CCACHE_LOG \ -v ${CCACHE_DIR}:${BUILDER_HOME}/.ccache" fi fi # if CACHE_DIR is not set bind mount it if [[ -n "${CACHE_DIR}" ]]; then mkdir -p ${CACHE_DIR} DOWNLOAD_ARGS="-e CACHE_DIR=${BUILDER_HOME}/go/src/${BUILD_REPO}/.cache \ -v ${CACHE_DIR}:${BUILDER_HOME}/go/src/${BUILD_REPO}/.cache" fi # we copy credential files for github access [[ -f ${HOME}/.netrc ]] && NETRC_ARGS="-v ${HOME}/.netrc:${BUILDER_HOME}/.netrc" tty -s && TTY_ARGS=-ti || TTY_ARGS= # docker seems more reliable when running with net=host. if [ -z "${DISABLE_HOST_NETWORK}" ]; then NET_ARGS="--net=host" fi # BUGBUG: new docker clients switch to using OSX keychain. how do we copy creds? # sometimes we run docker inside docker. bind the docker config and socket if [ -z "${DISABLE_NESTED_DOCKER}" ]; then DOCKER_NESTED_ARGS="\ -v ${HOME}/.docker:${BUILDER_HOME}/.docker \ -v /var/run/docker.sock:/var/run/docker.sock" fi # set AWS creds AWS_ARGS="\ -e AWS_ACCESS_KEY_ID \ -e AWS_SECRET_ACCESS_KEY \ -e AWS_DEFAULT_REGION \ -v ${HOME}/.aws:${BUILDER_HOME}/.aws" rsync_back() { if [ "`uname -s`" != "Linux" ]; then # rsync generated files back to the host. IMPORTANT: we never rsync the .git directory back # since the host's version might have changed. rsync_container_to_host \ --filter="+ /_output/" \ --filter="+ /vendor/" \ --filter="- /*" fi } docker run \ --rm \ -h ${BUILD_HOST} \ -e BUILD_REGISTRY=${BUILD_REGISTRY} \ -e GOPATH="${BUILDER_HOME}/go" \ -e GO_PKG_DIR="" \ -e GITHUB_TOKEN \ -e VERSION \ -e CHANNEL \ -v ${PWD}/_output:${BUILDER_HOME}/go/bin \ ${TTY_ARGS} \ ${KUBE_ARGS} \ ${KUBEADM_DIND_ARGS} \ ${CCACHE_ARGS} \ ${DOWNLOAD_ARGS} \ ${NETRC_ARGS} \ ${AWS_ARGS} \ ${USER_ARGS} \ ${DOCKER_NESTED_ARGS} \ ${NET_ARGS} \ ${MOUNT_OPTS} \ -w ${BUILDER_HOME}/go/src/${BUILD_REPO} \ ${CROSS_IMAGE} \ "$@" || { rsync_back; exit 1; } rsync_back