159 lines
5.8 KiB
Bash
Executable File
159 lines
5.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
# integrate_github_netbox.sh
|
|
# Create AWX Project (Git) and NetBox inventory source via AWX API.
|
|
# Usage (dry-run by default):
|
|
# ./integrate_github_netbox.sh --github-repo https://github.com/owner/repo.git \
|
|
# --github-pat GH_PAT --netbox-url https://netbox.example/api/ --netbox-token NETBOX_TOKEN [--apply]
|
|
|
|
AWX_URL=${AWX_URL:-http://localhost:30081}
|
|
AWX_USER=${AWX_USER:-admin}
|
|
AWX_PW="${AWX_PW:-}"
|
|
GITHUB_REPO=""
|
|
GITHUB_PAT=""
|
|
NETBOX_URL=""
|
|
NETBOX_TOKEN=""
|
|
PROJECT_NAME="awx-github-project"
|
|
INV_NAME="netbox-inventory"
|
|
DRY_RUN=1
|
|
|
|
usage(){
|
|
cat <<EOF
|
|
Usage: $0 --github-repo REPO_URL --github-pat PAT --netbox-url URL --netbox-token TOKEN [--project-name NAME] [--inventory-name NAME] [--apply]
|
|
|
|
This script is dry-run by default. Add --apply to execute API POSTs.
|
|
Secrets can also be provided via env vars: GITHUB_PAT, NETBOX_TOKEN, AWX_PW.
|
|
EOF
|
|
}
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--github-repo) GITHUB_REPO="$2"; shift 2;;
|
|
--github-pat) GITHUB_PAT="$2"; shift 2;;
|
|
--netbox-url) NETBOX_URL="$2"; shift 2;;
|
|
--netbox-token) NETBOX_TOKEN="$2"; shift 2;;
|
|
--project-name) PROJECT_NAME="$2"; shift 2;;
|
|
--inventory-name) INV_NAME="$2"; shift 2;;
|
|
--apply) DRY_RUN=0; shift;;
|
|
-h|--help) usage; exit 0;;
|
|
*) echo "Unknown arg: $1"; usage; exit 1;;
|
|
esac
|
|
done
|
|
|
|
# pick up env secrets if not provided
|
|
: "${GITHUB_PAT:-}" && GITHUB_PAT=${GITHUB_PAT:-$GITHUB_PAT}
|
|
AWX_PW=${AWX_PW:-}
|
|
NETBOX_TOKEN=${NETBOX_TOKEN:-$NETBOX_TOKEN}
|
|
|
|
for cmd in curl jq; do
|
|
if ! command -v "$cmd" >/dev/null 2>&1; then
|
|
echo "missing dependency: $cmd" >&2
|
|
exit 1
|
|
fi
|
|
done
|
|
|
|
if [ -z "$AWX_PW" ]; then
|
|
# try to read from k8s secret
|
|
if command -v kubectl >/dev/null 2>&1; then
|
|
if AWX_PW_RAW=$(kubectl -n awx get secret awx-admin-password -o jsonpath='{.data.password}' 2>/dev/null || true); then
|
|
if [ -n "$AWX_PW_RAW" ]; then
|
|
AWX_PW=$(echo "$AWX_PW_RAW" | base64 --decode)
|
|
fi
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Require github repo, netbox url and token. Either GITHUB_PAT OR a local SSH key file must exist.
|
|
if [ -z "$GITHUB_REPO" ] || [ -z "$NETBOX_URL" ] || [ -z "${NETBOX_TOKEN:-}" ] || { [ -z "${GITHUB_PAT:-}" ] && [ ! -f "$HOME/.ssh/awx_deploy_key" ]; }; then
|
|
echo "Missing required inputs." >&2
|
|
echo "Provide --github-repo, --netbox-url, --netbox-token and either --github-pat or a private key at $HOME/.ssh/awx_deploy_key." >&2
|
|
usage
|
|
exit 1
|
|
fi
|
|
|
|
AUTH="${AWX_USER}:${AWX_PW}"
|
|
|
|
api_get(){
|
|
local path=$1
|
|
curl -sS -u "$AUTH" "$AWX_URL/api/v2/$path"
|
|
}
|
|
|
|
api_post(){
|
|
local path=$1
|
|
local data=$2
|
|
if [ "$DRY_RUN" -ne 0 ]; then
|
|
echo "[DRY-RUN] POST $AWX_URL/api/v2/$path -> payload:" >&2
|
|
echo "$data" | jq . >&2 || true
|
|
return 0
|
|
fi
|
|
curl -sS -u "$AUTH" -H 'Content-Type: application/json' -X POST "$AWX_URL/api/v2/$path" -d "$data" | jq .
|
|
}
|
|
|
|
echo "AWX: $AWX_URL (user: $AWX_USER)"
|
|
echo "Repo: $GITHUB_REPO"
|
|
echo "Project: $PROJECT_NAME"
|
|
echo "Inventory: $INV_NAME"
|
|
echo "Dry-run: $DRY_RUN"
|
|
|
|
echo "Listing credential types (to pick SCM type)..."
|
|
api_get credential_types/ | jq -r '.results[] | "id:\(.id) name:\(.name) kind:\(.kind)"'
|
|
|
|
# User-friendly heuristic to pick SCM credential_type id
|
|
SCM_CT_ID=$(api_get credential_types/ | jq -r '.results[] | select((.name|test("Source Control|Git|SCM";"i")) or (.kind == "scm")) | .id' | head -n1)
|
|
if [ -z "$SCM_CT_ID" ]; then
|
|
echo "Could not auto-detect SCM credential_type id. You must create credentials manually using AWX UI or list credential_types." >&2
|
|
else
|
|
echo "Detected SCM credential_type id: $SCM_CT_ID"
|
|
fi
|
|
|
|
echo "Creating Git credential (token or ssh key)"
|
|
if [ -n "${GITHUB_PAT:-}" ]; then
|
|
git_cred_payload=$(jq -n --arg name "github-pat" --argjson ct "$SCM_CT_ID" --arg inputs "{\"token\":\"$GITHUB_PAT\"}" '{name:$name, credential_type:$ct, inputs:( $inputs | fromjson ) }')
|
|
else
|
|
# fall back to SSH private key if available
|
|
if [ -f "$HOME/.ssh/awx_deploy_key" ]; then
|
|
SSH_KEY_DATA=$(sed -n '1,2000p' "$HOME/.ssh/awx_deploy_key")
|
|
# use --arg to safely inject SSH private key text into JSON
|
|
git_cred_payload=$(jq -n --arg name "github-ssh" --argjson ct "$SCM_CT_ID" --arg ssh "$SSH_KEY_DATA" '{name:$name, credential_type:$ct, inputs:{ssh_key_data:$ssh}}')
|
|
else
|
|
echo "No GITHUB_PAT and no $HOME/.ssh/awx_deploy_key - cannot create SCM credential" >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
CREDS_OUT=$(api_post credentials/ "$git_cred_payload" || true)
|
|
SCM_CRED_ID=$(echo "$CREDS_OUT" | jq -r '.id // empty' 2>/dev/null || true)
|
|
if [ -z "$SCM_CRED_ID" ]; then
|
|
SCM_CRED_ID=null
|
|
echo "SCM credential id: (none - dry-run or failed)"
|
|
else
|
|
echo "SCM credential id: $SCM_CRED_ID"
|
|
fi
|
|
|
|
echo "Creating Project pointing to $GITHUB_REPO"
|
|
proj_payload=$(jq -n --arg name "$PROJECT_NAME" --arg scm_type "git" --arg scm_url "$GITHUB_REPO" --argjson cred "$SCM_CRED_ID" '{name:$name, scm_type:$scm_type, scm_url:$scm_url, scm_update_on_launch:true, scm_branch:null, scm_clean:false, scm_ref:null, scm_credential:$cred }')
|
|
api_post projects/ "$proj_payload"
|
|
|
|
echo "Creating Inventory: $INV_NAME"
|
|
inv_payload=$(jq -n --arg name "$INV_NAME" '{name:$name, organization:1}')
|
|
INV_OUT=$(api_post inventories/ "$inv_payload" || true)
|
|
INV_ID=$(echo "$INV_OUT" | jq -r '.id // empty')
|
|
if [ -z "$INV_ID" ]; then
|
|
echo "Could not create inventory (check output)." >&2
|
|
else
|
|
echo "Inventory id: $INV_ID"
|
|
fi
|
|
|
|
echo "Creating NetBox inventory source for inventory id $INV_ID"
|
|
source_vars=$(cat <<EOF
|
|
token: "$NETBOX_TOKEN"
|
|
url: "$NETBOX_URL"
|
|
validate_certs: true
|
|
EOF
|
|
)
|
|
src_payload=$(jq -n --arg name "netbox-src" --arg source "netbox" --arg source_vars "$source_vars" --argjson update_on_launch true '{name:$name, source:$source, source_vars:$source_vars, update_on_launch:$update_on_launch}')
|
|
api_post "inventories/$INV_ID/inventory_sources/" "$src_payload"
|
|
|
|
echo "Done. If run in dry-run mode, re-run with --apply to execute the API calls."
|
|
|
|
exit 0
|