#!/bin/sh
#
# 2015 Steven Armstrong (steven-cdist at armstrong.cc)
# 2015 Nico Schottelius (nico-cdist at schottelius.org)
#
# This file is part of cdist.
#
# cdist is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# cdist is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with cdist. If not, see <http://www.gnu.org/licenses/>.
#


os=$(cat "$__global/explorer/os")

case "$os" in
   centos|debian|redhat|ubuntu)
      # whitelist safeguard
      :
   ;;
   *)
      echo "Your operating system ($os) is currently not supported by this type (${__type##*/})." >&2
      echo "Please contribute an implementation for it if you can." >&2
      exit 1
   ;;
esac

state="$(cat "$__object/parameter/state")"
user="$(cat "$__object/parameter/user")"
group="$(cat "$__object/parameter/group")"
data_dir="/var/lib/consul"
conf_dir="/etc/consul/conf.d"
conf_file="config.json"

# FIXME: there has got to be a better way to handle the dependencies in this case
case "$state" in
   present)
      __group "$group" --system --state "$state"
      require="__group/$group" \
         __user "$user" --system --gid "$group" \
            --home "$data_dir" --state "$state"
      export require="__user/consul"
   ;;
   absent)
      echo "Sorry, state=absent currently not supported :-(" >&2
      exit 1
      require="$__object_name" \
         __user "$user" --system --gid "$group" --state "$state"
      require="__user/$user" \
         __group "$group" --system --state "$state"
   ;;
esac

__directory /etc/consul \
   --owner root --group "$group" --mode 750 --state "$state"
require="__directory/etc/consul" \
   __directory "$conf_dir" \
      --owner root --group "$group" --mode 750 --state "$state"

if [ -f "$__object/parameter/ca-file-source" -o -f "$__object/parameter/cert-file-source" -o -f "$__object/parameter/key-file-source" ]; then
   # create directory for ssl certs
   require="__directory/etc/consul" \
      __directory /etc/consul/ssl \
         --owner root --group "$group" --mode 750 --state "$state"
fi

__directory "$data_dir" \
   --owner "$user" --group "$group" --mode 770 --state "$state"


# Generate json config file
(
echo "{"

# parameters we define ourself
printf '   "data_dir": "%s"\n' "$data_dir"

for param in $(ls "$__object/parameter/"); do
   case "$param" in
      state|user|group|json-config) continue ;;
      ca-file-source|cert-file-source|key-file-source)
         source="$(cat "$__object/parameter/$param")"
         destination="/etc/consul/ssl/${source##*/}"
         require="__directory/etc/consul/ssl" \
            __file "$destination" \
               --owner root --group consul --mode 640 \
               --source "$source" \
               --state "$state"
         key="$(echo "${param%-*}" | tr '-' '_')"
         printf '   ,"%s": "%s"\n' "$key" "$destination"
      ;;
      disable-remote-exec|disable-update-check|leave-on-terminate|rejoin-after-leave|server|syslog|verify-incoming|verify-outgoing)
         # handle boolean parameters
         key="$(echo "$param" | tr '-' '_')"
         printf '   ,"%s": true\n' "$key"
      ;;
      retry-join)
         # join multiple parameters into json array
         retry_join="$(awk '{printf "\""$1"\","}' "$__object/parameter/retry-join")"
         # remove trailing ,
         printf '   ,"retry_join": [%s]\n' "${retry_join%*,}"
      ;;
      retry-join-wan)
         # join multiple parameters into json array over wan
         retry_join_wan="$(awk '{printf "\""$1"\","}' "$__object/parameter/retry-join-wan")"
         # remove trailing ,
         printf '   ,"retry_join_wan": [%s]\n' "${retry_join_wan%*,}"
      ;;
      bootstrap-expect)
         # integer key=value parameters
         key="$(echo "$param" | tr '-' '_')"
         printf '   ,"%s": %s\n' "$key" "$(cat "$__object/parameter/$param")"
      ;;
      *)
         # string key=value parameters
         key="$(echo "$param" | tr '-' '_')"
         printf '   ,"%s": "%s"\n' "$key" "$(cat "$__object/parameter/$param")"
      ;;
   esac
done
if [ -f "$__object/parameter/json-config" ]; then
   json_config="$(cat "$__object/parameter/json-config")"
   if [ "$json_config" = "-" ]; then
      json_config="$__object/stdin"
   fi
   # remove leading and trailing whitespace and commas from first and last line
   # indent each line with 3 spaces for consistency
   json=$(sed -e 's/^[ \t]*/   /' -e '1s/^[ \t,]*//' -e '$s/[ \t,]*$//' "$json_config")
   printf '   ,%s\n' "$json"
fi
echo "}"
) | \
require="__directory${conf_dir}" \
   __config_file "${conf_dir}/${conf_file}" \
      --owner root --group "$group" --mode 640 \
      --state "$state" \
      --onchange 'service consul status >/dev/null && service consul reload || true' \
      --source -

init_sysvinit()
{
    __file /etc/init.d/consul \
        --owner root --group root --mode 0755 \
        --state "$state" \
        --source "$__type/files/consul.sysv-$1"
    require="__file/etc/init.d/consul" __start_on_boot consul
}

init_systemd()
{
    __file /lib/systemd/system/consul.service \
        --owner root --group root --mode 0644 \
        --state "$state" \
        --source "$__type/files/consul.systemd"
        require="__file/lib/systemd/system/consul.service" __start_on_boot consul
}

init_upstart()
{
    __file /etc/init/consul-prepare.conf \
        --owner root --group root --mode 0644 \
        --state "$state" \
        --source "$__type/files/consul-prepare.upstart"
    require="__file/etc/init/consul-prepare.conf" \
        __file /etc/init/consul.conf \
            --owner root --group root --mode 0644 \
            --state "$state" \
            --source "$__type/files/consul.upstart"
    require="__file/etc/init/consul.conf" __start_on_boot consul
}

# Install init script to start on boot
case "$os" in
   centos|redhat)
      os_version="$(sed 's/[^0-9.]//g' "$__global/explorer/os_version")"
      major_version="${os_version%%.*}"
      case "$major_version" in
         [456])
            init_sysvinit redhat
         ;;
         7)
            init_systemd
         ;;
         *)
            echo "Unsupported CentOS/Redhat version: $os_version" >&2
            exit 1
         ;;
      esac
   ;;

    debian)
        os_version=$(cat "$__global/explorer/os_version")
        major_version="${os_version%%.*}"

        case "$major_version" in
            [567])
                init_sysvinit debian
            ;;
            8)
                init_systemd
            ;;
            *)
                echo "Unsupported Debian version $os_version" >&2
                exit 1
            ;;
        esac
    ;;

   ubuntu)
      init_upstart
   ;;
esac
