140 lines
4.7 KiB
Bash
Executable File
140 lines
4.7 KiB
Bash
Executable File
echo "Created credential id=$NEW_CRED_ID"
|
|
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
# create_cred_and_ping.sh
|
|
# Creates an AWX Machine credential from a local private key and runs an ad-hoc ping
|
|
# against static hosts. Configure AWX_HOST/AWX_USER/AWX_PASS or AWX_TOKEN/AWX_AUTH_HEADER via env.
|
|
|
|
# Defaults
|
|
AWX_HOST="${AWX_HOST:-http://192.168.49.2:30081}"
|
|
AWX_USER="${AWX_USER:-admin}"
|
|
AWX_PASS="${AWX_PASS:-Aase#1234!}"
|
|
KEY_PATH="${KEY_PATH:-$HOME/.ssh/awx_deploy_key}"
|
|
CREDS_NAME="${CREDS_NAME:-auto-machine-awx_deploy_key}"
|
|
USERNAME="${USERNAME:-admin}"
|
|
ORG_ID="${ORG_ID:-1}"
|
|
CREDTYPE="${CREDTYPE:-1}"
|
|
INV_ID="${INV_ID:-2}"
|
|
LIMIT="${LIMIT:-host-192-168-1-144,host-192-168-1-23,host-192-168-1-24}"
|
|
POLL_TIMEOUT="${POLL_TIMEOUT:-180}"
|
|
|
|
# Dependencies
|
|
for cmd in curl jq python3 mktemp; do
|
|
if ! command -v "$cmd" >/dev/null 2>&1; then
|
|
echo "ERROR: required command '$cmd' not found in PATH" >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
if [ ! -f "$KEY_PATH" ]; then
|
|
echo "ERROR: private key not found at $KEY_PATH" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Temp files
|
|
TMP_DIR=$(mktemp -d)
|
|
cleanup() {
|
|
rm -rf "${TMP_DIR:-/tmp}" || true
|
|
}
|
|
trap cleanup EXIT INT TERM
|
|
|
|
TMP_JSON="$TMP_DIR/awx_new_cred.json"
|
|
TMP_BODY="$TMP_DIR/awx_new_cred_body.json"
|
|
ADHOC_JSON="$TMP_DIR/awx_adhoc.json"
|
|
RESP_FILE="$TMP_DIR/awx_adhoc_resp.json"
|
|
|
|
# Helper to perform authenticated curl; supports AWX_TOKEN or AWX_AUTH_HEADER or basic auth fallback
|
|
curl_auth() {
|
|
local method="$1" url="$2" datafile="${3:-}" outfile="${4:-/dev/stdout}"
|
|
local hdrs=( -H "Content-Type: application/json" )
|
|
if [ -n "${AWX_TOKEN:-}" ]; then
|
|
hdrs+=( -H "Authorization: Bearer ${AWX_TOKEN}" )
|
|
elif [ -n "${AWX_AUTH_HEADER:-}" ]; then
|
|
hdrs+=( -H "Authorization: ${AWX_AUTH_HEADER}" )
|
|
else
|
|
hdrs+=( -u "${AWX_USER}:${AWX_PASS}" )
|
|
fi
|
|
|
|
if [ -n "$datafile" ]; then
|
|
curl -sS -w "%{http_code}" "${hdrs[@]}" -X "$method" "$url" -d "@${datafile}" -o "$outfile" || true
|
|
else
|
|
curl -sS -w "%{http_code}" "${hdrs[@]}" -X "$method" "$url" -o "$outfile" || true
|
|
fi
|
|
}
|
|
|
|
echo "Generating credential payload..."
|
|
python3 - "$KEY_PATH" "$CREDS_NAME" "$USERNAME" "$CREDTYPE" "$ORG_ID" > "$TMP_JSON" <<'PY'
|
|
import json,sys
|
|
keypath=sys.argv[1]
|
|
name=sys.argv[2]
|
|
username=sys.argv[3]
|
|
ct=int(sys.argv[4])
|
|
org=int(sys.argv[5])
|
|
with open(keypath,'r',encoding='utf-8') as f:
|
|
key=f.read()
|
|
payload={'name': name, 'credential_type': ct, 'organization': org, 'inputs': {'username': username, 'ssh_key_data': key}}
|
|
print(json.dumps(payload))
|
|
PY
|
|
|
|
echo "Creating AWX credential from $KEY_PATH..."
|
|
CODE=$(curl_auth POST "$AWX_HOST/api/v2/credentials/" "$TMP_JSON" "$TMP_BODY")
|
|
echo "HTTP status: $CODE"
|
|
cat "$TMP_BODY" || true
|
|
|
|
if [ "$CODE" -lt 200 ] || [ "$CODE" -ge 300 ]; then
|
|
echo "Failed to create credential (status=$CODE). See response above." >&2
|
|
exit 1
|
|
fi
|
|
|
|
NEW_CRED_ID=$(jq -r '.id // empty' "$TMP_BODY")
|
|
if [ -z "$NEW_CRED_ID" ]; then
|
|
echo "No credential id returned; aborting" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "Created credential id=$NEW_CRED_ID"
|
|
|
|
# Prepare ad-hoc payload (use jq to be safe)
|
|
jq -n --arg inv "$INV_ID" --arg cred "$NEW_CRED_ID" --arg limit "$LIMIT" '{inventory:( ($inv|tonumber) ), credential:( ($cred|tonumber) ), module_name: "ping", module_args: "", limit: $limit}' > "$ADHOC_JSON"
|
|
|
|
echo "Launching ad-hoc ping..."
|
|
ADHOC_CODE=$(curl_auth POST "$AWX_HOST/api/v2/ad_hoc_commands/" "$ADHOC_JSON" "$RESP_FILE")
|
|
echo "Launch HTTP status: $ADHOC_CODE"
|
|
cat "$RESP_FILE" || true
|
|
ADHOC_ID=$(jq -r '.id // empty' "$RESP_FILE" || true)
|
|
if [ -z "$ADHOC_ID" ]; then
|
|
echo "Failed to launch ad-hoc command; response above." >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "Launched ad-hoc id=$ADHOC_ID; polling until finished (${POLL_TIMEOUT}s max)"
|
|
END=$((SECONDS+POLL_TIMEOUT))
|
|
STATUS=""
|
|
while [ $SECONDS -lt $END ]; do
|
|
# fetch status
|
|
curl_auth GET "$AWX_HOST/api/v2/ad_hoc_commands/$ADHOC_ID/" "" "$TMP_DIR/adhoc_status.json" >/dev/null
|
|
STATUS=$(jq -r '.status // empty' "$TMP_DIR/adhoc_status.json" || true)
|
|
echo "Status: ${STATUS:-unknown}"
|
|
if [ -n "$STATUS" ] && [ "$STATUS" != "running" ] && [ "$STATUS" != "pending" ]; then
|
|
break
|
|
fi
|
|
sleep 2
|
|
done
|
|
|
|
if [ -z "$STATUS" ]; then
|
|
echo "Timed out waiting for ad-hoc command to complete" >&2
|
|
else
|
|
echo "Final status: $STATUS"
|
|
fi
|
|
|
|
echo "--- events (first 500) ---"
|
|
curl_auth GET "$AWX_HOST/api/v2/ad_hoc_commands/$ADHOC_ID/events/?page_size=500" "" "$TMP_DIR/events.json" >/dev/null
|
|
jq -r '.results[] | {counter: .counter, event: .event, host_name: .host_name, stdout: .stdout}' "$TMP_DIR/events.json" || true
|
|
|
|
echo "--- stdout (text) ---"
|
|
curl_auth GET "$AWX_HOST/api/v2/ad_hoc_commands/$ADHOC_ID/stdout/?format=txt" "" "$TMP_DIR/stdout.txt" >/dev/null
|
|
cat "$TMP_DIR/stdout.txt" || true
|
|
|
|
echo "Done. If SSH auth fails, ensure the private key has access to the target hosts or use a key with passwordless access."
|