#!/bin/bash
# Copyright 2014 - Rackspace Hosting
#
#    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.


# Solum App Unit Test Script for Docker and lp-cedarish

SCRIPT_START_TIME=$(date +"%s")

PROJECT_ID=${PROJECT_ID:-null}
BUILD_ID=${BUILD_ID:-null}
TASKNAME=unittest
DOCKER_REGISTRY=${DOCKER_REGISTRY:-'127.0.0.1:5042'}
USER_PARAMS=${USER_PARAMS:-null}
SOLUM_PARAMS=${SOLUM_PARAMS:-null}
USE_DRONE=${_SYSTEM_USE_DRONE:-null}
GIT_PRIVATE_KEY=${REPO_DEPLOY_KEYS:-''}
ENTRYPOINT=${TEST_CMD:-:}
IMAGE_STORAGE=${IMAGE_STORAGE:-null}
DELETE_LOCAL_CACHE=${DELETE_LOCAL_CACHE:-null}
LP_ACCESS=${ACCESS:-null}

OS_AUTH_TOKEN=${OS_AUTH_TOKEN:-null}
OS_REGION_NAME=${OS_REGION_NAME:-null}
OS_STORAGE_URL=${OS_STORAGE_URL:-null}

OPR_LP_DOWNLOAD_STRATEGY=${OPR_LP_DOWNLOAD_STRATEGY:-null}
OPER_AUTH_TOKEN=${OPER_AUTH_TOKEN:-null}
OPER_OS_STORAGE_URL=${OPER_OS_STORAGE_URL:-null}

# TLOG, PRUN, ENSURE_LOGFILE, and elapsed defined in app-common
HERE=$(dirname $0)
source $HERE/../../common/utils

function TLOG () {
  TLOG_FILTERED $*
}

function cleanup_on_exit () {
  if [[ $DELETE_LOCAL_CACHE == "true" ]]; then
    # Not Deleting languagepack image because we found it conflicts with docker load in
    # performance tests, which might be due to a concurrency bug in docker load and rmi.
    #if [[ -n $BASE_IMG ]] && [[ $BASE_IMG != "solum/slugtester" ]]; then
    #  sudo docker rmi -f $BASE_IMG
    #fi

    # Delete local DU image after running user tests
    if [[ -n $RANDOM_NAME ]]; then
      sudo docker rmi $RANDOM_NAME
    fi

    # Delete the cloned git repo
    if [[ -n $APP_DIR ]]; then
      rm -rf $APP_DIR
    fi
    if [[ -n $TMP_DIR ]]; then
      rm -rf $TMP_DIR
    fi

    # Delete temp output file
    if [[ -n $OUTPUT ]] && [[ -e $OUTPUT ]]; then
      rm -f $OUTPUT
    fi

    remove_ssh_creds "$GIT_PRIVATE_KEY"
  fi
}

LOG_FILE=$(GET_LOGFILE)

TLOG ===== Starting Test Script $0 $*

# Check command line arguments
if [[ $# -lt 5 ]]; then
  TLOG Usage: $0 git_url commit_sha tenant img_external_ref lp_img_tag && exit 1
fi

PRUN silent sudo docker ps
[[ $? != 0 ]] && TLOG Cannot talk to docker. && exit 1

GIT=$1
shift
COMMIT_SHA=$1
shift
TENANT=$1
shift
IMG_EXTERNAL_REF=$1
shift
LP_IMG_TAG=$1

if ! (test_public_repo $GIT); then
    TLOG Could not reach $GIT with curl. Failing. && exit 1
fi

TLOG "Executing test command $ENTRYPOINT"

BASE_DIR=/dev/shm
RANDOM_NAME=$(mktemp -u XXXXXXXXXXXXXXXXXXXXXXX | tr '[:upper:]' '[:lower:]' | head -n 1)
APP_DIR=$BASE_DIR/solum/$RANDOM_NAME
TMP_DIR=/tmp/solum/$RANDOM_NAME
rm -rf $APP_DIR
rm -rf $TMP_DIR
mkdir -p $APP_DIR
mkdir -p $TMP_DIR

# Set base docker image to solum/slugtester for the 'auto' option
BASE_IMG="solum/slugtester"

trap cleanup_on_exit EXIT

# download base image if it is not 'Auto'
if [[ $IMG_EXTERNAL_REF != "auto" ]]; then
  TLOG downloading LP image from $IMAGE_STORAGE
  if [[ $IMAGE_STORAGE == "glance" ]]; then
    OUTPUT="$TMP_DIR/$LP_IMG_TAG"
    glance image-download --file $OUTPUT $IMG_EXTERNAL_REF
    if [[ $? != 0 ]]; then
      TLOG Failed to download image $IMG_EXTERNAL_REF from glance. && exit 1
    fi

    docker_load_with_retry $OUTPUT

    BASE_IMG=$LP_IMG_TAG
  elif [[ $IMAGE_STORAGE == "swift" ]]; then
    OUTPUT="$TMP_DIR/$LP_IMG_TAG"

    if [[ $LP_ACCESS == "custom" ]]; then
      python $HERE/swift-handler.py $OS_REGION_NAME $OS_AUTH_TOKEN $OS_STORAGE_URL download solum_lp $IMG_EXTERNAL_REF $OUTPUT \
      > >(while read ALINE; do TLOG $ALINE; done)
    elif [[ $LP_ACCESS == "operator" ]]; then
      if [[ $OPR_LP_DOWNLOAD_STRATEGY == "swift-client" ]]; then
        python $HERE/swift-handler.py $OS_REGION_NAME $OPER_AUTH_TOKEN $OPER_OS_STORAGE_URL download solum_lp $IMG_EXTERNAL_REF $OUTPUT \
        > >(while read ALINE; do TLOG $ALINE; done)
      elif [[ $OPR_LP_DOWNLOAD_STRATEGY == "wget" ]]; then
        wget -q "$IMG_EXTERNAL_REF" --output-document=$OUTPUT
      fi
    fi
    if [[ $? != 0 ]]; then
      TLOG Failed to download image $IMG_EXTERNAL_REF from swift. && exit 1
    fi

    docker_load_with_retry $OUTPUT
    if [[ $? != 0 ]]; then
      OUTPUT_FILE_SIZE=$(stat -c%s "$OUTPUT")
      TLOG Docker load failed, file size $OUTPUT_FILE_SIZE && exit 1
    fi

    BASE_IMG=$LP_IMG_TAG
  elif [[ $IMAGE_STORAGE == "docker_registry" ]]; then
    sudo docker pull $IMG_EXTERNAL_REF
    if [[ $? != 0 ]]; then
      TLOG Failed to download image $IMG_EXTERNAL_REF from docker registry. && exit 1
    fi

    BASE_IMG=$IMG_EXTERNAL_REF
  else
    TLOG Unsupported Image storage backend - $IMAGE_STORAGE && exit 1
  fi
fi

add_ssh_creds "$GIT_PRIVATE_KEY" "$APP_DIR"
[[ $? != 0 ]] && TLOG FAILED to register ssh key with ssh-agent && exit 1

if [[ $COMMIT_SHA ]]; then
  git_clone_with_retry $GIT $APP_DIR/code
  [[ $? != 0 ]] && TLOG Git clone failed. Check repo $GIT && exit 1

  cd $APP_DIR/code
  PRUN git checkout -B solum_testing $COMMIT_SHA
else
  git_clone_with_retry $GIT $APP_DIR/code --single-branch
  [[ $? != 0 ]] && TLOG Git clone failed. Check repo $GIT && exit 1

  cd $APP_DIR/code
fi

# if $ENTRYPOINT contains a testing script in repo ($APP_DIR/code)
# and not executable, make it executable
# docker ADD and COPY will inherit permissions
test_cmd_prefix="./"
if [[ -n $ENTRYPOINT ]] && [[ "$ENTRYPOINT" == $test_cmd_prefix* ]]; then
  script_name=${ENTRYPOINT:2}
  if [[ -e "$script_name" ]] && [[ ! -x "$script_name" ]]; then
    chmod +x "$script_name"
  fi
fi

DRONE_ENTRYPOINT=$ENTRYPOINT
DOCKER_ENTRYPOINT=$ENTRYPOINT

# copy params to the working dir
EXT=$(mktemp -u XXX | head -n 1)
if [[ $USER_PARAMS != null ]]; then
  cp $USER_PARAMS $APP_DIR/code/user_params.$EXT
  DRONE_ENTRYPOINT="/bin/bash -c 'source user_params.$EXT && $ENTRYPOINT'"
  DOCKER_ENTRYPOINT="[\"/bin/bash\", \"-c\", \"source user_params.$EXT && $ENTRYPOINT\"]"
fi
if [[ $SOLUM_PARAMS != null ]]; then
  cp $SOLUM_PARAMS $APP_DIR/code/solum_params.$EXT
fi

echo "$GIT_PRIVATE_KEY" > $APP_DIR/code/id_rsa
# Test the application code
TLOG "===>" Testing App

if [[ $USE_DRONE != null && $(type drone) ]]; then
  TLOG "===>" Using Drone
  if [[ ! -e $APP_DIR/code/.drone.yml ]]; then
    TLOG "===>" Creating .drone.yml
    cat << EOF > $APP_DIR/code/.drone.yml
image: $BASE_IMG
script:
- $DRONE_ENTRYPOINT
EOF
  else
    TLOG "===>" .drone.yml found in source
  fi
  sudo /usr/local/bin/drone build $APP_DIR/code 2>&1 > >(while read LINE; do TLOG $LINE; done)
else
  TLOG Creating Dockerfile
  cat << EOF > $APP_DIR/Dockerfile
FROM $BASE_IMG
COPY code /code
COPY code/id_rsa /root/.ssh/id_rsa
RUN chmod 0600 /root/.ssh/id_rsa
RUN echo "Host *\n\tStrictHostKeyChecking no\n\tUserKnownHostsFile=/dev/null" > /root/.ssh/config
WORKDIR /code
RUN ${DOCKER_ENTRYPOINT}
EOF

  cd $APP_DIR
  echo "code/.git" > .dockerignore
  sudo docker build --force-rm=true -t $RANDOM_NAME . 2>&1 > >(while read LINE; do TLOG $LINE; done)
fi

SUCCESS=$?
echo Docker finished with status $SUCCESS.

if [[ $SUCCESS == 0 ]]; then
TLOG ==== Status: SUCCESS
else
TLOG ==== Status: FAIL
fi

TOTAL_TIME=$(elapsed $SCRIPT_START_TIME)
TLOG ===== Total elapsed time: $TOTAL_TIME sec

# Return 0 if the tests went well, or 1 otherwise.
[[ $SUCCESS = 0 ]] && exit 0 || exit 1
