#!/bin/bash
#
# functions - puppet-openstack-integration specific functions
#

# Install external Puppet modules with r10k
# Uses the following variables:
#
# - ``SCRIPT_DIR`` must be set to script path
# - ``GEM_BIN_DIR`` must be set to Gem bin directory
install_external() {
  PUPPETFILE=${SCRIPT_DIR}/Puppetfile1 r10k -v DEBUG puppetfile install
}

# Install Puppet OpenStack modules with zuul-cloner
# Uses the following variables:
#
# - ``PUPPETFILE_DIR`` must be set to Puppet modules directory
# - ``SCRIPT_DIR`` must be set to script path
# - ``ZUUL_BRANCH`` must be set to Zuul branch. Fallback to 'master'.
install_openstack() {
  cat > clonemap.yaml <<EOF
clonemap:
  - name: '(.*?)/puppet-(.*)'
    dest: '$PUPPETFILE_DIR/\2'
EOF

  # Periodic jobs run without ref on master
  ZUUL_BRANCH=${ZUUL_BRANCH:-master}

  local project_names=$(awk '{ if ($1 == ":git") print $3 }' \
    ${SCRIPT_DIR}/Puppetfile0 | tr -d "'," | cut -d '/' -f 4- | xargs
  )
  project_names="${project_names} openstack/puppet-openstack-integration"
  /usr/zuul-env/bin/zuul-cloner -m clonemap.yaml \
    --cache-dir /opt/git \
    --zuul-branch $ZUUL_BRANCH \
    git://git.openstack.org $project_names

  # Because openstack-integration can't be a class name.
  # https://projects.puppetlabs.com/issues/5268
  mv $PUPPETFILE_DIR/openstack-integration $PUPPETFILE_DIR/openstack_integration
}

# Install all Puppet modules with r10k
# Uses the following variables:
#
# - ``SCRIPT_DIR`` must be set to script path
install_all() {
  # When installing from local source, we want to install the current source
  # we're working from.
  PUPPETFILE=${SCRIPT_DIR}/Puppetfile r10k -v DEBUG puppetfile install
  cp -a ${SCRIPT_DIR} ${PUPPETFILE_DIR}/openstack_integration
}

# Install Puppet OpenStack modules and dependencies by using
# zuul-cloner or r10k.
# Uses the following variables:
#
# - ``PUPPETFILE_DIR`` must be set to Puppet modules directory
# - ``SCRIPT_DIR`` must be set to script path
# - ``ZUUL_BRANCH`` must be set to Zuul branch
install_modules() {
  # If zuul-cloner is there, have it install modules using zuul refs
  if [ -e /usr/zuul-env/bin/zuul-cloner ] ; then
    csplit ${SCRIPT_DIR}/Puppetfile /'External modules'/ \
      --prefix ${SCRIPT_DIR}/Puppetfile \
      --suffix '%d'
    install_external
    install_openstack
  else
    install_all
  fi
}

# Write out basic hiera configuration
#
# Uses the following variables:
# - ``SCRIPT_DIR`` must be set to the dir that contains a /hiera folder to use
# - ``HIERA_CONFIG`` must be set to the hiera config file location
#
configure_hiera() {
  cat <<EOF >$HIERA_CONFIG
---
:backends:
  - yaml
:yaml:
  :datadir: "${SCRIPT_DIR}/hiera"
:hierarchy:
  - "%{::operatingsystem}"
  - "%{::osfamily}"
  - common
EOF
}

is_fedora() {
    if [ -f /etc/os-release ]; then
        source /etc/os-release
        test "$ID" = "fedora" -o "$ID" = "centos"
    else
        return 1
    fi
}

uses_debs() {
    # check if apt-get is installed, valid for debian based
    type "apt-get" 2>/dev/null
}

print_header() {
    if [ -n "$(set | grep xtrace)" ]; then
      set +x
      local enable_xtrace='yes'
    fi
    local msg=$1
    printf '%.0s-' {1..80}; echo
    printf '| %-76s |\n' "${msg}"
    printf '%.0s-' {1..80}; echo
    if [ -n "${enable_xtrace}" ]; then
      set -x
    fi
}

install_puppet() {
    if uses_debs; then
        print_header 'Setup (Debian based)'
        # Puppetlabs packaging:
        # - xenial: puppet4 only
        if dpkg -l $PUPPET_RELEASE_FILE >/dev/null 2>&1; then
            $SUDO apt-get purge -y $PUPPET_RELEASE_FILE
        fi
        $SUDO rm -f /tmp/puppet.deb
        wget http://apt.puppetlabs.com/${PUPPET_RELEASE_FILE}-${DISTRO}.deb -O /tmp/puppet.deb
        $SUDO dpkg -i /tmp/puppet.deb
        # TODO(emilien): figure what installed /etc/default/puppet on the xenial nodepool image
        # We have no problem on Trusty but on Xenial we need to remove /etc/default/puppet before
        # trying to deploy puppet-agent from puppetlabs.com.
        $SUDO rm -rf /etc/default/puppet
        $SUDO apt-get update
        $SUDO apt-get install -y ${PUPPET_PKG}
    elif is_fedora; then
        print_header 'Setup (RedHat based)'
        if rpm --quiet -q $PUPPET_RELEASE_FILE; then
            $SUDO rpm -e $PUPPET_RELEASE_FILE
        fi
        # EPEL does not work fine with RDO, we need to make sure EPEL is really disabled
        if rpm --quiet -q epel-release; then
            $SUDO rpm -e epel-release
        fi
        $SUDO rm -f /tmp/puppet.rpm

        if [ "${MANAGE_REPOS}" == "true" ] ; then
            wget http://yum.puppetlabs.com/${PUPPET_URL_SUFFIX}${PUPPET_RELEASE_FILE}-el-7.noarch.rpm -O /tmp/puppet.rpm
            $SUDO rpm -ivh /tmp/puppet.rpm
        fi
        $SUDO yum install -y ${PUPPET_PKG}
    fi
}

function run_puppet() {
    local manifest=$1
    $SUDO $PUPPET_FULL_PATH apply $PUPPET_ARGS fixtures/${manifest}.pp
    local res=$?
    return $res
}

function catch_selinux_alerts() {
    if is_fedora; then
        $SUDO sealert -a /var/log/audit/audit.log
        if $SUDO grep -iq 'type=AVC' /var/log/audit/audit.log; then
            echo "AVC detected in /var/log/audit/audit.log"
            # TODO: figure why latest rabbitmq deployed with SSL tries to write in SSL pem file.
            # https://bugzilla.redhat.com/show_bug.cgi?id=1341738
            if $SUDO grep -iqE 'denied.*system_r:rabbitmq_t' /var/log/audit/audit.log; then
                echo "non-critical RabbitMQ AVC, ignoring it now."
            else
                echo "Please file a bug on https://bugzilla.redhat.com/enter_bug.cgi?product=Red%20Hat%20OpenStack&component=openstack-selinux showing sealert output."
                exit 1
            fi
        else
            echo 'No AVC detected in /var/log/audit/audit.log'
        fi
    fi
}

function timestamp_puppet_log() {
    $SUDO mv ${WORKSPACE}/puppet.log ${WORKSPACE}/puppet-$(date +%Y%m%d_%H%M%S).log
}

function catch_puppet_failures() {
    grep -wiE '(Error|\(err\))' ${WORKSPACE}/puppet.log
}