#!/usr/bin/bash # # from-inventory.sh — convert the Discourse #307 system inventory (raw # markdown of its wiki post) into the CMDB seed CSV [#705] # # Input: raw markdown of https://community.turnsys.com/t/307 (post 385), # fetched e.g. via the discourse-cli raw-API escape hatch # Output: cmdb/seed/systems.csv (normalized CI rows; v0 schema) # # Re-run whenever #307 changes; the CSV is the GLPI import candidate, the # markdown topic stays the human-readable inventory. # set -euo pipefail if [ $# -ne 1 ] || [ ! -r "$1" ]; then echo "usage: $0 systems.csv" >&2 exit 2 fi echo 'category,ci_name,host_node,vmid,specs,ts_ip,extra_ip,tuned,access,extra,status,source_section' awk -F'|' ' function trim(s) { gsub(/^[ \t]+|[ \t]+$/, "", s); return s } function strip(s) { gsub(/"/, "", s); return trim(s) } function csv(s) { gsub(/"/, "", s); return "\"" trim(s)"\"" } # canon(s) — apply the section-7 VM-name -> Tailscale/DNS-name map so # ci_name always uses the canonical fleet name [#705] function canon(s) { s = strip(s); return (s in map) ? map[s] : s } /^## / { sec = substr($0, 4) sub(/\(.*/, "", sec) gsub(/^[ \t]+|[ \t]+$/, "", sec) next } /^\|/ { # pass 1 (same file read twice): capture only the section-7 rename map if (FNR == NR) { if (sec ~ /^7\./) { for (i = 1; i <= NF; i++) f[i] = trim($i) if (f[2] == "" || f[2] ~ /^-+$/ || f[2] == "VM Name") next key = f[2]; sub(/[ (].*/, "", key) map[key] = trim(f[3]) } next } if (sec ~ /^7\./) next if (sec !~ /^[1-6]\./) next for (i = 1; i <= NF; i++) f[i] = trim($i) if (f[2] == "" || f[2] ~ /^-+$/) next if (f[2] == "Host" || f[2] == "VMID" || f[2] == "Name" || f[2] == "DNS Name") next status = (index($0, "RETIRED") > 0) ? "retired" : "active" if (sec ~ /^1\./) printf "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n", "hypervisor", csv(canon(f[2])), "", "", csv(f[3] "; CPU " f[4] "; RAM " f[5]), csv(f[6]), csv(f[8]), csv(f[9]), csv(f[10]), csv("mgmt " f[7]), status, csv("307 s1") else if (sec ~ /^2\./) printf "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n", "vm-prod", csv(canon(f[3])), csv(f[4]), csv(f[2]), csv("CPU " f[5] "; RAM " f[6] "; TS? " f[7]), csv(f[8]), "", csv(f[10]), csv(f[9]), "", status, csv("307 s2") else if (sec ~ /^3\./) printf "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n", "vm-sectestbed", csv(canon(f[3])), "pfv-tsys5", csv(f[2]), "", csv(f[5]), "", csv(f[7]), csv(f[6]), "", status, csv("307 s3") else if (sec ~ /^4\./) printf "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n", "vm-preprod", csv(canon(f[3])), "pfv-tsys5", csv(f[2]), "", csv(f[5]), "", csv(f[7]), csv(f[6]), "", status, csv("307 s4") else if (sec ~ /^5\./) printf "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n", "physical-sbc", csv(canon(f[2])), "", "", "", csv(f[3]), "", "", csv(f[5]), csv("dns " f[4]), status, csv("307 s5") else if (sec ~ /^6\./) printf "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n", "stale-dns-record", csv(f[2]), "", "", "", "", "", "", "", "", "retired", csv("307 s6: " f[4]) } ' "$1" "$1"