All checks were successful
Build and Release / Build Windows Exe (push) Successful in 10s
95 lines
3.2 KiB
Python
95 lines
3.2 KiB
Python
from typing import List, Dict, Any
|
|
from .models import Server, Flow
|
|
from .network import to_mgt_ip
|
|
|
|
def generate_inventory(servers: Dict[str, Server], flows: List[Flow]) -> Dict[str, Any]:
|
|
"""
|
|
Generates the Ansible inventory dictionary.
|
|
servers: Dict[Reference, Server]
|
|
flows: List[Flow]
|
|
"""
|
|
|
|
# Build Lookup Map: IP -> Server
|
|
# Note: A server might have multiple IPs (e.g. Mgt, Public, Private).
|
|
# The 'Server' object mainly captures the Management IP or the one listed in the "IP Address" column.
|
|
# If the WIF has "Source Public IP" and that differs from "IP Address" in Servers tab,
|
|
# we might miss it if we only index the primary IP.
|
|
# However, strict filtering means we trust the 'Servers' tab.
|
|
|
|
ip_to_server = {}
|
|
for s in servers.values():
|
|
# Index all Management IPs
|
|
for ip in s.ip_addresses:
|
|
ip_to_server[ip] = s
|
|
|
|
# Index all Production IPs
|
|
for ip in s.production_ips:
|
|
ip_to_server[ip] = s
|
|
|
|
# Also index by reference/hostname for DNS matches
|
|
if s.reference:
|
|
ip_to_server[s.reference.lower()] = s
|
|
if s.hostname:
|
|
ip_to_server[s.hostname.lower()] = s
|
|
|
|
inventory_hosts = {}
|
|
|
|
# Process flows
|
|
match_count = 0
|
|
drop_count = 0
|
|
|
|
for flow in flows:
|
|
# Find source server
|
|
server = ip_to_server.get(flow.source_ip)
|
|
|
|
if not server:
|
|
# Try DNS resolution (Public IP -> Management FQDN)
|
|
mgt_dns = to_mgt_ip(flow.source_ip)
|
|
if mgt_dns:
|
|
# mgt_dns might be "server.ds.gc.ca".
|
|
# Our keys might be "server" or "server.ds.gc.ca" or IPs
|
|
# Try exact match
|
|
server = ip_to_server.get(mgt_dns.lower())
|
|
|
|
# If not found, try shortname?
|
|
if not server:
|
|
short = mgt_dns.split('.')[0]
|
|
server = ip_to_server.get(short.lower())
|
|
|
|
if not server:
|
|
drop_count += 1
|
|
if drop_count <= 5: # Debug spam limit
|
|
print(f"Dropping flow {flow.flow_id}: Source {flow.source_ip} (Mgt: {mgt_dns}) not found in Servers tab.")
|
|
continue
|
|
|
|
match_count += 1
|
|
|
|
# Prepare host entry if new
|
|
# We use the Hostname (from Server Name col) -> Reference (cleaned) -> IP match
|
|
host_key = server.hostname or server.reference or server.primary_ip
|
|
|
|
if host_key not in inventory_hosts:
|
|
host_vars = server.get_ansible_vars()
|
|
host_vars['flows'] = []
|
|
inventory_hosts[host_key] = host_vars
|
|
|
|
# Add flow
|
|
flow_entry = {
|
|
'flow_id': flow.flow_id,
|
|
'dest': flow.destination_ip,
|
|
'ports': flow.ports,
|
|
'protocol': flow.protocol
|
|
}
|
|
|
|
# Dedup check?
|
|
# Ideally we shouldn't have exact duplicates, but appending is safe.
|
|
inventory_hosts[host_key]['flows'].append(flow_entry)
|
|
|
|
print(f"Inventory Generation Report: Matches={match_count}, Dropped={drop_count}")
|
|
|
|
return {
|
|
'all': {
|
|
'hosts': inventory_hosts
|
|
}
|
|
}
|