Files
KNELIAC/scripts/awx_create_job_templates.py
T
mrcharles 7fa2792256 feat(awx): add AWX job template creation script
Add scripts/awx_create_job_templates.py that creates the two AWX job
templates (Hello World + Setup New System) after the code has been
pushed to git and the project has synced. Run this once after cloning
the repo on a new AWX instance.

🤖 Generated with [Crush](https://github.com/charmassociates/crush)

Assisted-by: GLM-5 via Crush <crush@charm.land>
2026-07-30 12:16:44 -05:00

161 lines
4.9 KiB
Python

#!/usr/bin/env python3
"""
awx_create_job_templates.py
Run this AFTER committing and pushing the KNELIAC code to the git remote.
It will:
1. Trigger a project sync in AWX (pulls latest code from git)
2. Wait for the sync to complete
3. Create the two job templates (Hello World + Setup New System)
4. Create the inventory source (auto-syncs hosts from inventory/hosts.yml)
Usage:
python3 awx_create_job_templates.py
"""
import urllib.request, urllib.parse, json, base64, time, sys
API = "http://100.91.39.53/api/v2"
AUTH = base64.b64encode(b"***REMOVED***").decode()
PROJECT_ID = 10
INVENTORY_ID = 2
SCM_CRED_ID = 3
MACHINE_CRED_ID = 4
ORG_ID = 1
def awx_req(method, endpoint, data=None):
url = f"{API}/{endpoint}"
body = json.dumps(data).encode() if data else None
req = urllib.request.Request(url, data=body, method=method)
req.add_header("Authorization", f"Basic {AUTH}")
req.add_header("Content-Type", "application/json")
try:
with urllib.request.urlopen(req, timeout=30) as resp:
raw = resp.read()
return json.loads(raw) if raw else {}
except urllib.error.HTTPError as e:
err = e.read().decode()
print(f" ERROR {e.code}: {err[:300]}")
return None
def find_or_create(resource, name, payload):
encoded = urllib.parse.quote(name)
existing = awx_req("GET", f"{resource}/?name={encoded}")
if existing and existing.get("count", 0) > 0:
item = existing["results"][0]
print(f" EXISTS: [{item['id']}] {name}")
return item
result = awx_req("POST", f"{resource}/", payload)
if result:
print(f" CREATED: [{result.get('id')}] {name}")
return result
# Step 1: Sync the project
print("=" * 60)
print("STEP 1: Syncing project (pulling latest code from git)")
print("=" * 60)
sync = awx_req("POST", f"projects/{PROJECT_ID}/update/", {})
if not sync:
print("FAILED to trigger sync")
sys.exit(1)
update_id = sync.get("id")
print(f" Sync started: project_updates/{update_id}")
print(" Waiting...", end="", flush=True)
for i in range(30):
time.sleep(3)
print(".", end="", flush=True)
status = awx_req("GET", f"project_updates/{update_id}/")
s = status.get("status") if status else "?"
if s in ("successful", "failed", "error", "canceled"):
print(f" {s}")
break
else:
print(" timeout")
sys.exit(1)
if s != "successful":
print(f" Project sync failed: {s}")
print(" Make sure the code is committed and pushed to the git remote.")
sys.exit(1)
# Step 2: Verify playbooks are available
print("\n" + "=" * 60)
print("STEP 2: Verifying playbooks")
print("=" * 60)
playbooks = awx_req("GET", f"projects/{PROJECT_ID}/playbooks/")
if playbooks:
print(f" Found {len(playbooks)} playbook(s):")
for p in playbooks:
print(f" - {p}")
else:
print(" No playbooks found! Push your code and re-run.")
sys.exit(1)
# Step 3: Create inventory source
print("\n" + "=" * 60)
print("STEP 3: Creating inventory source")
print("=" * 60)
find_or_create("inventory_sources", "KNELIAC Fleet Source", {
"name": "KNELIAC Fleet Source",
"description": "Auto-synced from inventory/hosts.yml",
"inventory": INVENTORY_ID,
"source": "scm",
"source_project": PROJECT_ID,
"source_path": "inventory/hosts.yml",
"update_on_launch": True,
"overwrite": True,
"overwrite_vars": True,
})
# Step 4: Create job templates
print("\n" + "=" * 60)
print("STEP 4: Creating job templates")
print("=" * 60)
find_or_create("job_templates", "KNELIAC - Hello World", {
"name": "KNELIAC - Hello World",
"description": "AWX smoke test - verify connectivity to managed hosts",
"organization": ORG_ID,
"inventory": INVENTORY_ID,
"project": PROJECT_ID,
"playbook": "playbooks/hello_world.yml",
"credential": MACHINE_CRED_ID,
"verbosity": 1,
"forks": 5,
"ask_limit_on_launch": True,
})
find_or_create("job_templates", "KNELIAC - Setup New System", {
"name": "KNELIAC - Setup New System",
"description": "Full host provisioning (port of SetupNewSystem.sh)",
"organization": ORG_ID,
"inventory": INVENTORY_ID,
"project": PROJECT_ID,
"playbook": "playbooks/setup_new_system.yml",
"credential": MACHINE_CRED_ID,
"verbosity": 1,
"forks": 5,
"ask_limit_on_launch": True,
"ask_variables_on_launch": True,
})
print("\n" + "=" * 60)
print("ALL DONE - AWX is ready!")
print("=" * 60)
print("""
AWX URL: http://tsys-awx.knel.net (or http://100.91.39.53)
Login: admin
Resources created:
Credentials:
[3] KNELIAC Git Credential (Source Control - for git access)
[4] KNELIAC Host SSH Key (Machine - for fleet host access)
Project:
[10] KNELIAC (git repo, auto-syncs on launch)
Inventory:
[2] KNELIAC Fleet (auto-syncs hosts from inventory/hosts.yml)
Job Templates:
- KNELIAC - Hello World (smoke test, run first!)
- KNELIAC - Setup New System (full provisioning)
""")