#!/bin/bash

# debops-init: create a new DebOps project
# Copyright (C) 2014 Nick Janetakis <nick.janetakis@gmail.com>
# Part of the DebOps project - http://debops.org/

set -e

# ---- Global constants ----

declare -r DEBOPS_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}/debops"
declare -r DEBOPS_CONFIG=".debops.cfg"
declare -r DEBOPS_INVENTORY="inventory"
declare -r SCRIPT_NAME="$(basename ${0})"
declare -r SECRET_SUFFIX=".secret"


# ---- Configuration variables ----

NEW_INVENTORY="ansible/${DEBOPS_INVENTORY}"

SKEL_DIRS=(
  "ansible/${DEBOPS_INVENTORY}/group_vars/all"
  "ansible/${DEBOPS_INVENTORY}/host_vars"
  "ansible/playbooks"
)


# ---- Functions ----

# Find specified file or directory in parent dir (if not specified, finds $DEBOPS_CONFIG)
# Source: https://unix.stackexchange.com/questions/13464
find_up () {
  local name=${1:-$DEBOPS_CONFIG}
  local slashes="${PWD//[^\/]/}"
  local directory="${PWD}"

  for (( n=${#slashes}; n>0; --n )) ; do
    test -e "${directory}/${name}" && echo "$(readlink -f ${directory}/${name})" && return
    directory="$directory/.."
  done
}

# Display error message and exit
error_msg () {
  local severity="${2:-Error}"
  local message="${1}"

  echo >&2 "${SCRIPT_NAME}: ${severity}: ${message}"
  set +e
  [[ "${severity}" == "Error" ]] && exit 1
  set -e
}

# Check if required commands exist
require_commands () {
  for name in ${@} ; do
    if ! type ${name} > /dev/null 2>&1 ; then
      error_msg "${name}: command not found"
    fi
  done
}


# ---- DebOps environment setup ----

# Specify name of new project directory
project="${1:-$PWD}"

# Find DebOps configuration file
debops_config="$(find_up)"

# Check if project dir already exists
new_project="$(find_up ${project})"

# Find root of the DebOps project dir
[ -n "${debops_config}" ] && debops_root="$(dirname ${debops_config})"

# Exit if we are in a DebOps project dir and nested project would be created
if [ -n "${debops_root}" ] ; then
  if [ "${debops_root}" = "${new_project}" ] ; then
    error_msg "You are inside ${new_project} project already"
  else
    [ -z "${project}" ] && error_msg "Cannot create nested project in ${debops_root}"
  fi
fi

# Exit if DebOps configuration file has been found
[ -r "${project}/${DEBOPS_CONFIG}" ] && error_msg "${project} is already a DebOps project"


# ---- Main script ----

echo "Creating new DebOps project in ${project} ..."

# Create base project directories
for skel_dir in "${SKEL_DIRS[@]}" ; do
  if [ ! -d ${project}/${skel_dir} ] ; then
    mkdir -p ${project}/${skel_dir}
  fi
done

# Create .debops.cfg
cat <<EOF > ${project}/${DEBOPS_CONFIG}
EOF

# Create .gitignore
cat <<EOF > ${project}/.gitignore
ansible/${DEBOPS_INVENTORY}${SECRET_SUFFIX}
${DEBOPS_INVENTORY}${SECRET_SUFFIX}


# Created by http://www.gitignore.io

### vim ###
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
*.un~
Session.vim
.netrwhist
*~


### Emacs ###
# -*- mode: gitignore; -*-
\#*\#
/.emacs.desktop
/.emacs.desktop.lock
*.elc
auto-save-list
tramp
.\#*


### SublimeText ###
# workspace files are user-specific
*.sublime-workspace

# project files should be checked into the repository, unless a significant
# proportion of contributors will probably not be using SublimeText
# *.sublime-project

#sftp configuration file
sftp-config.json

EOF

# Swap in different hosts file content depending on the host's OS/distro
valid_debops_controller=0
hosts_file="${project}/${NEW_INVENTORY}/hosts"

if [ $(uname) = "Linux" ]; then
  distro=$(lsb_release -si)
  if [ "${distro}" = "Debian" -o "${distro}" = "Ubuntu" ]; then
    valid_debops_controller=1
  fi
fi

cat <<EOF > ${hosts_file}
# This is Ansible inventory file in INI format. Here you can define list of
# hosts and host groups managed by this particular inventory.

# Host group below manages Ansible Controllers, hosts which are used to run the
# playbooks. To see what roles will be run, look in common playbook, located in
# debops-playbooks/playbooks/common.yml (these are common services like iptables
# firewall, Postfix SMTP server, sshd configuration, etc.).
EOF

if [ "$valid_debops_controller" -eq 1 ]; then
  cat <<EOF >> ${hosts_file}
# Your host can be managed by DebOps playbook. If you want above
# functionality and more, then uncomment your hostname in group below.
[ansible_controllers]
#$(hostname) ansible_connection=local

EOF
else
  cat <<EOF >> ${hosts_file}
# Your host is not Debian-based so you will not be able to leverage
# the above features on your current operating system. You can however
# use Vagrant or something else to setup a VM and install DebOps there.

[ansible_controllers]
#<VM host IP>

EOF
fi

apt_lxc_file="${project}/${NEW_INVENTORY}/group_vars/all/apt_lxc.yml"

cat <<EOF > ${apt_lxc_file}
# Occasionally Debian's CDN is a bit flaky. If you get 404s trying to access
# source URLs then uncomment the 2 variables below. You may also want to use
# your location's mirror rather than US, check the list of mirrors here:
#
# http://debian.mirrors.tds.net/pub/linux/debian/README.mirrors.html
#
#apt_debian_http_mirror: 'ftp.us.debian.org'
#lxc_template_debootstrap_mirror: 'http://{{ apt_debian_http_mirror }}/debian'
EOF

