multivendor-cli-configurator / scripts /patch_yang_more_vendors.py
gesh75's picture
Upload folder using huggingface_hub
1bd64c1 verified
Raw History Blame Contribute Delete
24.9 kB
#!/usr/bin/env python3
"""
patch_yang_more_vendors.py — close Automate fallback gaps.
Previously Huawei / NVIDIA / SONiC / Extreme / Mikrotik fell through to
AUTO_*.Cisco (dangerous YANG/IOS snippets). This pass injects CLI-first
Netmiko/Ansible renderers for those vendors into every AUTO_* map.
Idempotent via /* MORE_VENDOR_AUTO_EXT */ marker.
"""
from __future__ import annotations
import pathlib
import re
import sys
ROOT = pathlib.Path(__file__).resolve().parent.parent
HTML = ROOT / "index.html"
MARKER = "/* MORE_VENDOR_AUTO_EXT — Huawei/NVIDIA/SONiC/Extreme/Mikrotik */"
MORE_HELPERS = r'''
/* MORE_VENDOR_AUTO_EXT — Huawei/NVIDIA/SONiC/Extreme/Mikrotik */
function moreIfaceIpv4(vendor, v){
if(vendor==="Huawei") return _withDev(_autoCliBundle("Huawei VRP interface IPv4",
[`system-view`,`interface ${v.ifname}`,`ip address ${v.ip} ${v.mask}`,`quit`],
`- name: VRP IPv4 ${v.ifname}
community.network.ce_config:
lines:
- interface ${v.ifname}
- ip address ${v.ip} ${v.mask}`), "huawei");
if(vendor==="NVIDIA") return _withDev(_autoCliBundle("NVIDIA NVUE interface IPv4",
[`nv set interface ${v.ifname} ip address ${v.ip}/${v.cidr}`,`nv config apply`],
`- name: NVUE IPv4 ${v.ifname}
nvidia.nvue.command:
commands:
- nv set interface ${v.ifname} ip address ${v.ip}/${v.cidr}
- nv config apply`), "linux");
if(vendor==="SONiC") return _withDev(_autoCliBundle("SONiC interface IPv4",
[`sudo config interface ip add ${v.ifname} ${v.ip}/${v.cidr}`],
`- name: SONiC IPv4 ${v.ifname}
ansible.builtin.shell: sudo config interface ip add ${v.ifname} ${v.ip}/${v.cidr}`), "linux");
if(vendor==="Extreme") return _withDev(_autoCliBundle("Extreme EXOS interface IPv4",
[`configure vlan ${v.ifname} ipaddress ${v.ip} ${v.mask}`],
`- name: EXOS IPv4
community.network.exos_config:
lines:
- configure vlan ${v.ifname} ipaddress ${v.ip} ${v.mask}`), "extreme_exos");
if(vendor==="Mikrotik") return _withDev(_autoCliBundle("RouterOS interface IPv4",
[`/ip address add address=${v.ip}/${v.cidr} interface=${v.ifname}`],
`- name: RouterOS IPv4
community.routeros.command:
commands:
- /ip address add address=${v.ip}/${v.cidr} interface=${v.ifname}`), "mikrotik_routeros");
return null;
}
function moreStatic(vendor, v){
if(vendor==="Huawei") return _withDev(_autoCliBundle("Huawei static route",
[`system-view`,`ip route-static ${v.prefix} ${v.mask} ${v.nh}`],
`- name: VRP static
community.network.ce_config:
lines:
- ip route-static ${v.prefix} ${v.mask} ${v.nh}`), "huawei");
if(vendor==="NVIDIA") return _withDev(_autoCliBundle("NVUE static route",
[`nv set vrf default router static ${v.prefix}/${v.cidr} via ${v.nh}`,`nv config apply`],
`- name: NVUE static
nvidia.nvue.command:
commands:
- nv set vrf default router static ${v.prefix}/${v.cidr} via ${v.nh}
- nv config apply`), "linux");
if(vendor==="SONiC") return _withDev(_autoCliBundle("SONiC static route",
[`sudo config route add prefix ${v.prefix}/${v.cidr} nexthop ${v.nh}`],
`- name: SONiC static
ansible.builtin.shell: sudo config route add prefix ${v.prefix}/${v.cidr} nexthop ${v.nh}`), "linux");
if(vendor==="Extreme") return _withDev(_autoCliBundle("EXOS static route",
[`configure iproute add ${v.prefix} ${v.mask} ${v.nh}`],
`- name: EXOS static
community.network.exos_config:
lines:
- configure iproute add ${v.prefix} ${v.mask} ${v.nh}`), "extreme_exos");
if(vendor==="Mikrotik") return _withDev(_autoCliBundle("RouterOS static route",
[`/ip route add dst-address=${v.prefix}/${v.cidr} gateway=${v.nh}`],
`- name: RouterOS static
community.routeros.command:
commands:
- /ip route add dst-address=${v.prefix}/${v.cidr} gateway=${v.nh}`), "mikrotik_routeros");
return null;
}
function moreOspf(vendor, v){
const area = v.area || "0.0.0.0";
if(vendor==="Huawei") return _withDev(_autoCliBundle("Huawei OSPF",
[`system-view`,`ospf 1`,`area ${area}`,`network ${v.net || "10.0.0.0"} ${v.wildcard || "0.0.0.255"}`],
`- name: VRP OSPF
community.network.ce_config:
lines:
- ospf 1
- area ${area}
- network ${v.net || "10.0.0.0"} ${v.wildcard || "0.0.0.255"}`), "huawei");
if(vendor==="NVIDIA") return _withDev(_autoCliBundle("NVUE OSPF",
[`nv set vrf default router ospf area ${area}`,`nv config apply`],
`- name: NVUE OSPF
nvidia.nvue.command:
commands:
- nv set vrf default router ospf area ${area}
- nv config apply`), "linux");
if(vendor==="SONiC") return _withDev(_autoCliBundle("SONiC OSPF via FRR vtysh",
[`sudo vtysh -c 'configure terminal' -c 'router ospf' -c 'network ${v.net || "10.0.0.0"}/24 area ${area}' -c 'end' -c 'write'`],
`- name: SONiC OSPF
ansible.builtin.shell: sudo vtysh -c 'configure terminal' -c 'router ospf' -c 'network ${v.net || "10.0.0.0"}/24 area ${area}' -c 'end' -c 'write'`), "linux");
if(vendor==="Extreme") return _withDev(_autoCliBundle("EXOS OSPF",
[`enable ospf`,`configure ospf add vlan ${v.ifname || "UNDERLAY"} area ${area}`],
`- name: EXOS OSPF
community.network.exos_config:
lines:
- enable ospf
- configure ospf add vlan ${v.ifname || "UNDERLAY"} area ${area}`), "extreme_exos");
if(vendor==="Mikrotik") return _withDev(_autoCliBundle("RouterOS OSPF",
[`/routing ospf instance add name=def redistribute=connected`,`/routing ospf interface-template add interfaces=${v.ifname} area=backbone`],
`- name: RouterOS OSPF
community.routeros.command:
commands:
- /routing ospf instance add name=def redistribute=connected`), "mikrotik_routeros");
return null;
}
function moreBgp(vendor, v){
if(vendor==="Huawei") return _withDev(_autoCliBundle("Huawei BGP neighbor",
[`system-view`,`bgp ${v.local_as}`,`peer ${v.peer} as-number ${v.remote_as}`],
`- name: VRP BGP
community.network.ce_config:
lines:
- bgp ${v.local_as}
- peer ${v.peer} as-number ${v.remote_as}`), "huawei");
if(vendor==="NVIDIA") return _withDev(_autoCliBundle("NVUE BGP neighbor",
[`nv set vrf default router bgp autonomous-system ${v.local_as}`,`nv set vrf default router bgp neighbor ${v.peer} remote-as ${v.remote_as}`,`nv config apply`],
`- name: NVUE BGP
nvidia.nvue.command:
commands:
- nv set vrf default router bgp autonomous-system ${v.local_as}
- nv set vrf default router bgp neighbor ${v.peer} remote-as ${v.remote_as}
- nv config apply`), "linux");
if(vendor==="SONiC") return _withDev(_autoCliBundle("SONiC BGP neighbor",
[`sudo config bgp autonomous-system ${v.local_as}`,`sudo config bgp neighbor add ${v.peer} remote-as ${v.remote_as}`],
`- name: SONiC BGP
ansible.builtin.shell: |
sudo config bgp autonomous-system ${v.local_as}
sudo config bgp neighbor add ${v.peer} remote-as ${v.remote_as}`), "linux");
if(vendor==="Extreme") return _withDev(_autoCliBundle("EXOS BGP neighbor",
[`enable bgp`,`configure bgp as-number ${v.local_as}`,`configure bgp add neighbor ${v.peer} remote-as ${v.remote_as}`],
`- name: EXOS BGP
community.network.exos_config:
lines:
- enable bgp
- configure bgp as-number ${v.local_as}
- configure bgp add neighbor ${v.peer} remote-as ${v.remote_as}`), "extreme_exos");
if(vendor==="Mikrotik") return _withDev(_autoCliBundle("RouterOS BGP neighbor",
[`/routing bgp connection add name=to-peer remote.address=${v.peer} remote.as=${v.remote_as} local.role=ebgp`],
`- name: RouterOS BGP
community.routeros.command:
commands:
- /routing bgp connection add name=to-peer remote.address=${v.peer} remote.as=${v.remote_as} local.role=ebgp`), "mikrotik_routeros");
return null;
}
function moreVlan(vendor, v){
if(vendor==="Huawei") return _withDev(_autoCliBundle("Huawei VLAN",
[`system-view`,`vlan ${v.id}`,`name ${v.name}`],
`- name: VRP VLAN
community.network.ce_config:
lines:
- vlan ${v.id}
- name ${v.name}`), "huawei");
if(vendor==="NVIDIA") return _withDev(_autoCliBundle("NVUE VLAN",
[`nv set bridge domain br_default vlan ${v.id}`,`nv config apply`],
`- name: NVUE VLAN
nvidia.nvue.command:
commands:
- nv set bridge domain br_default vlan ${v.id}
- nv config apply`), "linux");
if(vendor==="SONiC") return _withDev(_autoCliBundle("SONiC VLAN",
[`sudo config vlan add ${v.id}`],
`- name: SONiC VLAN
ansible.builtin.shell: sudo config vlan add ${v.id}`), "linux");
if(vendor==="Extreme") return _withDev(_autoCliBundle("EXOS VLAN",
[`create vlan ${v.name} tag ${v.id}`],
`- name: EXOS VLAN
community.network.exos_config:
lines:
- create vlan ${v.name} tag ${v.id}`), "extreme_exos");
if(vendor==="Mikrotik") return _withDev(_autoCliBundle("RouterOS VLAN",
[`/interface vlan add name=${v.name} vlan-id=${v.id} interface=bridge1`],
`- name: RouterOS VLAN
community.routeros.command:
commands:
- /interface vlan add name=${v.name} vlan-id=${v.id} interface=bridge1`), "mikrotik_routeros");
return null;
}
function moreHostname(vendor, v){
if(vendor==="Huawei") return _withDev(_autoCliBundle("Huawei sysname",
[`system-view`,`sysname ${v.hostname}`],
`- name: VRP sysname
community.network.ce_config:
lines:
- sysname ${v.hostname}`), "huawei");
if(vendor==="NVIDIA") return _withDev(_autoCliBundle("NVUE hostname",
[`nv set system hostname ${v.hostname}`,`nv config apply`],
`- name: NVUE hostname
nvidia.nvue.command:
commands:
- nv set system hostname ${v.hostname}
- nv config apply`), "linux");
if(vendor==="SONiC") return _withDev(_autoCliBundle("SONiC hostname",
[`sudo config hostname ${v.hostname}`],
`- name: SONiC hostname
ansible.builtin.shell: sudo config hostname ${v.hostname}`), "linux");
if(vendor==="Extreme") return _withDev(_autoCliBundle("EXOS hostname",
[`configure snmp sysName ${v.hostname}`],
`- name: EXOS hostname
community.network.exos_config:
lines:
- configure snmp sysName ${v.hostname}`), "extreme_exos");
if(vendor==="Mikrotik") return _withDev(_autoCliBundle("RouterOS identity",
[`/system identity set name=${v.hostname}`],
`- name: RouterOS identity
community.routeros.command:
commands:
- /system identity set name=${v.hostname}`), "mikrotik_routeros");
return null;
}
function moreNtp(vendor, v){
if(vendor==="Huawei") return _withDev(_autoCliBundle("Huawei NTP",
[`system-view`,`ntp-service unicast-server ${v.server}`],
`- name: VRP NTP
community.network.ce_config:
lines:
- ntp-service unicast-server ${v.server}`), "huawei");
if(vendor==="NVIDIA") return _withDev(_autoCliBundle("NVUE NTP",
[`nv set system ntp server ${v.server}`,`nv config apply`],
`- name: NVUE NTP
nvidia.nvue.command:
commands:
- nv set system ntp server ${v.server}
- nv config apply`), "linux");
if(vendor==="SONiC") return _withDev(_autoCliBundle("SONiC NTP",
[`sudo config ntp add ${v.server}`],
`- name: SONiC NTP
ansible.builtin.shell: sudo config ntp add ${v.server}`), "linux");
if(vendor==="Extreme") return _withDev(_autoCliBundle("EXOS NTP",
[`configure ntp server add ${v.server}`,`enable ntp`],
`- name: EXOS NTP
community.network.exos_config:
lines:
- configure ntp server add ${v.server}
- enable ntp`), "extreme_exos");
if(vendor==="Mikrotik") return _withDev(_autoCliBundle("RouterOS NTP",
[`/system ntp client set enabled=yes servers=${v.server}`],
`- name: RouterOS NTP
community.routeros.command:
commands:
- /system ntp client set enabled=yes servers=${v.server}`), "mikrotik_routeros");
return null;
}
function moreSyslog(vendor, v){
if(vendor==="Huawei") return _withDev(_autoCliBundle("Huawei syslog",
[`system-view`,`info-center loghost ${v.host}`],
`- name: VRP syslog
community.network.ce_config:
lines:
- info-center loghost ${v.host}`), "huawei");
if(vendor==="NVIDIA") return _withDev(_autoCliBundle("NVUE syslog",
[`nv set system syslog server ${v.host}`,`nv config apply`],
`- name: NVUE syslog
nvidia.nvue.command:
commands:
- nv set system syslog server ${v.host}
- nv config apply`), "linux");
if(vendor==="SONiC") return _withDev(_autoCliBundle("SONiC syslog",
[`sudo config syslog add ${v.host}`],
`- name: SONiC syslog
ansible.builtin.shell: sudo config syslog add ${v.host}`), "linux");
if(vendor==="Extreme") return _withDev(_autoCliBundle("EXOS syslog",
[`configure syslog add ${v.host} local use-local-time`],
`- name: EXOS syslog
community.network.exos_config:
lines:
- configure syslog add ${v.host} local use-local-time`), "extreme_exos");
if(vendor==="Mikrotik") return _withDev(_autoCliBundle("RouterOS syslog",
[`/system logging action set remote remote=${v.host}`],
`- name: RouterOS syslog
community.routeros.command:
commands:
- /system logging action set remote remote=${v.host}`), "mikrotik_routeros");
return null;
}
function moreGeneric(vendor, lines, ansible, dev){
return _withDev(_autoCliBundle(vendor+" config", lines, ansible), dev);
}
'''
MORE_WRAPPERS = {
"AUTO_IFACE_IPV4": " Huawei: v => moreIfaceIpv4('Huawei', v),\n NVIDIA: v => moreIfaceIpv4('NVIDIA', v),\n SONiC: v => moreIfaceIpv4('SONiC', v),\n Extreme: v => moreIfaceIpv4('Extreme', v),\n Mikrotik: v => moreIfaceIpv4('Mikrotik', v),",
"AUTO_STATIC": " Huawei: v => moreStatic('Huawei', v),\n NVIDIA: v => moreStatic('NVIDIA', v),\n SONiC: v => moreStatic('SONiC', v),\n Extreme: v => moreStatic('Extreme', v),\n Mikrotik: v => moreStatic('Mikrotik', v),",
"AUTO_OSPF": " Huawei: v => moreOspf('Huawei', v),\n NVIDIA: v => moreOspf('NVIDIA', v),\n SONiC: v => moreOspf('SONiC', v),\n Extreme: v => moreOspf('Extreme', v),\n Mikrotik: v => moreOspf('Mikrotik', v),",
"AUTO_BGP": " Huawei: v => moreBgp('Huawei', v),\n NVIDIA: v => moreBgp('NVIDIA', v),\n SONiC: v => moreBgp('SONiC', v),\n Extreme: v => moreBgp('Extreme', v),\n Mikrotik: v => moreBgp('Mikrotik', v),",
"AUTO_VLAN": " Huawei: v => moreVlan('Huawei', v),\n NVIDIA: v => moreVlan('NVIDIA', v),\n SONiC: v => moreVlan('SONiC', v),\n Extreme: v => moreVlan('Extreme', v),\n Mikrotik: v => moreVlan('Mikrotik', v),",
"AUTO_HOSTNAME": " Huawei: v => moreHostname('Huawei', v),\n NVIDIA: v => moreHostname('NVIDIA', v),\n SONiC: v => moreHostname('SONiC', v),\n Extreme: v => moreHostname('Extreme', v),\n Mikrotik: v => moreHostname('Mikrotik', v),",
"AUTO_NTP": " Huawei: v => moreNtp('Huawei', v),\n NVIDIA: v => moreNtp('NVIDIA', v),\n SONiC: v => moreNtp('SONiC', v),\n Extreme: v => moreNtp('Extreme', v),\n Mikrotik: v => moreNtp('Mikrotik', v),",
"AUTO_SYSLOG": " Huawei: v => moreSyslog('Huawei', v),\n NVIDIA: v => moreSyslog('NVIDIA', v),\n SONiC: v => moreSyslog('SONiC', v),\n Extreme: v => moreSyslog('Extreme', v),\n Mikrotik: v => moreSyslog('Mikrotik', v),",
"AUTO_DEFAULTRT": " Huawei: v => moreStatic('Huawei', {prefix:'0.0.0.0', cidr:'0', mask:'0.0.0.0', nh:v.nh}),\n NVIDIA: v => moreStatic('NVIDIA', {prefix:'0.0.0.0', cidr:'0', mask:'0.0.0.0', nh:v.nh}),\n SONiC: v => moreStatic('SONiC', {prefix:'0.0.0.0', cidr:'0', mask:'0.0.0.0', nh:v.nh}),\n Extreme: v => moreStatic('Extreme', {prefix:'0.0.0.0', cidr:'0', mask:'0.0.0.0', nh:v.nh}),\n Mikrotik: v => moreStatic('Mikrotik', {prefix:'0.0.0.0', cidr:'0', mask:'0.0.0.0', nh:v.nh}),",
"AUTO_LOOPBACK": " Huawei: v => moreIfaceIpv4('Huawei', {ifname:v.name||'LoopBack0', ip:v.ip, mask:v.mask, cidr:v.cidr}),\n NVIDIA: v => moreIfaceIpv4('NVIDIA', {ifname:v.name||'lo', ip:v.ip, mask:v.mask, cidr:v.cidr}),\n SONiC: v => moreIfaceIpv4('SONiC', {ifname:v.name||'Loopback0', ip:v.ip, mask:v.mask, cidr:v.cidr}),\n Extreme: v => moreIfaceIpv4('Extreme', {ifname:v.name||'Default', ip:v.ip, mask:v.mask, cidr:v.cidr}),\n Mikrotik: v => moreIfaceIpv4('Mikrotik', {ifname:v.name||'bridge1', ip:v.ip, mask:v.mask, cidr:v.cidr}),",
"AUTO_SWITCHPORT": " Huawei: v => moreGeneric('Huawei', [`system-view`,`interface ${v.ifname}`,`port link-type access`,`port default vlan ${v.vlan}`], `- name: VRP access\\n community.network.ce_config:\\n lines:\\n - interface ${v.ifname}\\n - port default vlan ${v.vlan}`, 'huawei'),\n NVIDIA: v => moreGeneric('NVIDIA', [`nv set interface ${v.ifname} bridge domain br_default access ${v.vlan}`,`nv config apply`], `- name: NVUE access\\n nvidia.nvue.command:\\n commands: ['nv set interface ${v.ifname} bridge domain br_default access ${v.vlan}','nv config apply']`, 'linux'),\n SONiC: v => moreGeneric('SONiC', [`sudo config vlan member add ${v.vlan} ${v.ifname}`], `- name: SONiC access\\n ansible.builtin.shell: sudo config vlan member add ${v.vlan} ${v.ifname}`, 'linux'),\n Extreme: v => moreGeneric('Extreme', [`configure vlan ${v.vlan} add ports ${v.ifname} untagged`], `- name: EXOS access\\n community.network.exos_config:\\n lines:\\n - configure vlan ${v.vlan} add ports ${v.ifname} untagged`, 'extreme_exos'),\n Mikrotik: v => moreGeneric('Mikrotik', [`/interface bridge port set [find interface=${v.ifname}] pvid=${v.vlan}`], `- name: RouterOS access\\n community.routeros.command:\\n commands: ['/interface bridge port set [find interface=${v.ifname}] pvid=${v.vlan}']`, 'mikrotik_routeros'),",
"AUTO_IFDESC": " Huawei: v => moreGeneric('Huawei', [`system-view`,`interface ${v.ifname}`,`description ${v.desc}`], `- name: VRP ifDesc\\n community.network.ce_config:\\n lines:\\n - interface ${v.ifname}\\n - description ${v.desc}`, 'huawei'),\n NVIDIA: v => moreGeneric('NVIDIA', [`nv set interface ${v.ifname} description '${v.desc}'`,`nv config apply`], `- name: NVUE ifDesc\\n nvidia.nvue.command:\\n commands: [\"nv set interface ${v.ifname} description '${v.desc}'\",'nv config apply']`, 'linux'),\n SONiC: v => moreGeneric('SONiC', [`sudo config interface description ${v.ifname} '${v.desc}'`], `- name: SONiC ifDesc\\n ansible.builtin.shell: sudo config interface description ${v.ifname} '${v.desc}'`, 'linux'),\n Extreme: v => moreGeneric('Extreme', [`configure ports ${v.ifname} display-string ${v.desc}`], `- name: EXOS ifDesc\\n community.network.exos_config:\\n lines:\\n - configure ports ${v.ifname} display-string ${v.desc}`, 'extreme_exos'),\n Mikrotik: v => moreGeneric('Mikrotik', [`/interface set ${v.ifname} comment=\"${v.desc}\"`], `- name: RouterOS ifDesc\\n community.routeros.command:\\n commands: ['/interface set ${v.ifname} comment=\"${v.desc}\"']`, 'mikrotik_routeros'),",
"AUTO_TRUNK": " Huawei: v => moreGeneric('Huawei', [`system-view`,`interface ${v.ifname}`,`port link-type trunk`,`port trunk allow-pass vlan ${v.vlans}`], `- name: VRP trunk\\n community.network.ce_config:\\n lines:\\n - interface ${v.ifname}\\n - port trunk allow-pass vlan ${v.vlans}`, 'huawei'),\n NVIDIA: v => moreGeneric('NVIDIA', [`nv set interface ${v.ifname} bridge domain br_default vlan ${v.vlans}`,`nv config apply`], `- name: NVUE trunk\\n nvidia.nvue.command:\\n commands: ['nv set interface ${v.ifname} bridge domain br_default vlan ${v.vlans}','nv config apply']`, 'linux'),\n SONiC: v => moreGeneric('SONiC', [`sudo config vlan member add ${v.vlans.split(',')[0]} ${v.ifname} -t`], `- name: SONiC trunk\\n ansible.builtin.shell: sudo config vlan member add ${v.vlans.split(',')[0]} ${v.ifname} -t`, 'linux'),\n Extreme: v => moreGeneric('Extreme', [`configure vlan ${v.vlans.split(',')[0]} add ports ${v.ifname} tagged`], `- name: EXOS trunk\\n community.network.exos_config:\\n lines:\\n - configure vlan ${v.vlans.split(',')[0]} add ports ${v.ifname} tagged`, 'extreme_exos'),\n Mikrotik: v => moreGeneric('Mikrotik', [`/interface bridge vlan add bridge=bridge1 tagged=${v.ifname} vlan-ids=${v.vlans}`], `- name: RouterOS trunk\\n community.routeros.command:\\n commands: ['/interface bridge vlan add bridge=bridge1 tagged=${v.ifname} vlan-ids=${v.vlans}']`, 'mikrotik_routeros'),",
"AUTO_RADIUS": " Huawei: v => moreGeneric('Huawei', [`system-view`,`radius-server template AAA`,`radius-server shared-key cipher ${v.key}`,`radius-server authentication ${v.host}`], `- name: VRP RADIUS\\n community.network.ce_config:\\n lines:\\n - radius-server authentication ${v.host}`, 'huawei'),\n NVIDIA: v => moreGeneric('NVIDIA', [`nv set system aaa authentication-order radius`,`nv config apply`], `- name: NVUE RADIUS note\\n nvidia.nvue.command:\\n commands: ['nv set system aaa authentication-order radius','nv config apply']`, 'linux'),\n SONiC: v => moreGeneric('SONiC', [`# configure host PAM/RADIUS for SONiC mgmt plane`], `- name: SONiC RADIUS note\\n ansible.builtin.debug:\\n msg: configure host PAM RADIUS`, 'linux'),\n Extreme: v => moreGeneric('Extreme', [`configure radius-server add ${v.host} shared-secret ${v.key}`], `- name: EXOS RADIUS\\n community.network.exos_config:\\n lines:\\n - configure radius-server add ${v.host} shared-secret ${v.key}`, 'extreme_exos'),\n Mikrotik: v => moreGeneric('Mikrotik', [`/radius add address=${v.host} secret=${v.key} service=login`], `- name: RouterOS RADIUS\\n community.routeros.command:\\n commands: ['/radius add address=${v.host} secret=${v.key} service=login']`, 'mikrotik_routeros'),",
"AUTO_PORTCHANNEL": " Huawei: v => moreGeneric('Huawei', [`system-view`,`interface Eth-Trunk${v.pcid}`,`mode lacp-static`,`quit`,`interface ${v.ifname}`,`eth-trunk ${v.pcid}`], `- name: VRP Eth-Trunk\\n community.network.ce_config:\\n lines:\\n - interface ${v.ifname}\\n - eth-trunk ${v.pcid}`, 'huawei'),\n NVIDIA: v => moreGeneric('NVIDIA', [`nv set interface bond${v.pcid} bond member ${v.ifname}`,`nv config apply`], `- name: NVUE bond\\n nvidia.nvue.command:\\n commands: ['nv set interface bond${v.pcid} bond member ${v.ifname}','nv config apply']`, 'linux'),\n SONiC: v => moreGeneric('SONiC', [`sudo config portchannel add PortChannel${v.pcid}`,`sudo config portchannel member add PortChannel${v.pcid} ${v.ifname}`], `- name: SONiC LAG\\n ansible.builtin.shell: |\\n sudo config portchannel add PortChannel${v.pcid}\\n sudo config portchannel member add PortChannel${v.pcid} ${v.ifname}`, 'linux'),\n Extreme: v => moreGeneric('Extreme', [`enable sharing ${v.pcid} grouping ${v.ifname} algorithm address-based L3_L4 lacp`], `- name: EXOS LAG\\n community.network.exos_config:\\n lines:\\n - enable sharing ${v.pcid} grouping ${v.ifname} algorithm address-based L3_L4 lacp`, 'extreme_exos'),\n Mikrotik: v => moreGeneric('Mikrotik', [`/interface bonding add name=bond${v.pcid} slaves=${v.ifname} mode=802.3ad`], `- name: RouterOS bond\\n community.routeros.command:\\n commands: ['/interface bonding add name=bond${v.pcid} slaves=${v.ifname} mode=802.3ad']`, 'mikrotik_routeros'),",
}
def inject_helpers(text: str) -> str:
if MARKER in text:
return text
anchor = "/* Per-vendor template renderers — return {netconf, ncclient, ansible} */"
if anchor not in text:
raise SystemExit("AUTO renderer anchor not found")
return text.replace(anchor, MORE_HELPERS + "\n" + anchor, 1)
def inject_keys(text: str) -> str:
for name, block in MORE_WRAPPERS.items():
flag = f"/* more:{name} */"
if flag in text:
continue
# Prefer inserting after existing stack ext flag, else after const {
stack_flag = f"/* ext:{name} */"
if stack_flag in text:
# insert after the stack wrapper block — find flag and insert after next blank-ish
idx = text.find(stack_flag)
# find end of first vendor block cluster: look for blank line after Aruba/FRR keys
# Simpler: insert right after the flag line
nl = text.find("\n", idx)
insert_at = nl + 1
text = text[:insert_at] + flag + "\n" + block + "\n" + text[insert_at:]
continue
m = re.search(rf"(const\s+{name}\s*=\s*\{{)", text)
if not m:
print(f"WARN: {name} not found", file=sys.stderr)
continue
insert = m.group(1) + "\n" + flag + "\n" + block + "\n"
text = text[: m.start()] + insert + text[m.end() :]
return text
def main() -> None:
text = HTML.read_text()
if MARKER in text and all(f"/* more:{n} */" in text for n in MORE_WRAPPERS):
print("already patched")
return
text = inject_helpers(text)
text = inject_keys(text)
if "--dry-run" in sys.argv:
print("dry-run ok, would write", len(text), "bytes")
return
HTML.write_text(text)
print("patched", HTML, "bytes", len(text))
if __name__ == "__main__":
main()