#!/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.
    return 1
fi

# if the container does not exist the pull or build it
if [[ ! $(docker images -q ${container_image}) ]]; then
    echo ==== Pulling ${container_image}
    docker pull ${container_image}
fi

# on Linux we run the container with the same uid and gid of the user to avoid
# permissions issues. For docker on macOS this is not needed since we rely on osxfs
if [ "`uname -s`" == "Linux" ]; then
  USER_ARGS="-e BUILDER_UID=$( id -u ) -e BUILDER_GID=$( id -g ) -e BUILDER_USER=$( id -un ) -e BUILDER_GROUP=$( id -gn )"
  BUILDER_HOME=/home/$( id -un )
else
  BUILDER_HOME=/root
fi

cleanup() {
    docker stop ${container_name} &> /dev/null || true
    docker rm ${container_name} &> /dev/null || true
}

# mount arguments
MOUNT_OPTS="\
    -v ${scriptdir}/../bin:${BUILDER_HOME}/go/src/${source_repo}/bin \
    -v ${scriptdir}/../release:${BUILDER_HOME}/go/src/${source_repo}/release \
"

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.

    # On non-linux 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)
    #    /.docker/config.json (bind mounted to host ${HOME}/.docker/config.json)
    #    /go (bind mounted to a docker volume)
    #       /.work
    #       /.ccache
    #       /bin  (bind mounted to host <source>/bin)
    #       /src/github.com/rook/rook (rsync'd from host <source>)
    #

    # create a new volume to hold our go workspace
    if [[ ! $(docker volume ls | grep ${container_volume}) ]]; then
        echo ==== Syncing sources for first time. This could take a few seconds.
        docker volume create --name ${container_volume} &> /dev/null
    fi

    trap "cleanup" EXIT
    cleanup

    # run the container as an rsyncd daemon so that we can copy the
    # source tree to the container volume.
    docker run \
        --name "${container_name}" \
        -d \
        -e OWNER=root \
        -e GROUP=root \
        -e MKDIRS="/volume/src/${source_repo}" \
        -p ${rsync_port}:873 \
        -v ${container_volume}:/volume \
        ${container_image} \
        /build/rsyncd.sh  &> /dev/null

    # wait for rsync to come up
    wait_for_rsync

    # now copy the source tree to the container volume
    rsync \
        --archive \
        --delete \
        --prune-empty-dirs \
        --filter='- /.work/' \
        --filter='- /.glide/' \
        --filter='- /.vscode/' \
        --filter='- /bin/' \
        --filter='- /release/' \
        ${scriptdir}/.. \
        rsync://localhost:${rsync_port}/volume/src/${source_repo}

    MOUNT_OPTS="${MOUNT_OPTS} \
        -v ${container_volume}:${BUILDER_HOME}/go"

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)
    #    /.docker/config.json (bind mounted to host ${HOME}/.docker/config.json)
    #    /go
    #       /.work  (bind mounted to host <source>/.work/cross)
    #       /.ccache (bind mounted to host CCACHE_DIR)
    #       /bin     (bind mounted to host <source>/bin)
    #       /src/github.com/rook/rook (bind mounted to <source>)
    #
    MOUNT_OPTS="${MOUNT_OPTS} \
        -v ${scriptdir}/../.work/cross:${BUILDER_HOME}/go/.work \
        -v ${scriptdir}/..:${BUILDER_HOME}/go/src/${source_repo}"

    CCACHE_MOUNT_ARGS="-v ${CCACHE_DIR}:${BUILDER_HOME}/go/.ccache"
fi

if [[ `which ccache` && -d "${CCACHE_DIR}" ]]; then
    CCACHE_ARGS="-e CCACHE_DIR=${BUILDER_HOME}/go/.ccache -e CCACHE_LOG ${CCACHE_MOUNT_ARGS}"
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

# sometimes we run docker inside docker. bind the docker config and socket
if [ -z "${DISABLE_NESTED_DOCKER}" ]; then
    DOCKER_NESTED_ARGS="\
    -v ${HOME}/.docker/config.json:${BUILDER_HOME}/.docker/config.json \
    -v /var/run/docker.sock:/var/run/docker.sock"
fi

trap "cleanup" EXIT
cleanup

docker run \
    --rm \
    --name "${container_name}" \
    -e GOPATH="${BUILDER_HOME}/go" \
    -e WORKDIR="${BUILDER_HOME}/go/.work" \
    -e GO_PKG_DIR="" \
    -e GITHUB_TOKEN \
    -e VERSION \
    ${TTY_ARGS} \
    ${CCACHE_ARGS} \
    ${NETRC_ARGS} \
    ${USER_ARGS} \
    ${DOCKER_NESTED_ARGS} \
    ${NET_ARGS} \
    ${MOUNT_OPTS} \
    -w ${BUILDER_HOME}/go/src/${source_repo} \
    ${container_image} \
    "$@"
