diff --git a/generate_template_docs.py b/generate_template_docs.py new file mode 100644 index 0000000..a4171ab --- /dev/null +++ b/generate_template_docs.py @@ -0,0 +1,190 @@ +import yaml +import sys +import os + +def load_yaml(file_path): + with open(file_path, 'r', encoding='utf-8') as f: + return yaml.safe_load(f) + +def get_priority_icon(priority): + icons = { + 'INFO': 'ℹ️', + 'WARNING': '⚠️', + 'AVERAGE': '🚨', + 'HIGH': '🚨', + 'DISASTER': '🔥' + } + return icons.get(priority, '❓') + +def format_trigger(trigger, is_prototype=False): + priority = trigger.get('priority', 'INFO') + icon = get_priority_icon(priority) + name = trigger.get('name', 'Unknown Trigger') + event_name = trigger.get('event_name', name) + + # Use event_name for display if it's richer, but standard usually puts name in the doc + # The reference doc uses "Name" field style but sometimes "Event Name" content might be more descriptive + # Looking at reference: + # - [AVERAGE] **🚨 DHCP Parado: Servidor DHCP não está em execução** + # The YAML trigger name is: '🚨 DHCP Parado: Servidor DHCP não está em execução' + # So it uses the Trigger Name directly. + + return f"- [{priority}] **{name}**" + +def generate_markdown(template_data): + # Depending on export structure, 'zabbix_export' root might be present + if 'zabbix_export' in template_data: + templates = template_data['zabbix_export'].get('templates', []) + else: + # Fallback if just raw template list + templates = template_data.get('templates', []) + + if not templates: + return "No templates found." + + # Process first template found (usually one per file) + template = templates[0] + + output = [] + + # Header + name = template.get('name', 'N/A') + description = template.get('description', '').strip() + + output.append(f"# Documentação: {name}") + output.append("") + output.append(f"**Template:** {name}") + output.append("**Descrição:**") + output.append(description) + output.append("") + + # Items + items = template.get('items', []) + output.append("## Itens Monitorados") + output.append("") + output.append("### Itens Globais") + + for item in items: + item_name = item.get('name', 'Unknown') + item_key = item.get('key', 'Unknown') + output.append(f"- **{item_name}** (`{item_key}`)") + + output.append("") + + # Discovery Rules + discovery_rules = template.get('discovery_rules', []) + if discovery_rules: + output.append("### Regras de Descoberta (LLD)") + output.append("") + for rule in discovery_rules: + rule_name = rule.get('name', 'Unknown') + rule_key = rule.get('key', 'Unknown') + output.append(f"#### {rule_name} (`{rule_key}`)") + + prototypes = rule.get('item_prototypes', []) + if prototypes: + output.append(" - **Protótipos de Itens:**") + for proto in prototypes: + p_name = proto.get('name', 'Unknown') + p_key = proto.get('key', 'Unknown') + output.append(f" - {p_name} (`{p_key}`)") + output.append("") + + # Triggers + # Triggers can be top-level (under template) or inside discovery rules (prototypes) + + triggers = template.get('items', []) # Actually triggers are under 'items' in some exports? No, typically under 'templates' -> 'items' -> 'triggers' key IS NOT STANDARD. + # Wait, in 7.0 export format: + # templates: + # - items: + # - triggers: ... (triggers linked to items? No, standard Zabbix export puts triggers list under the template object usually, OR under items? Let's check YAML structure) + + # Checking file content from previous turn: + # Items have 'triggers' list inside them! + # e.g. + # - uuid: ... + # name: Status do servidor DHCP + # ... + # triggers: + # - uuid: ... + # expression: ... + # name: '🚨 DHCP Parado: Servidor DHCP não está em execução' + + # So we need to collect triggers from all items. + + global_triggers = [] + for item in items: + if 'triggers' in item: + global_triggers.extend(item['triggers']) + + output.append("## Alertas (Triggers)") + output.append("") + output.append("### Triggers Globais") + + # Sort triggers by name or severity? Reference doc seems arbitrary or definition order. + # Let's keep definition order or sort by name. + + for trigger in global_triggers: + output.append(format_trigger(trigger)) + + output.append("") + + # Trigger Prototypes + if discovery_rules: + output.append("### Protótipos de Triggers (LLD)") + output.append("") + + for rule in discovery_rules: + rule_name = rule.get('name', 'Unknown rule') + output.append(f"**Regra: {rule_name}**") + + # Trigger prototypes are under discovery rule -> trigger_prototypes (older) or + # item_prototypes -> trigger_prototypes ? + # Looking at previous file view: + # - uuid: ... + # name: 'Interface [{#IFNAME}({#IFALIAS})]: Pacotes de entrada descartados' + # ... + # trigger_prototypes: + # - uuid: ... + # name: '🐢 Congestionamento: Descartes na interface {#IFNAME}' + + # So they are nested in item_prototypes. + + prototypes = [] + item_prototypes = rule.get('item_prototypes', []) + for ip in item_prototypes: + if 'trigger_prototypes' in ip: + prototypes.extend(ip['trigger_prototypes']) + + for proto in prototypes: + output.append(format_trigger(proto, is_prototype=True)) + + output.append("") + + return "\n".join(output) + +if __name__ == "__main__": + if len(sys.argv) < 2: + print("Usage: python generate_template_docs.py ") + sys.exit(1) + + file_path = sys.argv[1] + + try: + data = load_yaml(file_path) + markdown = generate_markdown(data) + + # Output to same dir as YAML with .md extension, or print to stdout? + # User asked to generate documentation. + # Let's write to file for convenience, similar name. + + base_name = os.path.splitext(file_path)[0] + output_path = base_name + "_generated.md" + + with open(output_path, 'w', encoding='utf-8') as f: + f.write(markdown) + + print(f"Documentation generated at: {output_path}") + + except Exception as e: + print(f"Error: {e}") diff --git a/templates_gold/documentation_pfsense_snmp.md b/templates_gold/documentation_pfsense_snmp.md index 6617ddd..bb1dcec 100644 --- a/templates_gold/documentation_pfsense_snmp.md +++ b/templates_gold/documentation_pfsense_snmp.md @@ -14,7 +14,6 @@ HOST-RESOURCES-MIB Gerado originalmente pela ferramenta oficial "Templator", Otimizado para Padrão Gold (Arthur) - ## Itens Monitorados ### Itens Globais @@ -77,14 +76,19 @@ Gerado originalmente pela ferramenta oficial "Templator", Otimizado para Padrão - [AVERAGE] **🚨 DHCP Parado: Servidor DHCP não está em execução** - [AVERAGE] **🚨 DNS Parado: Servidor DNS (Unbound) não está em execução** - [AVERAGE] **🚨 WebServer Parado: Nginx não está rodando** +- [WARNING] **🧩 Fragmentação Excessiva IPv4** +- [WARNING] **🛡️ Possível Ataque/Scan: Pico de Bloqueios** - [HIGH] **🚨 Firewall Desligado: Packet Filter inativo** - [WARNING] **⚠️ Tabela de Rastreamento Cheia: Uso elevado ({ITEM.LASTVALUE1}%)** +- [HIGH] **⏳ Source Tracking cheia em < 1h (Previsão)** - [WARNING] **🔥 Tabela de Estados Crítica: Risco de bloqueio ({ITEM.LASTVALUE1}%)** +- [HIGH] **⏳ Tabela de Estados cheia em < 1h (Previsão)** - [WARNING] **🚨 Falha SNMP: Sem coleta de dados no pfSense** ### Protótipos de Triggers (LLD) **Regra: Descoberta de interfaces de rede** -- [INFO] **ℹ️ PFSense: Interface [{#IFNAME}({#IFALIAS})]: Velocidade da Ethernet diminuiu** -- [WARNING] **⚠️ PFSense: Interface [{#IFNAME}({#IFALIAS})]: Alto uso de banda de entrada** -- [WARNING] **⚠️ PFSense: Interface [{#IFNAME}({#IFALIAS})]: Alto uso de banda de saída** +- [WARNING] **🐢 Congestionamento: Descartes na interface {#IFNAME}** +- [WARNING] **⚠️ PFSense: Interface [{#IFNAME}({#IFALIAS})]: Alta taxa de erros de entrada** +- [WARNING] **⚠️ PFSense: Interface [{#IFNAME}({#IFALIAS})]: Alta taxa de erros de saída** +- [AVERAGE] **🔌 PFSense: Interface [{#IFNAME}({#IFALIAS})]: Link indisponível**