#!/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
if [ "`uname -m`" != "x86_64" ]; then
    echo ERROR: we only support the cross container build on amd64 host.
    exit 1
fi
echo ==== building the cross container \(this could take minutes the first time\)
make_cmd="make --no-print-directory -C ${scriptdir}/../images cross PULL=0 DOCKERCMD=${DOCKERCMD}"
make_output=$($make_cmd 2>&1) || {
    cat <<EOF >&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 [[ ! $(${DOCKERCMD} 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.
        ${DOCKERCMD} 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)
    #    /go/src/github.com/rook/rook (rsync'd from host <source>)

    # 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}"

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)
    #    /go
    #       /pkg (bind mounted to <source>/.work/cross_pkg)
    #       /src/github.com/rook/rook (bind mounted to <source>)

    MOUNT_OPTS="${MOUNT_OPTS} \
        -v ${scriptdir}/../.work/cross_pkg:${BUILDER_HOME}/go/pkg
        -v ${scriptdir}/..:${BUILDER_HOME}/go/src/${BUILD_REPO}"
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="- /*"
    fi
}

${DOCKERCMD} 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} \
    ${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
