#!/usr/bin/env bash

PORTAINER_USER=${PORTAINER_USER:-"user"}
PORTAINER_PASSWORD=${PORTAINER_PASSWORD:-"password"}
PORTAINER_URL=${PORTAINER_URL:-"https://portainer.example.com"}
PORTAINER_PRUNE=${PORTAINER_PRUNE:-"false"}
PORTAINER_ENDPOINT=${PORTAINER_ENDPOINT:-"1"}
HTTPIE_VERIFY_SSL=${HTTPIE_VERIFY_SSL:-"yes"}

if [ -z ${1+x} ]; then
  echo "Error: Parameter #1 missing (stack name)"
  exit 1
fi
STACK_NAME="$1"

if [ -z ${2+x} ]; then
  echo "Error: Parameter #2 missing (path to yaml)"
  exit 1
fi
STACK_YAML_PATH="$2"

STACK_YAML_CONTENT=$(cat "$STACK_YAML_PATH")

# Escape carriage returns
STACK_YAML_CONTENT="${STACK_YAML_CONTENT//$'\r'/''}"

# Escape double quotes
STACK_YAML_CONTENT="${STACK_YAML_CONTENT//$'"'/'\"'}"

# Escape newlines
STACK_YAML_CONTENT="${STACK_YAML_CONTENT//$'\n'/'\n'}"

echo "Getting auth token..."
AUTH_TOKEN=$(http \
  --ignore-stdin \
  --verify=$HTTPIE_VERIFY_SSL \
  $PORTAINER_URL/api/auth \
  username=$PORTAINER_USER \
  password=$PORTAINER_PASSWORD \
  | jq -r .jwt)

if [ -z "$AUTH_TOKEN" ]; then
  echo "Error: Authentication error."
  exit 1
fi
echo "Done"

echo "Getting stack $STACK_NAME..."
STACKS=$(http \
  --ignore-stdin \
  --verify=$HTTPIE_VERIFY_SSL \
  "$PORTAINER_URL/api/stacks" \
  "Authorization: Bearer $AUTH_TOKEN")

STACK=$(echo "$STACKS" \
  | jq --arg STACK_NAME "$STACK_NAME" -jc '.[] | select(.Name == $STACK_NAME)')

if [ -z "$STACK" ]; then
  echo "Result: Stack $STACK_NAME not found."

  echo "Getting swarm cluster (if any)..."
  SWARM_ID=$(http \
    --ignore-stdin \
    --verify=$HTTPIE_VERIFY_SSL \
    "$PORTAINER_URL/api/endpoints/$PORTAINER_ENDPOINT/docker/info" \
    "Authorization: Bearer $AUTH_TOKEN" \
    | jq -r ".Swarm.Cluster.ID // empty")
  
  echo "Creating stack $STACK_NAME..."
  if [ -z "$SWARM_ID" ];then
    DATA_PREFIX="{\"Name\":\"$STACK_NAME\",\"StackFileContent\":\""
    DATA_SUFFIX="\"}"
    echo "$DATA_PREFIX$STACK_YAML_CONTENT$DATA_SUFFIX" > json.tmp

    CREATE=$(http \
      --ignore-stdin \
      --verify=$HTTPIE_VERIFY_SSL \
      --timeout=300 \
      "$PORTAINER_URL/api/stacks" \
      "Authorization: Bearer $AUTH_TOKEN" \
      type==2 \
      method==string \
      endpointId==$PORTAINER_ENDPOINT \
      @json.tmp)
  else
  	DATA_PREFIX="{\"Name\":\"$STACK_NAME\",\"SwarmID\":\"$SWARM_ID\",\"StackFileContent\":\""
    DATA_SUFFIX="\"}"
    echo "$DATA_PREFIX$STACK_YAML_CONTENT$DATA_SUFFIX" > json.tmp

    CREATE=$(http \
      --ignore-stdin \
      --verify=$HTTPIE_VERIFY_SSL \
      --timeout=300 \
      "$PORTAINER_URL/api/stacks" \
      "Authorization: Bearer $AUTH_TOKEN" \
      type==1 \
      method==string \
      endpointId==$PORTAINER_ENDPOINT \
      @json.tmp)
  fi

  rm json.tmp

  if [ -z ${CREATE+x} ]; then
    echo "Error: stack $STACK_NAME not created"
    exit 1
  fi
else
  echo "Result: Stack $STACK_NAME found."

  STACK_ID="$(echo "$STACK" | jq -j ".Id")"
  STACK_ENV_VARS="$(echo -n "$STACK"| jq ".Env" -jc)"
  DATA_PREFIX="{\"Id\":\"$STACK_ID\",\"StackFileContent\":\""
  DATA_SUFFIX="\",\"Env\":"$STACK_ENV_VARS",\"Prune\":$PORTAINER_PRUNE}"
  echo "$DATA_PREFIX$STACK_YAML_CONTENT$DATA_SUFFIX" > json.tmp
  
  echo "Updating stack $STACK_NAME..."
  UPDATE=$(http \
    --ignore-stdin \
    --verify=$HTTPIE_VERIFY_SSL \
    --timeout=300 \
    PUT "$PORTAINER_URL/api/stacks/$STACK_ID" \
    "Authorization: Bearer $AUTH_TOKEN" \
    endpointId==$PORTAINER_ENDPOINT \
    @json.tmp)
  
  rm json.tmp
  
  if [ -z ${UPDATE+x} ]; then
    echo "Error: stack $STACK_NAME not updated"
    exit 1
  fi
fi
echo "Done"