#!/bin/bash
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you 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.

#
# Creates the artifacts, performing additional QA checks
#
# Usage: _docker_run.sh <docker_image_name> <script_to_execute> <java_version>

################################
#
# Prep
#
################################

[ $DEBUG ] && set -x

# variables, with defaults
[ "x${cassandra_dir}" != "x" ] || cassandra_dir="$(readlink -f $(dirname "$0")/../..)"
[ "x${build_dir}" != "x" ] || build_dir="${cassandra_dir}/build"
[ "x${m2_dir}" != "x" ] || m2_dir="${HOME}/.m2/repository"
[ -d "${build_dir}" ] || { mkdir -p "${build_dir}" ; }
[ -d "${m2_dir}" ] || { mkdir -p "${m2_dir}" ; }

java_version_default=`grep 'property\s*name="java.default"' ${cassandra_dir}/build.xml |sed -ne 's/.*value="\([^"]*\)".*/\1/p'`
java_version_supported=`grep 'property\s*name="java.supported"' ${cassandra_dir}/build.xml |sed -ne 's/.*value="\([^"]*\)".*/\1/p'`

if [ "$1" == "-h" ]; then
   echo "$0 [-h] <dockerfile> <run_script> [<java version>]"
   echo " this script is used by check|build*.sh scripts (in the same directory) as a wrapper delegating the container run of the <dockerfile> and execution of the <run_script>, and using [<java version>] is specified"
   exit 1
fi

# arguments
dockerfile=$1
run_script=$2
java_version=$3

# pre-conditions
command -v docker >/dev/null 2>&1 || { echo >&2 "docker needs to be installed"; exit 1; }
command -v timeout >/dev/null 2>&1 || { echo >&2 "timeout needs to be installed"; exit 1; }
(docker info >/dev/null 2>&1) || { echo >&2 "docker needs to running"; exit 1; }
[ -f "${cassandra_dir}/build.xml" ] || { echo >&2 "${cassandra_dir}/build.xml must exist"; exit 1; }
[ -f "${cassandra_dir}/.build/docker/${dockerfile}" ] || { echo >&2 "${cassandra_dir}/.build/docker/${dockerfile} must exist"; exit 1; }
[ -f "${cassandra_dir}/.build/${run_script}" ] || { echo >&2 "${cassandra_dir}/.build/${run_script} must exist"; exit 1; }
[ "${build_dir:0:1}" == "/" ] || { echo >&2 "\$build_dir must be provided as an absolute path, was ${build_dir}"; exit 1; }

if [ "x${java_version}" == "x" ] ; then
    echo "Defaulting to java ${java_version_default}"
    java_version="${java_version_default}"
fi

regx_java_version="(${java_version_supported//,/|})"
if [[ ! "${java_version}" =~ $regx_java_version ]]; then
   echo "Error: Java version is not in ${java_version_supported}, it is set to ${java_version}"
   exit 1
fi

# print debug information on versions
docker --version

# make sure build_dir is good
chmod -R ag+rwx ${build_dir}


################################
#
# Main
#
################################

# git worktrees need their original working directory (in its original path)
if [ -f ${cassandra_dir}/.git ] ; then
    git_location="$(cat ${cassandra_dir}/.git | awk -F".git" '{print $1}' | awk '{print $2}')"
    docker_volume_opt="${docker_volume_opt} -v${git_location}:${git_location}"
fi

pushd ${cassandra_dir}/.build >/dev/null

image_tag="$(md5sum docker/${dockerfile} | cut -d' ' -f1)"
image_name="apache/cassandra-${dockerfile/.docker/}:${image_tag}"

# Look for existing docker image, otherwise build
if ! ( [[ "$(docker images -q ${image_name} 2>/dev/null)" != "" ]] ) ; then
  echo "Build image not found locally, pulling image ${image_name}..."
  if ! ( docker pull -q ${image_name} >/dev/null 2>/dev/null ) ; then
    # Create build images containing the build tool-chain, Java and an Apache Cassandra git working directory, with retry
    echo "Building docker image..."
    until docker build -t ${image_name} -f docker/${dockerfile} .  ; do
        echo "docker build failed… trying again in 10s… "
        sleep 10
    done
    echo "Docker image ${image_name} has been built"
  else
    echo "Successfully pulled build image."
  fi
else
  echo "Found build image locally."
fi

# Run build script through docker
random_string="$(LC_ALL=C tr -dc A-Za-z0-9 </dev/urandom | head -c 6 ; echo '')"
run_script_name=$(echo ${run_script} | sed  's/.sh//' | sed 's/_//')
container_name="cassandra_${dockerfile/.docker/}_${un_script_name}_jdk${java_version}__${random_string}"

[ $DEBUG ] && docker_envs="${docker_envs} --env DEBUG=1"

# Docker commands:
#  change ant's build directory to $DIST_DIR
#  set java to java_version
#  execute the run_script
docker_command="export ANT_OPTS=\"-Dbuild.dir=\${DIST_DIR} ${CASSANDRA_DOCKER_ANT_OPTS}\" ; \
                source \${CASSANDRA_DIR}/.build/docker/_set_java.sh ${java_version} ; \
                \${CASSANDRA_DIR}/.build/${run_script} ${@:4} ; exit \$? "

# run without the default seccomp profile
# re-use the host's maven repository
container_id=$(docker run --name ${container_name} -d --security-opt seccomp=unconfined --rm \
    -v "${cassandra_dir}":/home/build/cassandra -v ${m2_dir}:/home/build/.m2/repository/ -v "${build_dir}":/dist \
    ${docker_envs} ${docker_volume_opt} \
    ${image_name} sleep 1h)

echo "Running container ${container_name} ${container_id} using image ${image_name}"

docker exec --user root ${container_name} bash -c "\${CASSANDRA_DIR}/.build/docker/_create_user.sh build $(id -u) $(id -g)"
docker exec --user build ${container_name} bash -c "${docker_command}"
RETURN=$?

# docker stop in background, ignore errors
( nohup docker stop ${container_name} >/dev/null 2>/dev/null & )
popd >/dev/null
[ $RETURN -eq 0 ] && echo "Build directory found at ${build_dir}"
exit $RETURN
