|
#!/usr/bin/env bash |
|
|
|
# |
|
# @dependencies |
|
# [jq](https://stedolan.github.io/jq/manual/) used to parse api results cleanly |
|
# |
|
#---{Global Variables}---------------------------------------------------------# |
|
SVC=$0 |
|
NAME='search-userdata' |
|
LOG_PREFIX="[${NAME}]" |
|
GREP_PATTERN="${1}" |
|
|
|
# manually set behavior Variables. |
|
ONLY_INSTANCE_IDS="" # Add instance ids to check only those; spaced. |
|
MAX_ITEMS="" # Set max number of items, helpful for testing. |
|
DEBUG=false # each api call and function has debugging output. |
|
OUTPUT_NONMATCHES=false # True will output if an instance-id has a match or not. |
|
OUTPUT_MATCHEDCONTENT=false # True will output user data for matched instances. |
|
OUTPUT_NONMATCHEDCONTENT=false # True will output user data for non matched instances. |
|
|
|
read -r -d '' USAGE_MESSAGE <<- EOM |
|
---{cloudint-search}------------------------------------------------------------ |
|
Used to find instances that contain user |
|
data which matches the provided grep_pattern. |
|
|
|
Usage: ${SVC} grep_pattern |
|
Example: ${SVC} "-E (composer[[:space:]](.*)?install)" |
|
-------------------------------------------------------------------------------- |
|
EOM |
|
|
|
#---{helper functions}---------------------------------------------------------# |
|
usage() { echo "${USAGE_MESSAGE}" 1>&2; exit 0; } |
|
log() { NOW=$(date +"%F %H:%M:%S %z"); (>&2 echo "${LOG_PREFIX}::[${NOW}]::[$@]"); } |
|
debug() { if ${DEBUG}; then log "DEBUG: $@" ; fi } |
|
error() { log "ERROR: $@" ; usage; exit 1 ; } |
|
|
|
#---{script functions}---------------------------------------------------------# |
|
getClient(){ echo "aws"; } |
|
runClientCommand(){ |
|
local CMD="$(getClient) $@"; |
|
debug $CMD; |
|
${CMD} |
|
} |
|
|
|
getInstanceUserData(){ |
|
local instance_id="${1}" |
|
debug "(getInstanceUserData(${instance_id})" |
|
if [ -z "${instance_id}" ]; then error "invalid instance id provided (${instance_id})"; fi |
|
local data_raw=$(runClientCommand ec2 describe-instance-attribute --attribute userData --instance-id ${instance_id} --output text --query "UserData.Value") |
|
if [ "${data_raw}" == "None" ]; then data_raw=""; fi # hack; `None` is a bad/sad response from the SDK. |
|
local data_base64=$(echo ${data_raw} | base64 --decode) |
|
local data_gzip=$(echo ${data_raw} | base64 --decode | gzip -d 2>/dev/null ) |
|
echo "${data_gzip:-$data_base64}" |
|
} |
|
|
|
instanceDataHasMatch(){ |
|
local instance_id=${1} |
|
local grep_pattern=${2} |
|
if [ -z "${instance_id}" ]; then error "missing instance id (${instance_id})"; fi |
|
if [ -z "${grep_pattern}" ]; then error "missing grep pattern (${grep_pattern})"; fi |
|
debug "(instanceDataHasMatch(${instance_id}, ${grep_pattern})" |
|
data=$(getInstanceUserData ${instance_id}) |
|
matches=$(echo "${data}" | grep ${grep_pattern}) |
|
|
|
if [ ! -z "${matches}" ]; then |
|
debug "match found (${instance_id})" |
|
if ${OUTPUT_MATCHEDCONTENT}; then log "${instance_id} data: (${matches})"; fi |
|
return 0 |
|
else |
|
debug "match NOT found (${instance_id})" |
|
if ${OUTPUT_NONMATCHEDCONTENT}; then log "${instance_id} data: (${data})"; fi |
|
return 1 |
|
fi |
|
} |
|
|
|
execute(){ |
|
local grep_pattern="${1}" |
|
debug "(execute(${grep_pattern})" |
|
if [ -z "${grep_pattern}" ]; then error "invalid argument GREP_PATTERN (${grep_pattern})"; fi |
|
|
|
if [ ! -z "${TEST_INSTANCE_IDS}" ]; then |
|
local instances=$(runClientCommand ec2 describe-instances --instance-ids "${ONLY_INSTANCE_IDS}" --max-items "${MAX_ITEMS}" --filters "Name=instance-state-name,Values=running" --query "Reservations[].Instances[].InstanceId" | jq -r '.[]') |
|
else |
|
local instances=$(runClientCommand ec2 describe-instances --instance-ids "${ONLY_INSTANCE_IDS}" --filters "Name=instance-state-name,Values=running" --query "Reservations[].Instances[].InstanceId" | jq -r '.[]') |
|
fi |
|
|
|
for instance_id in ${instances}; do |
|
if instanceDataHasMatch "${instance_id}" "${grep_pattern}"; then |
|
log "${instance_id} has match" |
|
else |
|
if ${OUTPUT_NONMATCHES}; then log "${instance_id} has no match"; fi |
|
fi |
|
done |
|
} |
|
|
|
#---{run time}-----------------------------------------------------------# |
|
execute "${GREP_PATTERN}" |