%PDF- <> %âãÏÓ endobj 2 0 obj <> endobj 3 0 obj <>/ExtGState<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI] >>/Annots[ 28 0 R 29 0 R] /MediaBox[ 0 0 595.5 842.25] /Contents 4 0 R/Group<>/Tabs/S>> endobj ºaâÚÎΞ-ÌE1ÍØÄ÷{òò2ÿ ÛÖ^ÔÀá TÎ{¦?§®¥kuµùÕ5sLOšuY>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<>endobj 2 0 obj<> endobj 2 0 obj<>endobj 2 0 obj<>es 3 0 R>> endobj 2 0 obj<> ox[ 0.000000 0.000000 609.600000 935.600000]/Fi endobj 3 0 obj<> endobj 7 1 obj<>/ProcSet[/PDF/Text/ImageB/ImageC/ImageI]>>/Subtype/Form>> stream
#!/bin/sh # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: MIT set -e set -u readonly AGENTDIR="/opt/aws/amazon-cloudwatch-agent" readonly CMDDIR="${AGENTDIR}/bin" readonly CONFDIR="${AGENTDIR}/etc" readonly CWOC_CONFDIR="${AGENTDIR}/cwagent-otel-collector/etc" readonly CWA_RESTART_FILE="${CONFDIR}/restart" readonly CWOC_RESTART_FILE="${CWOC_CONFDIR}/cwoc-restart" readonly VERSION_FILE="${CMDDIR}/CWAGENT_VERSION" # The systemd and upstart scripts assume exactly this .toml file name readonly TOML="${CONFDIR}/amazon-cloudwatch-agent.toml" readonly YAML="${CWOC_CONFDIR}/cwagent-otel-collector.yaml" readonly JSON="${CONFDIR}/amazon-cloudwatch-agent.json" readonly JSON_DIR="${CONFDIR}/amazon-cloudwatch-agent.d" readonly YAML_DIR="${CWOC_CONFDIR}/cwagent-otel-collector.d" readonly PREDEFINED_CONFIG_DATA="${AGENTDIR}/cwagent-otel-collector/var/.predefined-config-data" readonly CV_LOG_FILE="${AGENTDIR}/logs/configuration-validation.log" readonly COMMON_CONIG="${CONFDIR}/common-config.toml" readonly CWA_NAME='amazon-cloudwatch-agent' readonly CWOC_NAME='cwagent-otel-collector' readonly ALL_CONFIG='all' SYSTEMD='false' UsageString=" usage: amazon-cloudwatch-agent-ctl -a stop|start|status|fetch-config|append-config|remove-config [-m ec2|onPremise|auto] [-c default|all|ssm:<parameter-store-name>|file:<file-path>] [-o default|all|ssm:<parameter-store-name>|file:<file-path>] [-s] e.g. 1. apply a SSM parameter store config on EC2 instance and restart the agent afterwards: amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c ssm:AmazonCloudWatch-Config.json -s 2. append a local json config file on onPremise host and restart the agent afterwards: amazon-cloudwatch-agent-ctl -a append-config -m onPremise -c file:/tmp/config.json -s 3. query agent status: amazon-cloudwatch-agent-ctl -a status -a: action stop: stop the agent process. start: start the agent process. status: get the status of the agent process. fetch-config: apply config for agent, followed by -c or -o or both. Target config can be based on location (ssm parameter store name, file name), or 'default'. append-config: append json config with the existing json configs if any, followed by -c. Target config can be based on the location (ssm parameter store name, file name), or 'default'. remove-config: remove config for agent, followed by -c or -o or both. Target config can be based on the location (ssm parameter store name, file name), or 'all'. -m: mode ec2: indicate this is on ec2 host. onPremise: indicate this is on onPremise host. auto: use ec2 metadata to determine the environment, may not be accurate if ec2 metadata is not available for some reason on EC2. -c: amazon-cloudwatch-agent configuration default: default configuration for quick trial. ssm:<parameter-store-name>: ssm parameter store name. file:<file-path>: file path on the host. all: all existing configs. Only apply to remove-config action. -o: cwagent-otel-collector configuration default: default configuration for quick trial. ssm:<parameter-store-name>: ssm parameter store name. file:<file-path>: file path on the host. all: all existing configs. Only apply to remove-config action. -s: optionally restart after configuring the agent configuration this parameter is used for 'fetch-config', 'append-config', 'remove-config' action only. " start_all() { mode="${1:-}" echo "****** processing cwagent-otel-collector ******" set +e agent_start "${CWOC_NAME}" "${mode}" set -e echo "" echo "****** processing amazon-cloudwatch-agent ******" agent_start "${CWA_NAME}" "${mode}" } agent_start() { agent_name="${1:-}" mode="${2:-}" if [ "$(runstatus ${agent_name})" = 'running' ]; then echo "${agent_name} has already been started" return 0 fi if [ "${agent_name}" = "${CWOC_NAME}" ] && [ ! -f "${YAML}" ]; then echo "${CWOC_NAME} will not be started as it has not been configured yet." return 0 fi if [ "${agent_name}" = "${CWA_NAME}" ] && [ ! -f "${TOML}" ]; then if [ -f "${YAML}" ]; then # If cwagent-otel-collector config exists, amazon-cloudwatch-agent default config will be suppressed echo "${CWA_NAME} will not be started as it has not been configured yet." return 0 fi echo "Both ${CWA_NAME} and ${CWOC_NAME} are not configured. Applying amazon-cloudwatch-agent default configuration." cwa_config 'default' 'false' "${mode}" 'default' fi if [ "${SYSTEMD}" = 'true' ]; then systemctl daemon-reload || return systemctl enable "${agent_name}.service" || return service "${agent_name}" restart || return else start "${agent_name}" || return sleep 1 fi } stop_all() { echo "****** processing cwagent-otel-collector ******" set +e agent_stop_and_disable "${CWOC_NAME}" set -e echo "" echo "****** processing amazon-cloudwatch-agent ******" agent_stop_and_disable "${CWA_NAME}" } agent_stop_and_disable() { agent_name="${1:-}" agent_stop "${agent_name}" agent_disable "${agent_name}" } agent_stop() { agent_name="${1:-}" if [ "$(runstatus ${agent_name})" = 'stopped' ]; then echo "${agent_name} has already been stopped" return 0 fi if [ "${SYSTEMD}" = 'true' ]; then service "${agent_name}" stop || return else stop "${agent_name}" || return fi } # disable cwagent-otel-collector in Systemd, amazon-cloudwatch-agent will not be disabled for now (TBD) # cwagent-otel-collector in Upstart are not disabled for now as old version of upstart doesn't support stanza 'Manual' agent_disable() { agent_name="${1:-}" if [ "${SYSTEMD}" = 'true' ] && [ "${agent_name}" = "${CWOC_NAME}" ]; then systemctl disable "${agent_name}.service" fi } # support for restart during upgrade via SSM packages prep_restart_all() { set +e agent_prep_restart "${CWOC_NAME}" "${CWOC_RESTART_FILE}" set -e agent_prep_restart "${CWA_NAME}" "${CWA_RESTART_FILE}" } agent_prep_restart() { agent_name="${1:-}" restart_file="${2:-}" if [ "$(runstatus ${agent_name})" = 'running' ]; then touch "${restart_file}" fi } # support for restart during upgrade via SSM packages cond_restart_all() { set +e agent_cond_restart "${CWOC_NAME}" "${CWOC_RESTART_FILE}" set -e agent_cond_restart "${CWA_NAME}" "${CWA_RESTART_FILE}" } agent_cond_restart() { agent_name="${1:-}" restart_file="${2:-}" if [ -f "${restart_file}" ]; then agent_start "${agent_name}" rm -f "${restart_file}" fi } preun_all() { set +e agent_preun "${CWOC_NAME}" set -e agent_preun "${CWA_NAME}" } agent_preun() { agent_name="${1:-}" agent_stop "${agent_name}" if [ "${SYSTEMD}" = 'true' ]; then systemctl disable "${agent_name}.service" || return systemctl daemon-reload || return systemctl reset-failed || return fi } status_all() { cwa_config_status='configured' if [ ! -f "${TOML}" ]; then cwa_config_status='not configured' fi cwoc_config_status='configured' if [ ! -f "${YAML}" ]; then cwoc_config_status='not configured' fi version="$(cat ${VERSION_FILE})" echo "{" echo " \"status\": \"$(runstatus ${CWA_NAME})\"," echo " \"starttime\": \"$(get_starttime_fmt ${CWA_NAME})\"," echo " \"configstatus\": \"${cwa_config_status}\"," echo " \"cwoc_status\": \"$(runstatus ${CWOC_NAME})\"," echo " \"cwoc_starttime\": \"$(get_starttime_fmt ${CWOC_NAME})\"," echo " \"cwoc_configstatus\": \"${cwoc_config_status}\"," echo " \"version\": \"${version}\"" echo "}" } get_starttime_fmt() { agent_name="${1:-}" agentPid='' if [ "${SYSTEMD}" = 'true' ]; then agentPid="$(systemctl show -p MainPID "${agent_name}.service" | sed s/MainPID=//)" else agentPid="$(initctl status "${agent_name}" | sed -n s/^.*process\ //p)" fi starttime_fmt='' if [ "${agentPid}" ] && [ "${agentPid}" -ne "0" ]; then starttime="$(TZ=UTC ps -o lstart= "${agentPid}")" starttime_fmt="$(TZ=UTC date -Isec -d "${starttime}")" fi echo "${starttime_fmt}" } runstatus() { agent_name="${1:-}" running=false if [ "${SYSTEMD}" = 'true' ]; then set +e if systemctl is-active "${agent_name}.service" 1>/dev/null; then running='true' fi set -e else if [ "$(initctl status "${agent_name}" | grep -c running)" = 1 ]; then running='true' fi fi if [ "${running}" = 'true' ]; then echo "running" else echo "stopped" fi } config_all() { cwa_config_location="${1:-}" cwoc_config_location="${2:-}" restart="${3:-}" mode="${4:-}" multi_config="${5:-}" if [ -z "${cwa_config_location}" ] && [ -z "${cwoc_config_location}" ]; then cwa_config_location='default' fi mkdir -p "${CONFDIR}" param_mode="ec2" case "${mode}" in ec2) param_mode="ec2" ;; onPremise) param_mode="onPrem" ;; auto) param_mode="auto" ;; *) echo "Invalid mode: ${mode}" >&2 exit 1 ;; esac if [ -n "${cwoc_config_location}" ]; then echo "****** processing cwagent-otel-collector ******" set +e cwoc_config "${cwoc_config_location}" "${restart}" "${param_mode}" "${multi_config}" set -e echo "" fi # cwa_config is called after cwoc_config becuase that whether applying # default cwa config depends on the existence of cwoc config if [ -n "${cwa_config_location}" ]; then echo "****** processing amazon-cloudwatch-agent ******" cwa_config "${cwa_config_location}" "${restart}" "${param_mode}" "${multi_config}" fi } cwa_config() { cwa_config_location="${1:-}" restart="${2:-}" param_mode="${3:-}" multi_config="${4:-}" if [ "${cwa_config_location}" = "${ALL_CONFIG}" ] && [ "${multi_config}" != 'remove' ]; then echo "ignore cwa configuration \"${ALL_CONFIG}\" as it is only supported by action \"remove-config\"" return fi if [ "${cwa_config_location}" = "${ALL_CONFIG}" ]; then rm -rf "${JSON_DIR}"/* else runDownloaderCommand="${CMDDIR}/config-downloader --output-dir ${JSON_DIR} --download-source ${cwa_config_location} --mode ${param_mode} --config ${COMMON_CONIG} --multi-config ${multi_config}" echo "${runDownloaderCommand}" ${runDownloaderCommand} || return fi if [ ! "$(ls ${JSON_DIR})" ]; then echo "all amazon-cloudwatch-agent configurations have been removed" rm -f "${TOML}" else echo "Start configuration validation..." runTranslatorCommand="${CMDDIR}/config-translator --input ${JSON} --input-dir ${JSON_DIR} --output ${TOML} --mode ${param_mode} --config ${COMMON_CONIG} --multi-config ${multi_config}" echo "${runTranslatorCommand}" ${runTranslatorCommand} || return runAgentSchemaTestCommand="${CMDDIR}/amazon-cloudwatch-agent -schematest -config ${TOML}" echo "${runAgentSchemaTestCommand}" # We will redirect the verbose error message out if ! ${runAgentSchemaTestCommand} > ${CV_LOG_FILE} 2>&1; then echo "Configuration validation second phase failed" echo "======== Error Log ========" cat ${CV_LOG_FILE} exit 1 fi echo "Configuration validation second phase succeeded" echo "Configuration validation succeeded" chmod ug+rw "${TOML}" # for translator: # default: only process .tmp files # append: process both existing files and .tmp files # remove: only process existing files # At this point, all json configs have been validated # multi_config: # default: delete non .tmp file, rename .tmp file # append: rename .tmp file # remove: no-op if [ "${multi_config}" = 'default' ]; then rm -f "${JSON}" for file in "${JSON_DIR}"/*; do base="${JSON_DIR}/$(basename "${file}" .tmp)" if [ "${file}" = "${base}" ]; then rm -f "${file}" else mv -f "${file}" "${base}" fi done elif [ "${multi_config}" = 'append' ]; then for file in "${JSON_DIR}"/*.tmp; do mv -f "${file}" "${JSON_DIR}/$(basename "${file}" .tmp)" done fi fi if [ "${restart}" = 'true' ]; then agent_stop_and_disable "${CWA_NAME}" agent_start "${CWA_NAME}" "${param_mode}" fi } cwoc_config() { cwoc_config_location="${1:-}" restart="${2:-}" param_mode="${3:-}" multi_config="${4:-}" if [ -f /opt/aws/aws-otel-collector/bin/aws-otel-collector-ctl ]; then echo "REMINDER: you are configuring \"cwagent-otel-collector\" instead of \"aws-otel-collector\"." fi if [ "${multi_config}" = 'append' ]; then echo "ignore \"-o\" as cwagent-otel-collector doesn't support append-config" return 0 fi if [ "${cwoc_config_location}" = "${ALL_CONFIG}" ] && [ "${multi_config}" != 'remove' ]; then echo "ignore cwoc configuration \"${ALL_CONFIG}\" as it is only supported by action \"remove-config\"" return fi if [ "${cwoc_config_location}" = "${ALL_CONFIG}" ]; then rm -rf "${YAML_DIR}"/* elif [ "${multi_config}" = 'default' ] && [ "${cwoc_config_location}" = 'default' ]; then cp "${PREDEFINED_CONFIG_DATA}" "${YAML_DIR}/default.tmp" echo "Successfully fetched the config and saved in ${YAML_DIR}/default.tmp" else runDownloaderCommand="${CMDDIR}/config-downloader --output-dir ${YAML_DIR} --download-source ${cwoc_config_location} --mode ${param_mode} --config ${COMMON_CONIG} --multi-config ${multi_config}" echo "${runDownloaderCommand}" ${runDownloaderCommand} || return fi if [ ! "$(ls ${YAML_DIR})" ]; then echo "all cwagent-otel-collector configurations have been removed" rm -f "${YAML}" else for file in "${YAML_DIR}"/*; do base="${YAML_DIR}/$(basename "${file}" .tmp)" if [ "${file}" = "${base}" ]; then rm -f "${file}" else mv -f "${file}" "${base}" cp -f "${base}" "${YAML}" echo "cwagent-otel-collector config has been successfully fetched." fi done fi if [ "${restart}" = 'true' ]; then agent_stop_and_disable "${CWOC_NAME}" agent_start "${CWOC_NAME}" "${param_mode}" fi } main() { action='' cwa_config_location='' cwoc_config_location='' restart='false' mode='ec2' # detect which init system is in use if [ "$(/sbin/init --version 2>/dev/null | grep -c upstart)" = 1 ]; then SYSTEMD='false' elif [ "$(systemctl | grep -c -E '\-\.mount\s')" = 1 ]; then SYSTEMD='true' elif [ -f /etc/init.d/cron ] && [ ! -h /etc/init.d/cron ]; then echo "sysv-init is not supported" >&2 exit 1 else echo "unknown init system" >&2 exit 1 fi OPTIND=1 while getopts ":hsa:c:o:m:" opt; do case "${opt}" in h) echo "${UsageString}" exit 0 ;; s) restart='true' ;; a) action="${OPTARG}" ;; c) cwa_config_location="${OPTARG}" ;; o) cwoc_config_location="${OPTARG}" ;; m) mode="${OPTARG}" ;; \?) echo "Invalid option: -${OPTARG} ${UsageString}" >&2 ;; :) echo "Option -${OPTARG} requires an argument ${UsageString}" >&2 exit 1 ;; esac done shift "$(( OPTIND - 1 ))" case "${mode}" in ec2) ;; onPremise) ;; auto) ;; *) echo "Invalid mode: ${mode} ${UsageString}" >&2 exit 1 ;; esac case "${action}" in stop) stop_all ;; start) start_all "${mode}" ;; fetch-config) config_all "${cwa_config_location}" "${cwoc_config_location}" "${restart}" "${mode}" 'default';; append-config) config_all "${cwa_config_location}" "${cwoc_config_location}" "${restart}" "${mode}" 'append';; remove-config) config_all "${cwa_config_location}" "${cwoc_config_location}" "${restart}" "${mode}" 'remove';; status) status_all ;; # helpers for ssm package scripts to workaround fact that it can't determine if invocation is due to # upgrade or install prep-restart) prep_restart_all ;; cond-restart) cond_restart_all ;; # helper for rpm+deb uninstallation hooks, not expected to be called manually preun) preun_all ;; *) echo "Invalid action: ${action} ${UsageString}" >&2 exit 1 ;; esac } main "$@"