Browse Source

Add support for dumping data to a hosts file.

TODO: This should probably dump everything, and not just changed
records.
Joe Clarke 5 months ago
parent
commit
f4377edd48
1 changed files with 50 additions and 3 deletions
  1. 50 3
      automation/services/netbox2cpnr.py

+ 50 - 3
automation/services/netbox2cpnr.py

@@ -456,6 +456,39 @@ def add_record(record: Union[ARecord, CNAMERecord, PTRRecord], primary_domain: s
         logger.warning(f"⛔️ Unexpected record of type {type(record)}")
 
 
+def dump_hosts(records: list[Union[ARecord, CNAMERecord, PTRRecord]], primary_domain: str, output_file: str) -> None:
+    """Dump the A and CNAME records to a hosts-like file
+
+    Args:
+        :records list: List of records to dump
+        :primary_domain str: Primary domain name to add if the record doesn't contain it
+        :output_file str: Path to the output file
+    """
+    aliases = {}
+    hosts = {}
+    for record in records:
+        if isinstance(record, PTRRecord):
+            continue
+
+        if isinstance(record, ARecord):
+            fqdn = f"{record.hostname}.{primary_domain}"
+            hosts[record.ip] = fqdn
+            if fqdn not in aliases:
+                aliases[fqdn] = [fqdn, record.hostname]
+            else:
+                aliases[fqdn] += [fqdn, record.hostname]
+        elif isinstance(record, CNAMERecord):
+            fqdn = f"{record.host.hostname}.{record.host.domain}"
+            if fqdn not in aliases:
+                aliases[fqdn] = [f"{record.alias}.{record.domain}"]
+            else:
+                aliases[fqdn].append(f"{record.alias}.{record.domain}")
+
+    with open(output_file, "a") as fd:
+        for ip, hname in hosts.items():
+            fd.write(f"{ip}\t{' '.join(aliases[hname])}\n")
+
+
 def parse_args() -> object:
     """Parse any command line arguments.
 
@@ -484,6 +517,8 @@ def parse_args() -> object:
     parser.add_argument(
         "--dummy", metavar="<DUMMY SERVER>", help="Override main DNS server with a dummy server (only used with --tenant", required=False
     )
+    parser.add_argument("--dump-hosts", action="store_true", help="Dump records to a hosts file", required=False)
+    parser.add_argument("--hosts-output", metavar="<OUTPUT_FILE>", help="Path to file to dump host records", required=False)
 
     args = parser.parse_args()
 
@@ -499,6 +534,10 @@ def parse_args() -> object:
         print("--dummy requires --tenant")
         exit(1)
 
+    if args.dump_hosts and not args.hosts_output:
+        print("A hosts output file must be specified")
+        exit(1)
+
     return args
 
 
@@ -517,6 +556,10 @@ def main():
 
     enb = ElementalNetbox()
 
+    if args.dump_hosts:
+        with open(args.hosts_output, "w") as fd:
+            fd.truncate()
+
     # 1. Get a list of all tenants.  If we work tenant-by-tenant, we will likely remain connected
     #    to the same DNS server.
     tenants = enb.tenancy.tenants.all()
@@ -544,18 +587,22 @@ def main():
             check_record, "check DNS record(s)", ip_addresses, "address", 20, False, primary_domain, edns, enb, wip_records
         )
 
-        # 4. If doing a dry-run, only print out the changes.
+        # 4. If desired, dump all hosts to a file.
+        if args.dump_hosts:
+            dump_hosts(wip_records.creates, primary_domain, args.hosts_output)
+
+        # 5. If doing a dry-run, only print out the changes.
         if args.dry_run:
             print_records(wip_records, primary_domain, tenant)
             continue
 
-        # 5. Process records to be deleted first.  Use thread pools again to parallelize this.
+        # 6. Process records to be deleted first.  Use thread pools again to parallelize this.
         success = launch_parallel_task(delete_record, "delete DNS record", wip_records.deletes, None, 20, True, primary_domain, edns)
 
         if not success:
             break
 
-        # 6. Process records to be added next.  Use thread pools again to parallelize this.
+        # 7. Process records to be added next.  Use thread pools again to parallelize this.
         launch_parallel_task(add_record, "add DNS record", wip_records.creates, "_name", 20, False, primary_domain, edns)
 
     # 7. Restart affected DNS servers.