63 lines
3.7 KiB
JavaScript
63 lines
3.7 KiB
JavaScript
import fs from 'node:fs'
|
|
import path from 'node:path'
|
|
import YAML from 'js-yaml'
|
|
|
|
const root = YAML.load(fs.readFileSync('configure/configure.yaml','utf8'))||{}
|
|
const inv = root.inventory||{}
|
|
const ttl = root?.meta?.dns_defaults?.ttl || 300
|
|
const zone = root?.meta?.domain || 'example.local'
|
|
|
|
const derive = (k,h) => {
|
|
const x={...h,fqdn:k}
|
|
if(!x.plan) x.plan = Number(x.layer)<=4?'VPN':'PKI'
|
|
if(!x.site) x.site = root?.meta?.site_default || 'dc1'
|
|
if(!x.tenant && x.plan==='PKI') x.tenant = root?.meta?.tenant_default || 'clp'
|
|
const vlan=Number(x.vlan), tid=(root?.meta?.tenant_id_map||{})[x.tenant||root?.meta?.tenant_default]
|
|
if((x.vni===null||x.vni===undefined||x.vni==='') && Number.isFinite(vlan) && tid) x.vni = tid*10000+vlan
|
|
x.monitoring=x.monitoring||{}; x.monitoring.prometheus=x.monitoring.prometheus||{}
|
|
if(!x.monitoring.prometheus.job){ const ln=(x.layer_name||'').toLowerCase(); x.monitoring.prometheus.job=ln||'node' }
|
|
x.dns=x.dns||{ ttl, records:[] }
|
|
return x
|
|
}
|
|
|
|
const prom = () => {
|
|
const jobs={}
|
|
for(const [k,v] of Object.entries(inv)){ const h=derive(k,v); const j=h?.monitoring?.prometheus?.job||'node'; (jobs[j]??=[]).push(h.fqdn) }
|
|
return YAML.dump({ scrape_configs: Object.entries(jobs).map(([j,t])=>({job_name:j, static_configs:[{targets:t}]})) })
|
|
}
|
|
const icinga = () => {
|
|
const out=[]
|
|
for(const [k,v] of Object.entries(inv)){
|
|
const h=derive(k,v); const addr=h.plan==='VPN'?(h.ip_internal||''):(h.ip_federative||h.ip_internal||'')
|
|
const groups=(h.hostgroups||[]).join(','); const checks=(h.checks||[]).map(c=>` vars.checks+=[\"${c}\"]`).join("\n")
|
|
out.push(`object Host "${h.fqdn}" {\n import "generic-host"\n address = "${addr}"\n vars.hostgroups = [${groups?groups.split(',').map(s=>`"${s.trim()}"`).join(', '):''}]\n${checks}\n}`)
|
|
}
|
|
return out.join("\n\n")
|
|
}
|
|
const zonefile = () => {
|
|
const rec=[`; zone ${zone}`, `$TTL ${ttl}`]
|
|
for(const [k,v] of Object.entries(inv)){
|
|
const h=derive(k,v)
|
|
if(h?.dns?.records?.length){ for(const r of h.dns.records){ if(!r?.type) continue; const name=k.replace(`.${zone}`,'@'); const val=(r.value||'').replace?.('{zone}', zone) ?? r.value; rec.push(`${name} ${r.ttl||ttl} IN ${r.type} ${val}`) } }
|
|
else { const ip=h.plan==='VPN'?h.ip_internal:(h.ip_federative||h.ip_internal); if(ip){ const name=k.replace(`.${zone}`,'@'); rec.push(`${name} ${ttl} IN A ${ip}`) } }
|
|
}
|
|
return rec.join("\n")
|
|
}
|
|
const ansible = () => {
|
|
const groups={all:[]}
|
|
for(const [k,v] of Object.entries(inv)){ const h=derive(k,v); groups.all.push(k); for(const g of [`layer_${h.layer||0}`, `plan_${(h.plan||'').toLowerCase()}`, (h.layer_name||'').toLowerCase(), ...((h?.ansible?.groups)||[])] ){ if(!g) continue; (groups[g]??=[]).push(k) } }
|
|
const lines=[]; for(const [g,hs] of Object.entries(groups)){ lines.push(`[${g}]`); hs.sort().forEach(n=>lines.push(n)); lines.push('') } ; return lines.join("\n")
|
|
}
|
|
const netbox = () => {
|
|
const rows=[["name","site","device_role","device_type","primary_ip4","tenant","tags"].join(",")]
|
|
for(const [k,v] of Object.entries(inv)){ const h=derive(k,v); const nb=h.netbox||{}; const ip=h.plan==='VPN'?(h.ip_internal||''):(h.ip_federative||h.ip_internal||''); const r=[k, nb.site||"DC1", nb.device_role||"Server", nb.device_type||"VM", ip, nb.tenant||"Chezlepro", (h.tags||[]).join('|')]; rows.push(r.map(x=>`"${String(x).replaceAll('"','""')}"`).join(",")) }
|
|
return rows.join("\n")
|
|
}
|
|
|
|
fs.mkdirSync('out',{recursive:true})
|
|
fs.writeFileSync('out/prometheus-targets.yaml', prom())
|
|
fs.writeFileSync('out/icinga-hosts.conf', icinga())
|
|
fs.writeFileSync('out/zonefile.zone', zonefile())
|
|
fs.writeFileSync('out/inventory.ini', ansible())
|
|
fs.writeFileSync('out/netbox.csv', netbox())
|
|
console.log('✅ exports: ./out')
|