054110d748
terragrunt-enc is the single source of truth for encapi ENC data (Puppet statuses, roles, and node classifications), managed with Terraform/Terragrunt. It supersedes Cobbler classification for Puppet and the terraform-incus dual-write prototype (PR #39). - Add modules/encapi (encapi_status / encapi_role / encapi_node, nodes FK-ordered after their role and status). - Add config/encapi leaf: 3 statuses, 51 roles, and 143 node assignments (130 container VMs env production + 13 prodnxsr physicals env develop), all YAML-driven. - Add config/root.hcl (consul backend infra/terraform/enc/<leaf>/state) and the encapi provider from the artifactapi registry (v0.1.0). - Add Makefile, Woodpecker pre-commit/plan/apply pipelines, pre-commit config, ci/extract_incus_nodes.py, and expand the README.
85 lines
2.9 KiB
Python
Executable File
85 lines
2.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Regenerate the container-VM portion of config/encapi/nodes.yaml from a
|
|
checkout of terraform-incus.
|
|
|
|
encapi is the single source of truth for Puppet ENC data, but the 130 container
|
|
VMs are *defined* in terraform-incus (config/instances/<host>/config.yaml). This
|
|
script lifts that classification into plain config data here:
|
|
|
|
certname = <dir basename>.<cobbler_domain> (cobbler_domain = main.unkin.net)
|
|
role = cobbler_mgmt_classes[0] (default roles::base)
|
|
environment = production
|
|
|
|
It only rewrites the "container VMs" block; the prodnxsr physical nodes below
|
|
the marker are maintained by hand and left untouched.
|
|
|
|
Usage:
|
|
python3 ci/extract_incus_nodes.py --incus-repo /path/to/terraform-incus
|
|
"""
|
|
import argparse
|
|
import os
|
|
import sys
|
|
|
|
try:
|
|
import yaml
|
|
except ImportError:
|
|
sys.exit("PyYAML required: pip install pyyaml")
|
|
|
|
PHYS_MARKER = "# --- prodnxsr physical nodes (develop) ---"
|
|
VM_MARKER = "# --- container VMs (production) ---"
|
|
|
|
|
|
def main():
|
|
ap = argparse.ArgumentParser()
|
|
ap.add_argument("--incus-repo", required=True,
|
|
help="Path to a terraform-incus checkout")
|
|
ap.add_argument("--domain", default="main.unkin.net")
|
|
ap.add_argument("--nodes-file",
|
|
default=os.path.join(os.path.dirname(__file__),
|
|
"..", "config", "encapi", "nodes.yaml"))
|
|
args = ap.parse_args()
|
|
|
|
inst = os.path.join(args.incus_repo, "config", "instances")
|
|
dirs = sorted(d for d in os.listdir(inst)
|
|
if os.path.isdir(os.path.join(inst, d))
|
|
and os.path.exists(os.path.join(inst, d, "config.yaml")))
|
|
|
|
vm_lines = []
|
|
for d in dirs:
|
|
with open(os.path.join(inst, d, "config.yaml")) as f:
|
|
cfg = yaml.safe_load(f) or {}
|
|
classes = cfg.get("cobbler_mgmt_classes") or []
|
|
role = classes[0] if classes else "roles::base"
|
|
vm_lines.append(f"{d}.{args.domain}:")
|
|
vm_lines.append(f" role: {role}")
|
|
vm_lines.append(" environment: production")
|
|
|
|
nodes_file = os.path.abspath(args.nodes_file)
|
|
with open(nodes_file) as f:
|
|
existing = f.read().splitlines()
|
|
|
|
# Preserve everything from the physical-nodes marker onward.
|
|
try:
|
|
idx = existing.index(PHYS_MARKER)
|
|
except ValueError:
|
|
sys.exit(f"marker not found in {nodes_file}: {PHYS_MARKER!r}")
|
|
tail = existing[idx:]
|
|
|
|
# Preserve only the top-of-file comment block, stopping at the VM marker.
|
|
header = []
|
|
for ln in existing[:idx]:
|
|
if ln == VM_MARKER:
|
|
break
|
|
header.append(ln)
|
|
while header and header[-1] == "":
|
|
header.pop()
|
|
|
|
out = header + ["", VM_MARKER] + vm_lines + ["", *tail]
|
|
with open(nodes_file, "w") as f:
|
|
f.write("\n".join(out).rstrip("\n") + "\n")
|
|
print(f"wrote {len(dirs)} container VM records to {nodes_file}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|