#!/bin/bash -e

file=
if test -e "${!#}"; then
    for var in $(sed -n 's,^ *# \+\(-p\|--pwd\) \+\([a-zA-Z][a-zA-Z0-9_]*\),\2,p' "${!#}"); do
        export ${var}=$(pwgen 40 1)
    done
fi

while test $# -gt 0; do
    case "$1" in
        (-h|--help) if test -e "${!#}"; then
                        sed -n 's,^ *# \( *[^-]\),\1,p' "${!#}"
                        cat <<EOF
$0 $(sed -n 's,^ *# \+-,-,p' "${!#}" | tr '\n' ' ') ${!#}
EOF
                    else
                        cat <<EOF
$0 [OPTIONS] FILE

OPTIONS

  -h, --help             Show this help

  -h, --help file        Show usage of template file (if documented)

  -v, --var  name=value  Set environment variable to be used in the template.

  -p, --pwd name         Generate a random password with the given name.
                         If a password is documented, then it does not
                         need to be specified. But automated
                         generation can be overwritten assigning a
                         value using option -v.

FILE

  A template file. In the template file, you may use bash variables
  and execute bash commands, e.g. you are allowed wo use the \$()
  expression.

  Document the template and the parameters that in comment
  lines. Comment lines that start with a hash and a space ("# "). If
  a dash ("-") follows, then this line documents a parameter.

  Example:

    # this is an arbitrary documentation line that is copied
    # these are the parameters:
    # 
    #  -v VAR1=
    #  -v VAR2=
    #  -p PWD1
    #  -p PWD2

DESCRIPTION

  Parse a template file and generate an instance for it, using the
  environment variables nd the given parameters. The use of
  environment variables and command line option --var is equivalent.

EXAMPLE

  file wordpress.tpl
-----------------------------------------------------------------------------
# this templeate starts a wordpress given an name and a port
#  -v NAME=
#  -v PORT=
#  -p PASSWORD
version: '3.3'
services:
  mysql:
    image: mysql
    volumes:
      - type: bind
        source: /var/volumes/\${NAME}/mysql
        target: /var/lib/mysql
    environment:
      - 'MYSQL_DATABASE=wordpress'
      - 'MYSQL_USER=wordpress'
      - 'MYSQL_PASSWORD=\${PASSWORD}'
      - 'MYSQL_ROOT_PASSWORD=\$(pwgen 40 1)'
    deploy:
      placement:
        constraints:
          - node.labels.location == ug
  wordpress:
    image: wordpress
    ports:
      - \${PORT}:80
    volumes:
      - type: bind
        source: /var/volumes/\${NAME}/wordpress
        target: /var/www/html
    environment:
      - 'WORDPRESS_DB_HOST=mysql'
      - 'WORDPRESS_DB_NAME=wordpress'
      - 'WORDPRESS_DB_USER=wordpress'
      - 'WORDPRESS_DB_PASSWORD=\${PASSWORD}'
    deploy:
      placement:
        constraints:
          - node.labels.location == ug
-----------------------------------------------------------------------------

  create instance from template:

  $0 -v NAME=my-site -v PORT=8006 -p PASSWORD wordpress.tpl > my-site.yaml

EOF
                    fi
                    exit;;
        (-v|--var) shift;
                   if [[ $1 =~ ^[a-zA-Z][a-zA-Z0-9_]*= ]]; then
                       export $1
                   else
                       echo "ERROR not a variable assignment: $1" 1>&2
                       echo " see: $0 --help" 1>&2
                       exit 1
                   fi;;
        (-p|--pwd) shift;
                   if [[ $1 =~ ^[a-zA-Z][a-zA-Z0-9_]*$ ]]; then
                       export $1=$(pwgen 40 1)
                   else
                       echo "ERROR not a variable name: $1" 1>&2
                       echo " see: $0 --help" 1>&2
                       exit 1
                   fi;;
        (*) if test $# -ne 1 -o ! -e "$1"; then
                echo "ERROR please specify exactly one template file" 1>&2
                echo " this not one template file: $*" 1>&2
                echo " see: $0 --help" 1>&2
                exit 1
            fi
            file="$1";
    esac
    if test $# -lt 1; then
        echo "ERROR too few arguments" 1>&2
        echo " see: $0 --help" 1>&2
        exit 1
    fi
    shift
done

if ! test -e "$file"; then
    echo "ERROR please specify a template file" 1>&2
    echo " see: $0 --help" 1>&2
    exit 1
fi

eval "sed '/^ *#/d' <<EOFXXXX
$(<$file)
EOFXXXX"
