#!/bin/sh
# @description trigger the execution of a remote agent
# @man This command allows to override the agent run schedule and to immediately
# @man update the policies and enforce them on th specified node.
# @man This command is currently only allowed from the policy server of the target node.
# @man +
# @man *Arguments*:
# @man +
# @man *nodes*: comma-separated list of IP or hostname of the target node or 'all' for all nodes of the server
# @man +
# @man *Options*:
# @man +
# @man *-i*: run the agent in information mode, prints basic information
# @man +
# @man *-v*: run the agent in verbose mode, prints detailed information
# @man +
# @man *-d*: run the agent in debug mode, prints low-level information
# @man +
# @man *-q*: run the agent in quiet mode (display only error messages)
# @man +
# @man *-w*: show full strings, never cut output
# @man +
# @man *-c*: run the agent without color output
# @man +
# @man *-T*: display timing information
# @man +
# @man *-r*: run the agent with raw output
# @man +
# @man *-R*: run the agent in completely unparsed mode, with no return code of 1 in case of error. A little faster.
# @man +
# @man *-D*: define a class for this run
# @man +
# @man *-a*: run the agent on all known nodes
# @man +
# @man *-g*: run the agent on all nodes of the group UUID given in parameter
# @man +
# @man *-e*: exit with an error if there was an error during policy application
# @man +
# @man *-E*: exit with an error if there a non compliance
# @man +
# @man *Exit codes*:
# @man +
# @man *0*: Agent ran normally
# @man +
# @man *1*: Agent encountered a critical error and could not run properly
# @man +
# @man *2*: Some policy encountered and error and *-e* parameter was passed
# @man +
# @man *3*: Some policy encountered a non compliance and *-E* parameter was passed


. "${BASEDIR}/../lib/common.sh"
. "${BASEDIR}/../lib/cfengine_parsing.sh"
. "${BASEDIR}/../lib/api_call.sh"

PORT=$(cut -d: -s -f2 "${RUDDER_VAR}/cfengine-community/policy_server.dat")
PORT=${PORT:-5309}
DELIM=""
MULTIHOST=1
TIMEOUT="-t 300"
DISPLAY_COMMAND=false

while getopts "iIvdqwrRcTD:j:g:at:u:C:eE" opt; do
  case $opt in
    i|I)
      DISPLAY_INFO=1
      QUIET=0
      DISPLAY_COMMAND=true
      ;;
    v)
      VERBOSITY="-v ${VERBOSE_CLASS}"
      DISPLAY_INFO=1
      QUIET=0
      DISPLAY_COMMAND=true
      ;;
    d)
      VERBOSITY="-d ${DEBUG_CLASS}"
      DISPLAY_INFO=1
      QUIET=0
      DISPLAY_COMMAND=true
      ;;
    q)
      DISPLAY_INFO=0
      QUIET=1
      DISPLAY_COMMAND=false
      ;;
    w)
      FULL_STRINGS=1
      ;;
    c)
      clear_colors
      ;;
    T)
      TIMING=1
      ;;
    r)
      SUMMARY_ONLY=1
      DISPLAY_INFO=1
      ;;
    R)
      PRETTY="cat"
      ;;
    D)
      CLASSES="${CLASSES},${OPTARG}"
      ;;
    g)
      GROUP="${OPTARG}"
      ;;
    a)
      ALL="true"
      ;;
    e)
      ERROR_FAIL=1
      ;;
    E)
      NONCOMPLIANT_FAIL=1
      ;;
  esac
done

if is_https_only; then
  echo "Remote run is not supported in HTTPS-only mode"
  exit 1
fi

# to read remaining arguments with $*
shift `expr ${OPTIND} - 1`

if [ -n "${CLASSES}" ]
then
  # remove the first comma, yes it's posix
  CLASS="-D ${CLASSES#,}"
fi

# Define node list method
if [ -z "${ALL}" ] && [ -z "${GROUP}" ]
then
  if [ -z "$1" ]
  then
    echo "Usage rudder remote run <node_ip_or_name>"
    exit 1
  else
    echo -n $* | xargs -I{} -d, "${RUDDER_DIR}/bin/cf-runagent" -H "{}:${PORT}" ${TIMEOUT} ${VERBOSITY} ${COLOR} ${CLASS} | eval ${PRETTY}
  fi
else
  if [ -n "${ALL}" ]
  then
    rudder_api_call "/nodes/applyPolicy" "POST" "" "${DISPLAY_COMMAND}"
  else
    echo "-g Group option not yet supported !"
    exit 1
  fi
fi
