#!/usr/bin/env bash

# Perform integration tests on the modules
# To keep retrying a failing test, you can set the following environment variables.
# This is mainly intended for CI use.
#   TEST_RETRIES=<num> - Number of times to try the test. Default: 1
#   TEST_RETRY_DELAY=<num> - Number of seconds to wait between failing test runs. Default: 300 (5min)

set -eu
set -o pipefail

SCRIPT_DIRECTORY=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
# shellcheck disable=1091
source "$SCRIPT_DIRECTORY/constants.sh"
# shellcheck disable=1091
source "$SCRIPT_DIRECTORY/util.sh"

TEST_RETRIES="${TEST_RETRIES:-1}"
TEST_RETRY_DELAY="${TEST_RETRY_DELAY:-300}"

# Docker settings
export STEP_PODMAN_NETWORK="step-ansible-modules"

# Remote CA settings
export STEP_REMOTE_CA_CT_NAME="step-ca"
export STEP_REMOTE_CA_PROVISIONER_NAME="ansible"
export STEP_REMOTE_CA_PROVISIONER_PASSWORD="ansible-module-tests-pw"
export STEP_REMOTE_CA_URL="https://$STEP_REMOTE_CA_CT_NAME:9000"
# FP can only evaluated when the remote docker ct is running
export STEP_REMOTE_CA_FP=""

# Local CA settings
export STEP_LOCAL_CA_USER=step
export STEP_LOCAL_CLI_BINARY=step
export STEP_LOCAL_STEPPATH=/home/step # hardcoded in Dockerfile

LOCAL_CA_TAG=local-ca

# Cleanup function to delete any docker objects that we might have created
cleanup() {
    echo "Cleaning up..."
    set +e # cleanup, we don't care if some stuff doesn't exist
    podman rm -f "$STEP_REMOTE_CA_CT_NAME" > /dev/null
    podman network rm "$STEP_PODMAN_NETWORK" > /dev/null
    echo "Done"
    set -e
    exit
}
trap cleanup INT ERR EXIT

prepare() {
    podman network create $STEP_PODMAN_NETWORK
}

render_config() {
    # The test config contains parameters that the module targets use to connect to the local/remote ca respectively.
    # We render out this config right before starting a integration test
    echo "Rendering configuration"
    tests/integration/render_config.sh tests/integration/integration_config.yml.template > tests/integration/integration_config.yml
}

remote_ca() {
    echo "Starting remote CA container"
    # CircleCIs systemd session is, in some way, misconfigured and that causes some issues with podman and cgroups
    # Instead of fixing it, we can just fallback to cgroupfs
    # See: https://github.com/containers/podman/issues/16529
    retry "$TEST_RETRIES" "$TEST_RETRY_DELAY" podman run --cgroup-manager=cgroupfs -d \
        --name $STEP_REMOTE_CA_CT_NAME --network $STEP_PODMAN_NETWORK \
        -e "DOCKER_STEPCA_INIT_NAME=Ansible-Test" \
        -e "DOCKER_STEPCA_INIT_DNS_NAMES=localhost,$STEP_REMOTE_CA_CT_NAME" \
        -e "DOCKER_STEPCA_INIT_PROVISIONER_NAME=$STEP_REMOTE_CA_PROVISIONER_NAME" \
        -e "DOCKER_STEPCA_INIT_PASSWORD=$STEP_REMOTE_CA_PROVISIONER_PASSWORD" \
        "docker.io/smallstep/step-ca:$STEP_CA_VERSION"


    # Give the CA a little bit to initialize
    echo "Waiting for CA to come online"
    # TODO: Check the container status with docker instead of exec-ing
    timeout 20 bash -c "while ! podman exec $STEP_REMOTE_CA_CT_NAME step ca health &> /dev/null; do sleep 1; done"

    STEP_REMOTE_CA_FP=$(podman exec $STEP_REMOTE_CA_CT_NAME step certificate fingerprint certs/root_ca.crt)
    export STEP_REMOTE_CA_FP

    render_config

    retry "$TEST_RETRIES" "$TEST_RETRY_DELAY" tox -e integration -- \
        --color -v \
        --controller docker:default --target docker:default,python=3.6 \
        --docker-network $STEP_PODMAN_NETWORK  \
        --skip-tags $LOCAL_CA_TAG \
        --docker-terminate=always `#Change this if you want to debug test targets`
}

local_ca() {
    local image_name="step-ca-ansible"

    echo "Building docker image for local-ca test targets: $image_name with step-ca version $STEP_CA_VERSION"
    # CircleCIs systemd session is, in some way, misconfigured and that causes some issues with podman and cgroups
    # Instead of fixing it, we can just fallback to cgroupfs
    # See: https://github.com/containers/podman/issues/16529
    retry "$TEST_RETRIES" "$TEST_RETRY_DELAY" podman build --cgroup-manager=cgroupfs tests/integration/docker/step-ca-ansible -t $image_name \
        --build-arg "STEP_CA_VERSION=$STEP_CA_VERSION" \
        --build-arg "PYTHON_VERSION=$PYTHON_VERSION" \
        --build-arg "STEP_CA_USER=$STEP_LOCAL_CA_USER"

    render_config

    retry "$TEST_RETRIES" "$TEST_RETRY_DELAY" tox -e integration -- \
        --color -v \
        --controller docker:default --target "docker:$image_name,python=$PYTHON_VERSION@/usr/local/bin/python3" \
        --docker-network $STEP_PODMAN_NETWORK  \
        --tags $LOCAL_CA_TAG \
        --docker-terminate=always `#Change this if you want to debug test targets`
}

main() {
    prepare
    local_ca
    remote_ca
    cleanup
}

main "$@"
