# Cortex Agent One-Liner Provisioner
import os
import sys
import urllib.request
import subprocess
print("🚀 Starting Cortex Agent Provisioning for node: {{ node_id }}")
# 1. Create .cortex/agent-node directory
install_dir = os.path.expanduser("~/.cortex/agent-node")
os.makedirs(install_dir, exist_ok=True)
os.chdir(install_dir)
# 2. Write agent_config.yaml
print("[*] Writing configuration...")
config_content = """{{ config_yaml }}"""
with open("agent_config.yaml", "wb") as f:
f.write(config_content.encode("utf-8"))
f.flush()
os.fsync(f.fileno())
# 3. Download bootstrap_installer.py
installer_url = "{{ base_url }}/api/v1/agent/installer"
print(f"[*] Downloading installer from {installer_url} ...")
try:
urllib.request.urlretrieve(installer_url, "bootstrap_installer.py")
# Force sync to avoid SIGBUS/Bus Error on some NAS filesystems during next step
if hasattr(os, 'sync'):
os.sync()
except Exception as e:
print(f"❌ Failed to download installer: {e}")
sys.exit(1)
size = os.path.getsize("bootstrap_installer.py")
if size < 100:
with open("bootstrap_installer.py") as f: content = f.read()
print(f"❌ Downloaded file is too small or corrupt ({size} bytes): {content}")
sys.exit(1)
# 4. Run installer. Use exec() to avoid mmap issues on some NAS with normal import.
print("[*] Bootstrapping agent...")
sys.argv = [
"bootstrap_installer.py",
"--daemon",
"--hub", "{{ base_url }}",
"--token", "{{ invite_token }}",
"--node-id", "{{ node_id }}"
]
try:
with open("bootstrap_installer.py", "rb") as f:
code = f.read()
# Define a clean globals dict for execution
globs = {
"__name__": "__main__",
"__file__": os.path.abspath("bootstrap_installer.py"),
"__builtins__": __builtins__
}
exec(code, globs)
except SystemExit as e:
if str(e) != "0" and e.code != 0:
print(f"❌ Provisioning failed! Installer exited with code {e}")
sys.exit(e.code if isinstance(e.code, int) else 1)
except Exception as e:
import traceback
print(f"❌ Provisioning crashed: {e}")
traceback.print_exc()
sys.exit(1)