#!/usr/bin/env bash

# Bootstrap host with Chef and apply Orchard workflow, roughly outlined as follows:
## 1. Bootstrap host from workstation
## 2. Update node definition file on Chef server
## 3. Add encryption secret for encrypted data bags
## 3. Run chef on the node after node definition has been updated
## 4. Delete or leave encryption secret, depending on future needs. 

# Global variables
CHEF_SECRET_DIRECTORY='/path/to/chef-repo/secret/dir'
CHEF_REPO_DIRECTORY='/path/to/chef-repo'
KNIFE_BINARY=$(/usr/bin/which knife)
DELETE_SECRET=true
SSH_USER='root'
SSH_OPTS="-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
CHEF_BOOTSTRAP_VERSION=''

function bootstrap_host { 
  # Bootstrap the host accordingly. 

  if [ -n "${SSH_KEY}" ]; then
    printf '%s\n'
    printf '%s\n' "SSH key specified"
    SCP_COMMAND="scp -i ${SSH_KEY} ${SSH_OPTS}"
    SSH_COMMAND="ssh -i ${SSH_KEY} ${SSH_OPTS}"
    KNIFE_SSH_COMMAND="-i ${SSH_KEY}"
  else
    SCP_COMMAND="scp ${SSH_OPTS}"
    SSH_COMMAND="ssh ${SSH_OPTS}"
    KNIFE_SSH_COMMAND=''
  fi

  if [ -n "${HOST_USER}" ]; then
    SSH_USER=${HOST_USER}
  fi

  if [ -n "${CHEF_CLIENT_VERSION}" ]; then
    printf '%s\n'
    printf '%s\n' "Chef client version ${CHEF_CLIENT_VERSION} specified"
    CHEF_BOOTSTRAP_VERSION=" --bootstrap-version ${CHEF_CLIENT_VERSION}"
  fi

  [ "${VERBOSE}" = true ] && printf '%s\n' "Running initial knife commands"
    
  KNIFE_COMMAND_STRING="${KNIFE_BINARY} bootstrap ${BOOTSTRAP_IP} ${CHEF_BOOTSTRAP_VERSION} -x ${SSH_USER} ${KNIFE_SSH_COMMAND} -N ${BOOTSTRAP_HOSTNAME}"

  if $(${KNIFE_BINARY} node show ${BOOTSTRAP_HOSTNAME} 2>&1 | grep -iq "Node Name" > /dev/null); then 
    printf '%s\n'
    printf '%s\n' "${BOOTSTRAP_HOSTNAME} is already an active Chef-managed host. Here is its current configuration:"
    ${KNIFE_BINARY} node show ${BOOTSTRAP_HOSTNAME} && exit 0
  else
    [ "${VERBOSE}" = true ] && printf '%s\n' "Host not found. I will now bootstrap it..."
  fi

  ${KNIFE_COMMAND_STRING}

  # Add node definition file. This assumes you have configured one with the appropriate role and details
  NODE_DEFINITION_FILE=$(find "${CHEF_REPO_DIRECTORY}" -type f -name "*${BOOTSTRAP_HOSTNAME}*")
  if [ -f NODE_DEFINITION_FILE ]; then
    printf '%s\n'
    printf '%s\n' "Node file not found in ${CHEF_REPO_DIRECTORY}. Please create a corresponding node file matching the hostname."
    exit 1
  else
    ${KNIFE_BINARY} node from file "${NODE_DEFINITION_FILE}"
  fi

  # Now temporarily copy over secret file
  printf '%s\n'
  printf '%s\n' "Copying secret file to node. You may be prompted for the node's ${SSH_USER} password one or more times..."
  printf '%s\n'
  ${SCP_COMMAND} ${CHEF_SECRET_DIRECTORY}/encrypted_data_bag_secret ${SSH_USER}@${BOOTSTRAP_IP}:/etc/chef/ && printf '%s\n' "Secret file copied to node Chef directory"

# Hack for broken nagios plugin recipe, required until Nagios goes away. 
cat << EOF > temp.sh
mkdir -p /var/chef/cache"
curl https://nagios-plugins.org/download/nagios-plugins-1.5.tar.gz > /var/chef/cache/nagios-plugins-1.5.tar.gz"
chef-client
EOF

  if [ "${DELETE_SECRET}" = true ]; then
    printf '%s\n'
    printf '%s\n' "Removing encryption secret..."
    echo "rm -rf /etc/chef/encrypted_data_bag_secret" >> temp.sh
  else
    printf '%s\n' "Leaving encryption secret for future client runs. You must now manually manage this secret."
  fi
  chmod +x temp.sh

  printf '%s\n' "Running chef-client to converge based on its updated node definition. You may be prompted for the node's ${SSH_USER} password one or more times..."
  printf '%s\n'
  ${SCP_COMMAND} temp.sh ${SSH_USER}@${BOOTSTRAP_IP}:/tmp && printf '%s\n' "Script file copied to node tmp directory"
  printf '%s\n'
  echo "/tmp/temp.sh" | ${SSH_COMMAND} ${SSH_USER}@${BOOTSTRAP_IP}

  rm -rf temp.sh
}

while getopts 'c:h:i:k:u:v' flag; do
  case "${flag}" in
  c) CHEF_CLIENT_VERSION="${OPTARG}" ;;
  h) BOOTSTRAP_HOSTNAME="${OPTARG}" ;;
  i) BOOTSTRAP_IP="${OPTARG}" ;;
  k) SSH_KEY="${OPTARG}" ;;
  u) HOST_USER="${OPTARG}" ;;
  v) VERBOSE=true && printf '%s\n' "Verbose output enabled" ;;
  *) printf "Unexpected option ${flag}\n"
     exit 1 ;;
  esac
done

[ -n "${BOOTSTRAP_HOSTNAME}" ] && [ -n "${BOOTSTRAP_IP}" ]  && bootstrap_host
