#!/bin/bash

exname=$(basename $0)

compose_core=$(which compose-core) || {
    echo "Requires compose-core executable to be in \$PATH." >&2
    exit 1
}

fetch-def() {
    local path="$1" fname="$2"
    ( . "$path" 1>&2 || {
          echo "Failed to load '$path'." >&2
          exit 1
      }
      declare -f "$fname"
    )
}

prefix_cmd="
. /etc/shlib

include common
include parse

. ../lib/common

$(fetch-def "$compose_core" yaml_get_values)
$(fetch-def "$compose_core" yaml_get_interpret)

" || {
    echo "Couldn't build prefix cmd" >&2
    exit 1
}


##
## Mocks
##

relation-get() {
    local key="$1"
    echo "$CFG" | shyaml get-value "$key" 2>/dev/null
}
export -f relation-get

export RELATION_DATA_FILE=x
relation-set() {
    local key="$1" value="$2"
    echo "relation-set $key:" >&2
    echo "$value" | prefix "  | " >&2
}
export -f relation-set

cfg-get-value() {
    local key="$1"
    shyaml get-value "$key" 2>/dev/null
}
export -f cfg-get-value

get_service_relations() {
    printf "%s\0" "${RELATIONS[@]}"
}
export -f get_service_relations

file_put() {
    echo "file_put $1"
    cat - | prefix "  | "
}
export -f file_put

docker() {
    echo "docker" "$@"
    echo stdin:
    cat - | prefix "  | "
}
export -f docker

config-add() {
    echo "config-add"
    echo "$1" | prefix "  | "
}
export -f config-add

init-config-add() {
    echo "init-config-add"
    echo "$1" | prefix "  | "
}
export -f init-config-add

mkdir() {
    echo "called: $FUNCNAME $@"  >&2
}
export -f mkdir

setfacl() {
    echo "called: $FUNCNAME $@" >&2
}
export -f setfacl

chgrp() {
    echo "called: $FUNCNAME $@" >&2
}
export -f chgrp

chmod() {
    echo "called: $FUNCNAME $@" >&2
}
export -f chmod

merge_yaml_str() {
    local arg_hash="$(H "$@" | cut -c -16)"
    local i
    echo "Calling: merge_yaml_str" >&2
    ((i=0))
    for arg in "$@"; do
        echo "  arg$((i++)):"
        echo "$arg" | prefix "  | "
    done >&2
    echo "  H> $arg_hash" >&2
    while read-0 h res; do
        if [[ "$arg_hash" == "$h" ]]; then
            echo "Mock hash matched, returning:" >&2
            echo "$res" | prefix "  | " >&2
            echo "$res"
            return 0
        fi
    done < <(e "$MERGE_YAML_STR" | shyaml key-values-0)
    printf "<merge_yaml_str("
    printf "'%s', " "$@"
    printf ")>"
}
export -f merge_yaml_str

yaml_get_interpret() {
    shyaml get-value
}
export -f yaml_get_interpret

yaml_key_val_str() {
    printf "%s: %s" "$1" "$2"
}
export -f yaml_key_val_str

cached_cmd_on_base_image() {
    echo "called: $FUNCNAME $@" >&2
    echo "stdout:" >&2
    echo "<GID>" | prefix " | " >&2
    echo "<GID>"
}
export -f cached_cmd_on_base_image


export state_tmpdir=$(mktemp -d -t tmp.XXXXXXXXXX)
trap "rm -rf \"$state_tmpdir\"" EXIT


##
## apache_vhost_create
##


try "
export SERVICE_CONFIGSTORE='\$SERVICE_CONFIGSTORE'
apache_vhost_create publish_dir '
domain: www.example.com
'"
is errlvl 0
is err part "\
relation-set url:
  | http://www.example.com"
is out reg '^file_put \$SERVICE_CONFIGSTORE/.*/www.example.com.conf'

try "
export SERVICE_CONFIGSTORE='\$SERVICE_CONFIGSTORE'
CFG='
domain: www.example.com
ssl: true
'
ADDITION='
apache-custom-rules:
  - |
    ## Auto-redirection from http to https
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L,QSA]'
MERGE_YAML_STR=\"
6b92a84e9d93e4a1: |
\$(echo \"\$CFG\" |  prefix '  ')
\$(echo \"\$ADDITION\" | prefix '  ')
\"
apache_vhost_create publish_dir \"\$CFG\"
"
is errlvl 0
is err part "## Auto-redirection from http to https"
is err part "\
relation-set url:
  | https://www.example.com"
is out reg '^file_put \$SERVICE_CONFIGSTORE/.*/www.example.com.conf'


try "
export SERVICE_CONFIGSTORE='\$SERVICE_CONFIGSTORE'
export CONFIGSTORE='\$CONFIGSTORE'
export BASE_SERVICE_NAME='\$BASE_SERVICE_NAME'
export MASTER_TARGET_SERVICE_NAME='\$MASTER_TARGET_SERVICE_NAME'
CFG='
domain: www.example.com
ssl:
  key: |
    a
    b
  cert: c
'
ADDITION='
apache-custom-rules:
  - |
    ## Auto-redirection from http to https
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L,QSA]'
MERGE_YAML_STR=\"
3b76349cfba9d3f2: |
\$(echo \"\$CFG\" |  prefix '  ')
\$(echo \"\$ADDITION\" | prefix '  ')
\"
apache_vhost_create publish_dir \"\$CFG\"
"
is errlvl 0
is err part "## Auto-redirection from http to https"
is err part "\
relation-set url:
  | https://www.example.com"
is out part 'file_put $CONFIGSTORE/$BASE_SERVICE_NAME/etc/ssl/certs/www.example.com.pem
  | c'
is out part 'file_put $CONFIGSTORE/$BASE_SERVICE_NAME/etc/ssl/private/www.example.com.key
  | a
  | b'
is out reg 'init-config-add'
is out reg ' - \$CONFIGSTORE/\$BASE_SERVICE_NAME/etc/ssl/certs/www.example.com.pem:/etc/ssl/certs/www.example.com.pem:ro'
is out reg ' - \$CONFIGSTORE/\$BASE_SERVICE_NAME/etc/ssl/private/www.example.com.key:/etc/ssl/private/www.example.com.key:ro'


try "
export DOCKER_BASE_IMAGE=docker/apache
export SERVICE_CONFIGSTORE='\$SERVICE_CONFIGSTORE'
export CONFIGSTORE='\$CONFIGSTORE'
export BASE_SERVICE_NAME='\$BASE_SERVICE_NAME'
export MASTER_TARGET_SERVICE_NAME='\$MASTER_TARGET_SERVICE_NAME'
CFG='
domain: www.example.com
creds:
  toto: xxx
'
apache_vhost_create publish_dir \"\$CFG\"
"
is errlvl 0
is err part "\
relation-set url:
  | http://www.example.com"
is out reg "htpasswd -bc '/etc/apache2/sites-enabled/www.example.com.passwd' 'toto' 'xxx'"
is out reg 'docker run -i --entrypoint /bin/bash .* docker/apache'


## XXXvlab: we don't need this feature anymore it seems
# try "
# export SERVICE_CONFIGSTORE='\$SERVICE_CONFIGSTORE'
# apache_vhost_create publish_dir '' ',http,' '000-default'"
# is errlvl 0
# is err part "\
# relation-set url:
#   | http://"    ## XXXvlab: this isn't right, is it ?
# is out reg '^file_put \$SERVICE_CONFIGSTORE/.*/000-default.conf'



##
## apache_publish_dir
##

try "
export DOCKER_BASE_IMAGE=docker/apache
export SERVICE_CONFIGSTORE='\$SERVICE_CONFIGSTORE'
export CONFIGSTORE='\$CONFIGSTORE'
export BASE_SERVICE_NAME='\$BASE_SERVICE_NAME'
export MASTER_TARGET_SERVICE_NAME='\$MASTER_TARGET_SERVICE_NAME'
apache_publish_dir '
creds:
  toto: xxx
'" "missing domain"
is errlvl 1  ## no domain


try "
export DATASTORE='\$DATASTORE'
export DOCKER_BASE_IMAGE=docker/apache
export SERVICE_CONFIGSTORE='\$SERVICE_CONFIGSTORE'
export CONFIGSTORE='\$CONFIGSTORE'
export BASE_SERVICE_NAME='\$BASE_SERVICE_NAME'
export MASTER_TARGET_SERVICE_NAME='\$MASTER_TARGET_SERVICE_NAME'
apache_publish_dir '
domain: www.example.com
creds:
  toto: xxx
'
"
is errlvl 0
is err reg 'setfacl -R -m g:<GID>:rx \$DATASTORE/\$BASE_SERVICE_NAME/var/www/www.example.com'
is err reg 'cached_cmd_on_base_image apache id -g www-data'


try "
export DATASTORE='\$DATASTORE'
export DOCKER_BASE_IMAGE=docker/apache
export SERVICE_CONFIGSTORE='\$SERVICE_CONFIGSTORE'
export CONFIGSTORE='\$CONFIGSTORE'
export BASE_SERVICE_NAME='\$BASE_SERVICE_NAME'
export MASTER_TARGET_SERVICE_NAME='\$MASTER_TARGET_SERVICE_NAME'
apache_publish_dir '
domain: www.example.com
creds:
  toto: xxx
data-dirs:
- a
- b
- c
'
"
is errlvl 0
is err reg 'setfacl -R -m g:<GID>:rwx \$DATASTORE/\$BASE_SERVICE_NAME/var/www/www.example.com/a \$DATASTORE/\$BASE_SERVICE_NAME/var/www/www.example.com/b \$DATASTORE/\$BASE_SERVICE_NAME/var/www/www.example.com/c'
is err reg 'setfacl -R -d -m g:<GID>:rwx \$DATASTORE/\$BASE_SERVICE_NAME/var/www/www.example.com/a \$DATASTORE/\$BASE_SERVICE_NAME/var/www/www.example.com/b \$DATASTORE/\$BASE_SERVICE_NAME/var/www/www.example.com/c'


try "
export DATASTORE='\$DATASTORE'
export DOCKER_BASE_IMAGE=docker/apache
export SERVICE_CONFIGSTORE='\$SERVICE_CONFIGSTORE'
export CONFIGSTORE='\$CONFIGSTORE'
export SERVICE_NAME='\$SERVICE_NAME'
export BASE_SERVICE_NAME='\$BASE_SERVICE_NAME'
export MASTER_BASE_SERVICE_NAME='\$MASTER_BASE_SERVICE_NAME'
export MASTER_TARGET_SERVICE_NAME='\$MASTER_TARGET_SERVICE_NAME'
apache_publish_dir '
domain: www.example.com
location: /opt/apps/newlocation
creds:
  toto: xxx
data-dirs:
- a
- b
- c
'
"
is errlvl 0
is err reg 'mkdir -p /opt/apps/newlocation'
is err reg 'setfacl -R -m g:<GID>:rx /opt/apps/newlocation'
is out part '
init-config-add
  |
  | $SERVICE_NAME:
  |   volumes:
  |     - /opt/apps/newlocation:/var/www/www.example.com' RTRIM




try "
export DATASTORE='\$DATASTORE'
export DOCKER_BASE_IMAGE=docker/apache
export SERVICE_CONFIGSTORE='\$SERVICE_CONFIGSTORE'
export CONFIGSTORE='\$CONFIGSTORE'
export BASE_SERVICE_NAME='\$BASE_SERVICE_NAME'
export MASTER_BASE_SERVICE_NAME='\$MASTER_BASE_SERVICE_NAME'
export MASTER_TARGET_SERVICE_NAME='\$MASTER_TARGET_SERVICE_NAME'
apache_ssh_tunnel '
domain: www.example.com
creds:
  toto: xxx
'
" "ssh tunnel without ssl"
is errlvl 1
is err 'Error: ssl must be valued in ssh-tunnel config.
'
is out ''


try "
export DATASTORE='\$DATASTORE'
export DOCKER_BASE_IMAGE=docker/apache
export SERVICE_CONFIGSTORE='\$SERVICE_CONFIGSTORE'
export CONFIGSTORE='\$CONFIGSTORE'
export BASE_SERVICE_NAME='\$BASE_SERVICE_NAME'
export MASTER_BASE_SERVICE_NAME='\$MASTER_BASE_SERVICE_NAME'
export MASTER_TARGET_SERVICE_NAME='\$MASTER_TARGET_SERVICE_NAME'
apache_ssh_tunnel '
ssl: true
creds:
  toto: xxx
'
" "ssh tunnel without domain"
is errlvl 1
is err 'Error: domain must be valued in ssh-tunnel config.
'
is out ''


try "
export DATASTORE='\$DATASTORE'
export DOCKER_BASE_IMAGE=docker/apache
export SERVICE_CONFIGSTORE='\$SERVICE_CONFIGSTORE'
export CONFIGSTORE='\$CONFIGSTORE'
export BASE_SERVICE_NAME='\$BASE_SERVICE_NAME'
export MASTER_BASE_SERVICE_NAME='\$MASTER_BASE_SERVICE_NAME'
export MASTER_TARGET_SERVICE_NAME='\$MASTER_TARGET_SERVICE_NAME'
apache_ssh_tunnel '
domain: ssh.example.com
ssl:
  key: a
  ca-cert: b
creds:
  toto: xxx
'
" "ssh tunnel"
is errlvl 0
is err reg 'relation-set domain:
  | ssh.example.com'
is out reg 'file_put \$SERVICE_CONFIGSTORE/etc/apache2/sites-enabled/000-ssh.example.com.conf'
is out reg 'file_put \$CONFIGSTORE/\$BASE_SERVICE_NAME/etc/ssl/private/ssh.example.com.key'
is out reg 'file_put \$CONFIGSTORE/\$BASE_SERVICE_NAME/etc/ssl/certs/ssh.example.com-ca.pem'
is out reg 'AuthUserFile /etc/apache2/sites-enabled/ssh.example.com.passwd'
is out reg "htpasswd -bc '/etc/apache2/sites-enabled/000-ssh.example.com.passwd' 'toto' 'xxx'"