#!/bin/bash

if [[ "$1" == "--help" ]]; then
    echo USAGE: [OPTIONS] ansible-test PLAYBOOK [TAGS]
    echo  OPTIONS:
    echo "  - image: The testing container to use, e.g. ubuntu1804,centos7,ubuntu1604,debian9 (default = centos7)"
    echo "  - cleanup: whether to remove the Docker container (default = true)"
    echo "  - container_id: the docker --name to set for the container (default = timestamp)"
    echo "  - test_idempotence: whether to test playbooks idempotence (default = true)"
    echo "  - image: The testing container to use (default = moshloop//docker-centos7-ansible)"
    exit 0
fi

# Exit on any individual command failure.
set -e

# Pretty colors.
red="\033[38;5;196m"
green="\033[38;5;46m"
neutral='\033[0m'
timestamp=$(date +%s)
image=${image:-"moshloop/docker-centos7-ansible"}
entrypoint=""

if [[ "$image" != *"/"* ]]; then
  image="moshloop/docker-$image-ansible"
fi

if [[ "$image" == "moshloop/docker-ubuntu1804-ansible" ]]; then
    entrypoint="/lib/systemd/systemd"
fi

get_args() {
  ARGS="--privileged -w $PWD -v $PWD:$PWD"
  # passthrough AWS variables
  for ARG in $(compgen -e); do
      if [[ "$ARG" == "AWS_"* && "$ARG" == "ANSIBLE_"*  ]]; then
          ARGS+=" -e $ARG=${!ARG}"
      fi
  done
  if [[ -e ~/.aws ]]; then
      ARGS+=" -v $HOME/.aws:/root/.aws"
  fi

  if [[ -e ~/.ansible ]]; then
      ARGS+=" -v $HOME/.ansible:/root/.ansible"
  fi

  if [[ -e /work ]]; then
      ARGS+=" -v /work:/work "
  fi

  ARGS+=" --volume ssh:/ssh --env SSH_AUTH_SOCK=/ssh/auth/sock"

  if [[ -e /var/run/docker.sock ]];  then
      ARGS+=" -v /var/run/docker.sock:/var/run/docker.sock"
      ARGS+=" -v /var/run/docker.sock:/tmp/var/run/docker.sock"
      ARGS+=" -e DOCKER_HOST=unix:///tmp/var/run/docker.sock"
  fi

  echo $ARGS
}

playbook=${playbook:-$1}
tags=${2:-""}
if [ "$tags" == "" ]; then
  tags=all
fi
cleanup=${cleanup:-"true"}
timestamp=$(date +"%Y%m%dT%H%M%S")
container_id=${container_id:-$timestamp}
test_idempotence=${test_idempotence:-"true"}

printf ${green}"Starting $image in the background: ${neutral}"$container_id"\n"
echo docker run --detach --name $container_id $(get_args) $image $entrypoint
docker run --detach --name $container_id $(get_args) $image $entrypoint
EXEC="docker exec --tty $container_id env TERM=xterm "
PLAYBOOK="$EXEC ANSIBLE_FORCE_COLOR=1 ansible-playbook "


# extract and install role dependencies
if [[ -e "$PWD/meta/main.yml" ]]; then
  dependencies=$(cat $PWD/meta/main.yml | yq -cr .galaxy_info.dependencies)

  if [[ "$dependencies" != "null" ]]; then
    dependencies=$(echo $dependencies | jq -j '. | join(" ") ')
  fi
  if [[ "$dependencies" != "null"  ]]; then

  printf ${green}"Installing role dependencies: "${neutral}" $dependencies\n"
    $EXEC ansible-galaxy install $dependencies
  fi
fi


requirements=$(dirname "$PWD/$playbook")"/requirements.yml"
if [ -e "$requirements" ]; then
  printf ${green}"Innstalling dependencies from: "${neutral}" $requirements \n"
  $EXEC ansible-galaxy install -rc  $PWD/tests/requirements.yml
fi

printf "\n"

if [[ "$1" == "" ]]; then
    # docker exec sometimes messes up the terminal dimensions so we need to record and pass them through
  width=$(stty size | cut -d" " -f2)
  height=$(stty size | cut -d" " -f1)
  tty_opts=$(stty -g)
  ARGS=" -e tty_width=$width -e tty_height=$height -e tty_opts=$tty_opts -e cid=$container_id"
  docker exec  $ARGS -it $container_id  bash -c "cd $PWD; bash"
  exit 0
fi

printf ${green}"Checking Ansible playbook syntax: "${neutral}
printf "$PLAYBOOK $pwd/$playbook --syntax-check"
$PLAYBOOK $PWD/$playbook --syntax-check

printf "\n"

printf ${green}"Running command: ${neutral} $PLAYBOOK $PWD/$playbook"
$PLAYBOOK $PWD/$playbook -t $tags

if [[ -e ${playbook%.*}.rb ]]; then
  $EXEC inspec exec $PWD/${playbook%.*}.rb  --reporter=cli junit:$PWD/junit.xml
fi

if [[ -e ${playbook%.*}.bats ]]; then
  $EXEC bats $PWD/${playbook%.*}.bats
fi

if [ "$test_idempotence" = true ]; then
  # Run Ansible playbook again (idempotence test).
  printf ${green}"Running idempotence test"${neutral}
  idempotence=$(mktemp)
  $PLAYBOOK $PWD/$playbook | tee -a $idempotence
  tail $idempotence \
    | grep -q 'changed=0.*failed=0' \
    && (printf "Idempotence test: ${green}pass"${neutral}"\n") \
    || (printf "Idempotence test: ${red}fail"${neutral}"\n" && exit 1)
fi

# Remove the Docker container (if configured).
if [ "$cleanup" = true ]; then
  printf "Removing Docker container...\n"
  docker rm -f $container_id
fi