Project

General

Profile

« Previous | Next » 

Revision 808edc81

Added by Benoît PECCATTE about 8 years ago

Fixes #8187: rudder remote-run should allow running for a group of nodes

View differences:

share/commands/remote-run
# @man +
# @man *Arguments*:
# @man +
# @man *node*: IP or hostname of the target node
# @man *node*: IP or hostname of the target node or 'all' for all nodes of the server
# @man +
# @man *Options*:
# @man +
......
# @man *-m*: run the agent with multiline output
# @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 *-j*: run this number of jobs in parallel
# @man +
# @man *-t*: provide an alternate token for group query (default from ~/.rudder)
# @man +
# @man *-u*: provide an alternate url for group query (default from ~/.rudder)
# @man +
# @man *-C*: provide an alternate config section in ~/.rudder for group query (default to first found)
. "${BASEDIR}/../lib/cfengine_parsing.sh"
. "${BASEDIR}/../lib/api_call.sh"
PORT=5309
LOOP="xargs -I{}"
MULTIHOST=1
while getopts "iIvdqwrRmcb:D:" opt; do
# Check for js presence
need_jq() {
if ! type jq >/dev/null 2>/dev/null
then
echo "ERROR: 'jq' must be installed to query hosts from server" 1>&2
exit 2
fi
}
while getopts "iIvdqwrRmcb:D:j:at:u:C:" opt; do
case $opt in
i|I)
VERBOSITY="-I ${DEBUG_CLASS}"
......
D)
CLASS="-D ${OPTARG}"
;;
j)
if ! type parallel >/dev/null 2>/dev/null
then
echo "ERROR: 'parallel' must be installed to run multiple jobs in parallel" 1>&2
exit 2
fi
LOOP="parallel --jobs ${OPTARG}"
;;
g)
need_jq
GROUP="${OPTARG}"
;;
a)
need_jq
ALL="true"
;;
t)
TOKEN="${OPTARG}"
;;
u)
URL="${OPTARG}"
;;
C)
CONFID="${OPTARG}"
;;
esac
# to keep the argument as $1
shift `expr ${OPTIND} - 1`
done
PORT=5309
NODE="$1"
if [ -z "${NODE}" ]
# Define node list method
if [ -n "${ALL}" ]
then
NODELIST="get_all_hostnames"
elif [ -n "${GROUP}" ]
then
NODELIST="get_group_hostids ${GROUP}"
elif [ -z "$1" ]
then
echo "Usage rudder remote run <node_ip_or_name>"
exit 1
else
NODELIST="echo $*"
fi
"${RUDDER_VAR}/cfengine-community/bin/cf-runagent" -H "${NODE}:${PORT}" ${VERBOSITY} ${COLOR} | eval ${PRETTY}
# get all hosts on server
get_all_hostnames() {
full_api_call "/api/nodes" "${URL}" "${CONFID}" "${TOKEN}" | jq '.data.nodes[].hostname' | sed -e 's/"\(.*\)"/\1/'
}
# get all hosts in a given group
get_group_hostids() {
for id in $(full_api_call "/api/groups/$1" "${URL}" "${CONFID}" "${TOKEN}" | jq '.data.groups[0].nodeIds[]')
do
full_api_call "/api/nodes/${id}" "${URL}" "${CONFID}" "${TOKEN}" | jq '.data.nodes[0].hostname'
done | sed -e 's/"\(.*\)"/\1/'
}
# Aggregate everything
${NODELIST} | ${LOOP} "${RUDDER_VAR}/cfengine-community/bin/cf-runagent" -H "{}:${PORT}" ${VERBOSITY} ${COLOR} | eval ${PRETTY}
share/lib/api_call.sh
if type curl >/dev/null 2>/dev/null
then
DOWNLOAD_COMMAND="curl --silent --show-error --insecure --location --proxy ''"
HEADER_OPT="--header"
else
DOWNLOAD_COMMAND="wget --quiet --no-check-certificate --no-proxy -O -"
HEADER_OPT="--header"
fi
# This functions tests if the API call returns "OK"
......
then
printf "${WHITE}${curl_command}${NORMAL}\n"
fi
result=`eval ${curl_command}`
result=`eval ${DOWNLOAD_COMMAND} \"${url}\"`
code=$?
if [ ${code} -eq 0 ] && [ "${result}" = "OK" ]
then
......
exit 1
fi
}
# retrieve one entry from ~/.rudder
_get_conf() {
conf="$1"
name="$2"
conffile=~/.rudder
[ -f "${conffile}" ] || return
[ -z "${conf}" ] && conf=".*"
# extract inifile section | extract value
sed -n "/^\\[${conf}\\]$/,/^\\[.*\\]$/p" "${conffile}" | sed -n "/^${name} *= */s/^${name} *= *//p"
}
# This function calls the api with a token
full_api_call() {
api="$1"
url="$2"
conf="$3"
token="$4"
if [ -z "${url}" ]
then
url=`_get_conf "${conf}" "url"`
if [ -z "${url}" ]
then
host=`cat /var/rudder/cfengine-community/policy_server.dat 2>/dev/null`
[ -z "${host}" ] && host="localhost"
url="https://${host}/rudder"
fi
fi
[ -z "${token}" ] && token=`_get_conf "${conf}" "token"`
if [ -z "${token}" ]
then
echo "A token is mandatory to query the server"
exit 1
fi
eval ${DOWNLOAD_COMMAND} ${HEADER_OPT} "\"X-API-Token: ${token}\"" ${HEADER_OPT} "\"Content-Type: application/json;charset=utf-8\"" ${HEADER_OPT} "\"X-API-Version: latest\"" \"${url}${api}\"
}
share/lib/cfengine_parsing.sh
QUIET=0
# Display full strings
FULL_STRINGS=0
# Prefix lines with hostname
MULTIHOST=0
UUID=$(cat /opt/rudder/etc/uuid.hive 2>/dev/null)
[ $? -ne 0 ] && UUID="Not yet configured"
VERSION=`"${BASEDIR}/agent-version"`
PRETTY="awk -v info=\"\${DISPLAY_INFO}\" -v full_strings=\"\${FULL_STRINGS}\" -v summary_only=\"\${SUMMARY_ONLY}\" -v quiet=\"\${QUIET}\" -v multiline=\"\${MULTILINE}\" \
PRETTY="awk -v info=\"\${DISPLAY_INFO}\" -v full_strings=\"\${FULL_STRINGS}\" -v summary_only=\"\${SUMMARY_ONLY}\" -v quiet=\"\${QUIET}\" -v multiline=\"\${MULTILINE}\" -v multihost=\"\${MULTIHOST}\" \
-v green=\"\${GREEN}\" -v darkgreen=\"\${DARKGREEN}\" -v red=\"\${RED}\" -v yellow=\"\${YELLOW}\" -v magenta=\"\${MAGENTA}\" -v normal=\"\${NORMAL}\" -v white=\"\${WHITE}\" -v cyan=\"\${CYAN}\" \
-f ${PRETTY_FILTER}"
share/lib/reports.awk
# Do not display "None" keys
$8 = "";
}
if (match($1, /.*> ->/))
{
hostname=substr($1, RSTART, RLENGTH-4);
}
{
if (!summary_only)
......
if (!header_printed)
{
header_printed = 1;
printf "%s%-8.8s %-25.25s %-25.25s %-18.18s %s%s\n", white, "Result", "Technique", "Component", "Key", "Message", normal;
if(multihost)
{
printf "%s%-10.10s %-8.8s %-25.25s %-25.25s %-18.18s %s%s\n", white, "Hostname", "Result", "Technique", "Component", "Key", "Message", normal;
}
else
{
printf "%s%-8.8s %-25.25s %-25.25s %-18.18s %s%s\n", white, "Result", "Technique", "Component", "Key", "Message", normal;
}
}
if(multihost)
{
printf "%s%-10.10s ", normal, hostname;
}
printf "%s%-8.8s%s ", color, result, normal;
if (full_strings)

Also available in: Unified diff