netbox-plugin-dns 0.22.4__tar.gz → 0.22.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of netbox-plugin-dns might be problematic. Click here for more details.

Files changed (116) hide show
  1. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/PKG-INFO +11 -11
  2. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/README.md +9 -10
  3. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/__init__.py +3 -2
  4. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/api/serializers.py +1 -0
  5. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/filters/registrar.py +1 -0
  6. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/forms/registrar.py +11 -1
  7. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/forms/zone.py +31 -21
  8. netbox_plugin_dns-0.22.5/netbox_dns/management/commands/cleanup_rrset_ttl.py +62 -0
  9. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/models/record.py +141 -25
  10. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/models/zone.py +82 -18
  11. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/templates/netbox_dns/registrar.html +4 -0
  12. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/templates/netbox_dns/zone.html +7 -0
  13. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/pyproject.toml +5 -2
  14. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/LICENSE +0 -0
  15. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/api/nested_serializers.py +0 -0
  16. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/api/urls.py +0 -0
  17. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/api/views.py +0 -0
  18. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/apps.py +0 -0
  19. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/fields/__init__.py +0 -0
  20. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/fields/address.py +0 -0
  21. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/fields/network.py +0 -0
  22. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/fields/rfc2317.py +0 -0
  23. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/filters/__init__.py +0 -0
  24. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/filters/contact.py +0 -0
  25. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/filters/nameserver.py +0 -0
  26. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/filters/record.py +0 -0
  27. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/filters/view.py +0 -0
  28. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/filters/zone.py +0 -0
  29. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/forms/__init__.py +0 -0
  30. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/forms/contact.py +0 -0
  31. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/forms/nameserver.py +0 -0
  32. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/forms/record.py +0 -0
  33. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/forms/view.py +0 -0
  34. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/graphql/__init__.py +0 -0
  35. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/graphql/contact.py +0 -0
  36. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/graphql/nameserver.py +0 -0
  37. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/graphql/record.py +0 -0
  38. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/graphql/registrar.py +0 -0
  39. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/graphql/schema.py +0 -0
  40. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/graphql/view.py +0 -0
  41. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/graphql/zone.py +0 -0
  42. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/management/commands/cleanup_database.py +0 -0
  43. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/management/commands/setup_coupling.py +0 -0
  44. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/management/commands/update_soa.py +0 -0
  45. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0001_initial.py +0 -0
  46. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0001_squashed_netbox_dns_0_15.py +0 -0
  47. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0002_zone_default_ttl.py +0 -0
  48. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0003_soa_managed_records.py +0 -0
  49. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0004_create_ptr_for_a_aaaa_records.py +0 -0
  50. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0005_update_ns_records.py +0 -0
  51. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0006_zone_soa_serial_auto.py +0 -0
  52. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0007_alter_zone_soa_serial_auto.py +0 -0
  53. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0008_zone_status_names.py +0 -0
  54. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0009_netbox32.py +0 -0
  55. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0010_update_soa_records.py +0 -0
  56. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0011_add_view_model.py +0 -0
  57. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0012_adjust_zone_and_record.py +0 -0
  58. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0013_add_nameserver_zone_record_description.py +0 -0
  59. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0014_add_view_description.py +0 -0
  60. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0015_add_record_status.py +0 -0
  61. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0016_cleanup_ptr_records.py +0 -0
  62. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0017_alter_record_ttl.py +0 -0
  63. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0018_zone_arpa_network.py +0 -0
  64. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0019_update_ns_ttl.py +0 -0
  65. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0020_netbox_3_4.py +0 -0
  66. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0021_record_ip_address.py +0 -0
  67. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0022_search.py +0 -0
  68. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0023_alter_record_value.py +0 -0
  69. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0024_tenancy.py +0 -0
  70. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0025_ipam_coupling_cf.py +0 -0
  71. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0026_domain_registration.py +0 -0
  72. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0027_alter_registrar_iana_id.py +0 -0
  73. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/0028_rfc2317_fields.py +0 -0
  74. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/migrations/__init__.py +0 -0
  75. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/models/__init__.py +0 -0
  76. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/models/contact.py +0 -0
  77. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/models/nameserver.py +0 -0
  78. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/models/registrar.py +0 -0
  79. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/models/view.py +0 -0
  80. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/navigation.py +0 -0
  81. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/signals/__init__.py +0 -0
  82. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/signals/ipam_coupling.py +0 -0
  83. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/tables/__init__.py +0 -0
  84. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/tables/contact.py +0 -0
  85. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/tables/nameserver.py +0 -0
  86. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/tables/record.py +0 -0
  87. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/tables/registrar.py +0 -0
  88. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/tables/view.py +0 -0
  89. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/tables/zone.py +0 -0
  90. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/template_content.py +0 -0
  91. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/templates/netbox_dns/contact.html +0 -0
  92. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/templates/netbox_dns/nameserver.html +0 -0
  93. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/templates/netbox_dns/record/managed.html +0 -0
  94. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/templates/netbox_dns/record/related.html +0 -0
  95. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/templates/netbox_dns/record.html +0 -0
  96. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/templates/netbox_dns/related_dns_objects.html +0 -0
  97. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/templates/netbox_dns/view.html +0 -0
  98. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/templates/netbox_dns/zone/base.html +0 -0
  99. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/templates/netbox_dns/zone/child.html +0 -0
  100. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/templates/netbox_dns/zone/managed_record.html +0 -0
  101. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/templates/netbox_dns/zone/record.html +0 -0
  102. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/templates/netbox_dns/zone/registration.html +0 -0
  103. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/templates/netbox_dns/zone/rfc2317_child_zone.html +0 -0
  104. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/urls.py +0 -0
  105. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/utilities/__init__.py +0 -0
  106. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/utilities/ipam_coupling.py +0 -0
  107. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/validators/__init__.py +0 -0
  108. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/validators/dns_name.py +0 -0
  109. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/validators/rfc2317.py +0 -0
  110. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/views/__init__.py +0 -0
  111. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/views/contact.py +0 -0
  112. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/views/nameserver.py +0 -0
  113. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/views/record.py +0 -0
  114. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/views/registrar.py +0 -0
  115. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/views/view.py +0 -0
  116. {netbox_plugin_dns-0.22.4 → netbox_plugin_dns-0.22.5}/netbox_dns/views/zone.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: netbox-plugin-dns
3
- Version: 0.22.4
3
+ Version: 0.22.5
4
4
  Summary: NetBox DNS is a NetBox plugin for managing DNS data.
5
5
  Home-page: https://github.com/peteeckel/netbox-plugin-dns
6
6
  License: MIT
@@ -8,6 +8,7 @@ Keywords: netbox,netbox-plugin,dns
8
8
  Author: Peter Eckel
9
9
  Author-email: pete@netbox-dns.org
10
10
  Requires-Python: >=3.8,<4.0
11
+ Classifier: Development Status :: 5 - Production/Stable
11
12
  Classifier: License :: OSI Approved :: MIT License
12
13
  Classifier: Programming Language :: Python :: 3
13
14
  Classifier: Programming Language :: Python :: 3.8
@@ -19,16 +20,15 @@ Requires-Dist: dnspython (>=2.2.1,<3.0.0)
19
20
  Project-URL: Repository, https://github.com/peteeckel/netbox-plugin-dns
20
21
  Description-Content-Type: text/markdown
21
22
 
22
- <h1 align="center">NetBox DNS</h1>
23
-
24
- <p align="center"><i>NetBox DNS is a NetBox plugin for managing DNS views, zones, name servers and records.</i></p>
23
+ # NetBox DNS
24
+ The NetBox DNS plugin enables NetBox to manage operational DNS data such as name servers, zones, records and views, as well as registration data for domains. It can automate tasks like creating PTR records, generating zone serial numbers, NS and SOA records, as well as validate names and values values for resource records to ensure zone data is consistent, current and conforming to the relevant RFCs.
25
25
 
26
26
  <div align="center">
27
27
  <a href="https://pypi.org/project/netbox-plugin-dns/"><img src="https://img.shields.io/pypi/v/netbox-plugin-dns" alt="PyPi"/></a>
28
- <a href="https://github.com/peteeckel/netbox-plugin-dns/stargazers"><img src="https://img.shields.io/github/stars/peteeckel/netbox-plugin-dns" alt="Stars Badge"/></a>
29
- <a href="https://github.com/peteeckel/netbox-plugin-dns/network/members"><img src="https://img.shields.io/github/forks/peteeckel/netbox-plugin-dns" alt="Forks Badge"/></a>
30
- <a href="https://github.com/peteeckel/netbox-plugin-dns/pulls"><img src="https://img.shields.io/github/issues-pr/peteeckel/netbox-plugin-dns" alt="Pull Requests Badge"/></a>
28
+ <a href="https://github.com/peteeckel/netbox-plugin-dns/stargazers"><img src="https://img.shields.io/github/stars/peteeckel/netbox-plugin-dns?style=flat" alt="Stars Badge"/></a>
29
+ <a href="https://github.com/peteeckel/netbox-plugin-dns/network/members"><img src="https://img.shields.io/github/forks/peteeckel/netbox-plugin-dns?style=flat" alt="Forks Badge"/></a>
31
30
  <a href="https://github.com/peteeckel/netbox-plugin-dns/issues"><img src="https://img.shields.io/github/issues/peteeckel/netbox-plugin-dns" alt="Issues Badge"/></a>
31
+ <a href="https://github.com/peteeckel/netbox-plugin-dns/pulls"><img src="https://img.shields.io/github/issues-pr/peteeckel/netbox-plugin-dns" alt="Pull Requests Badge"/></a>
32
32
  <a href="https://github.com/peteeckel/netbox-plugin-dns/graphs/contributors"><img alt="GitHub contributors" src="https://img.shields.io/github/contributors/peteeckel/netbox-plugin-dns?color=2b9348"></a>
33
33
  <a href="https://github.com/peteeckel/netbox-plugin-dns/blob/master/LICENSE"><img src="https://img.shields.io/github/license/peteeckel/netbox-plugin-dns?color=2b9348" alt="License Badge"/></a>
34
34
  <a href="https://pepy.tech/project/netbox-plugin-dns"><img alt="Downloads" src="https://static.pepy.tech/badge/netbox-plugin-dns"></a>
@@ -40,10 +40,10 @@ Description-Content-Type: text/markdown
40
40
 
41
41
  * Manage name servers, zones and records
42
42
  * Automatically generate SOA and NS records for zones
43
- * Automatically create and update PTR records for IPv4 and IPv6 records
44
- * Optionally organize DNS zones in views for split horizon DNS and multi-site deployments
45
- * Optionally maintain domain registrar and registrant information for zones
46
- * Maintain RFC2317 reverse zones for IPv4 prefixes with a network mask length longer than 24 bits
43
+ * Automatically create and update PTR records for IPv4 and IPv6 address records
44
+ * Organize DNS zones in views for split horizon DNS and multi-site deployments
45
+ * Manage domain registrar and registrant information for domains related to zones
46
+ * Manage RFC2317 reverse zones for IPv4 prefixes with a network mask length longer than 24 bits
47
47
 
48
48
  NetBox DNS is using the standardized NetBox plugin interface, so it also takes advantage of the NetBox tagging and change log features.
49
49
 
@@ -1,13 +1,12 @@
1
- <h1 align="center">NetBox DNS</h1>
2
-
3
- <p align="center"><i>NetBox DNS is a NetBox plugin for managing DNS views, zones, name servers and records.</i></p>
1
+ # NetBox DNS
2
+ The NetBox DNS plugin enables NetBox to manage operational DNS data such as name servers, zones, records and views, as well as registration data for domains. It can automate tasks like creating PTR records, generating zone serial numbers, NS and SOA records, as well as validate names and values values for resource records to ensure zone data is consistent, current and conforming to the relevant RFCs.
4
3
 
5
4
  <div align="center">
6
5
  <a href="https://pypi.org/project/netbox-plugin-dns/"><img src="https://img.shields.io/pypi/v/netbox-plugin-dns" alt="PyPi"/></a>
7
- <a href="https://github.com/peteeckel/netbox-plugin-dns/stargazers"><img src="https://img.shields.io/github/stars/peteeckel/netbox-plugin-dns" alt="Stars Badge"/></a>
8
- <a href="https://github.com/peteeckel/netbox-plugin-dns/network/members"><img src="https://img.shields.io/github/forks/peteeckel/netbox-plugin-dns" alt="Forks Badge"/></a>
9
- <a href="https://github.com/peteeckel/netbox-plugin-dns/pulls"><img src="https://img.shields.io/github/issues-pr/peteeckel/netbox-plugin-dns" alt="Pull Requests Badge"/></a>
6
+ <a href="https://github.com/peteeckel/netbox-plugin-dns/stargazers"><img src="https://img.shields.io/github/stars/peteeckel/netbox-plugin-dns?style=flat" alt="Stars Badge"/></a>
7
+ <a href="https://github.com/peteeckel/netbox-plugin-dns/network/members"><img src="https://img.shields.io/github/forks/peteeckel/netbox-plugin-dns?style=flat" alt="Forks Badge"/></a>
10
8
  <a href="https://github.com/peteeckel/netbox-plugin-dns/issues"><img src="https://img.shields.io/github/issues/peteeckel/netbox-plugin-dns" alt="Issues Badge"/></a>
9
+ <a href="https://github.com/peteeckel/netbox-plugin-dns/pulls"><img src="https://img.shields.io/github/issues-pr/peteeckel/netbox-plugin-dns" alt="Pull Requests Badge"/></a>
11
10
  <a href="https://github.com/peteeckel/netbox-plugin-dns/graphs/contributors"><img alt="GitHub contributors" src="https://img.shields.io/github/contributors/peteeckel/netbox-plugin-dns?color=2b9348"></a>
12
11
  <a href="https://github.com/peteeckel/netbox-plugin-dns/blob/master/LICENSE"><img src="https://img.shields.io/github/license/peteeckel/netbox-plugin-dns?color=2b9348" alt="License Badge"/></a>
13
12
  <a href="https://pepy.tech/project/netbox-plugin-dns"><img alt="Downloads" src="https://static.pepy.tech/badge/netbox-plugin-dns"></a>
@@ -19,10 +18,10 @@
19
18
 
20
19
  * Manage name servers, zones and records
21
20
  * Automatically generate SOA and NS records for zones
22
- * Automatically create and update PTR records for IPv4 and IPv6 records
23
- * Optionally organize DNS zones in views for split horizon DNS and multi-site deployments
24
- * Optionally maintain domain registrar and registrant information for zones
25
- * Maintain RFC2317 reverse zones for IPv4 prefixes with a network mask length longer than 24 bits
21
+ * Automatically create and update PTR records for IPv4 and IPv6 address records
22
+ * Organize DNS zones in views for split horizon DNS and multi-site deployments
23
+ * Manage domain registrar and registrant information for domains related to zones
24
+ * Manage RFC2317 reverse zones for IPv4 prefixes with a network mask length longer than 24 bits
26
25
 
27
26
  NetBox DNS is using the standardized NetBox plugin interface, so it also takes advantage of the NetBox tagging and change log features.
28
27
 
@@ -10,7 +10,7 @@ except ImportError:
10
10
  # NetBox 3.5.8
11
11
  from extras.plugins.utils import get_plugin_config
12
12
 
13
- __version__ = "0.22.4"
13
+ __version__ = "0.22.5"
14
14
 
15
15
 
16
16
  class DNSConfig(PluginConfig):
@@ -38,7 +38,8 @@ class DNSConfig(PluginConfig):
38
38
  ],
39
39
  "tolerate_non_rfc1035_types": [],
40
40
  "enable_root_zones": False,
41
- "enforce_unique_records": False,
41
+ "enforce_unique_records": True,
42
+ "enforce_unique_rrset_ttl": True,
42
43
  }
43
44
  base_url = "netbox-dns"
44
45
 
@@ -272,6 +272,7 @@ class RegistrarSerializer(NetBoxModelSerializer):
272
272
  "display",
273
273
  "name",
274
274
  "iana_id",
275
+ "address",
275
276
  "referral_url",
276
277
  "whois_server",
277
278
  "abuse_email",
@@ -12,6 +12,7 @@ class RegistrarFilter(NetBoxModelFilterSet):
12
12
  "id",
13
13
  "name",
14
14
  "iana_id",
15
+ "address",
15
16
  "referral_url",
16
17
  "whois_server",
17
18
  "abuse_email",
@@ -17,6 +17,7 @@ class RegistrarForm(NetBoxModelForm):
17
17
  fields = (
18
18
  "name",
19
19
  "iana_id",
20
+ "address",
20
21
  "referral_url",
21
22
  "whois_server",
22
23
  "abuse_email",
@@ -29,12 +30,18 @@ class RegistrarFilterForm(NetBoxModelFilterSetForm):
29
30
  model = Registrar
30
31
  fieldsets = (
31
32
  (None, ("q", "name", "iana_id", "tags")),
32
- ("Contact", ("referral_url", "whois_server", "abuse_email", "abuse_phone")),
33
+ (
34
+ "Contact",
35
+ ("address", "referral_url", "whois_server", "abuse_email", "abuse_phone"),
36
+ ),
33
37
  )
34
38
 
35
39
  name = forms.CharField(
36
40
  required=False,
37
41
  )
42
+ address = forms.CharField(
43
+ required=False,
44
+ )
38
45
  iana_id = forms.IntegerField(
39
46
  required=False,
40
47
  label="IANA ID",
@@ -64,6 +71,7 @@ class RegistrarImportForm(NetBoxModelImportForm):
64
71
  fields = (
65
72
  "name",
66
73
  "iana_id",
74
+ "address",
67
75
  "referral_url",
68
76
  "whois_server",
69
77
  "abuse_email",
@@ -96,6 +104,7 @@ class RegistrarBulkEditForm(NetBoxModelBulkEditForm):
96
104
  (
97
105
  None,
98
106
  (
107
+ "address",
99
108
  "referral_url",
100
109
  "whois_server",
101
110
  "abuse_email",
@@ -105,6 +114,7 @@ class RegistrarBulkEditForm(NetBoxModelBulkEditForm):
105
114
  )
106
115
 
107
116
  nullable_fields = (
117
+ "address",
108
118
  "referral_url",
109
119
  "whois_server",
110
120
  "abuse_email",
@@ -315,7 +315,7 @@ class ZoneImportForm(NetBoxModelImportForm):
315
315
  required=False,
316
316
  help_text="Mailbox of the zone's administrator",
317
317
  )
318
- soa_serial_auto = forms.BooleanField(
318
+ soa_serial_auto = forms.NullBooleanField(
319
319
  required=False,
320
320
  help_text="Generate the SOA serial",
321
321
  )
@@ -443,26 +443,6 @@ class ZoneImportForm(NetBoxModelImportForm):
443
443
  def clean_soa_rname(self):
444
444
  return self._clean_field_with_defaults("soa_rname")
445
445
 
446
- def clean_soa_serial_auto(self):
447
- try:
448
- return self._clean_field_with_defaults("soa_serial_auto")
449
- except ValidationError:
450
- if self.cleaned_data["soa_serial"] or self._get_default_value("soa_serial"):
451
- return None
452
-
453
- raise
454
-
455
- def clean_soa_serial(self):
456
- try:
457
- return self._clean_field_with_defaults("soa_serial")
458
- except ValidationError:
459
- if self.cleaned_data["soa_serial_auto"] or self._get_default_value(
460
- "soa_serial_auto"
461
- ):
462
- return None
463
-
464
- raise
465
-
466
446
  def clean_soa_refresh(self):
467
447
  return self._clean_field_with_defaults("soa_refresh")
468
448
 
@@ -475,6 +455,36 @@ class ZoneImportForm(NetBoxModelImportForm):
475
455
  def clean_soa_minimum(self):
476
456
  return self._clean_field_with_defaults("soa_minimum")
477
457
 
458
+ def clean(self, *args, **kwargs):
459
+ super().clean(*args, **kwargs)
460
+
461
+ soa_serial_auto = self.cleaned_data.get("soa_serial_auto")
462
+ soa_serial = self.cleaned_data.get("soa_serial")
463
+
464
+ if soa_serial is None:
465
+ soa_serial = self._get_default_value("soa_serial")
466
+
467
+ if soa_serial_auto is None:
468
+ if self._get_default_value("soa_serial_auto") is not None:
469
+ soa_serial_auto = self._get_default_value("soa_serial_auto")
470
+
471
+ elif soa_serial is not None:
472
+ soa_serial_auto = False
473
+
474
+ else:
475
+ raise ValidationError(
476
+ "SOA Serial Auto not set and no default value and SOA Serial available"
477
+ )
478
+
479
+ if "soa_serial_auto" in self.cleaned_data:
480
+ self.cleaned_data["soa_serial_auto"] = soa_serial_auto
481
+
482
+ if "soa_serial" in self.cleaned_data:
483
+ if soa_serial_auto:
484
+ self.cleaned_data["soa_serial"] = None
485
+ else:
486
+ self.cleaned_data["soa_serial"] = soa_serial
487
+
478
488
  class Meta:
479
489
  model = Zone
480
490
 
@@ -0,0 +1,62 @@
1
+ from django.core.management.base import BaseCommand
2
+ from django.db.models import Max, Min
3
+
4
+ from netbox_dns.models import (
5
+ Record,
6
+ RecordTypeChoices,
7
+ )
8
+
9
+
10
+ class Command(BaseCommand):
11
+ help = "Clean up the TTLs for RRSets"
12
+
13
+ def add_arguments(self, parser):
14
+ min_max = parser.add_mutually_exclusive_group()
15
+ min_max.add_argument(
16
+ "--min",
17
+ action="store_true",
18
+ help="Use the minimum TTL of an RRSet for all Records",
19
+ )
20
+ min_max.add_argument(
21
+ "--max",
22
+ action="store_true",
23
+ help="Use the maximum TTL of an RRSet for all Records",
24
+ )
25
+
26
+ def handle(self, *model_names, **options):
27
+ self.cleanup_rrset_ttl(**options)
28
+
29
+ self.stdout.write("RRSet cleanup completed.")
30
+
31
+ def cleanup_rrset_ttl(self, **options):
32
+ verbose = options.get("verbosity") > 1
33
+
34
+ ttl_records = (
35
+ Record.objects.filter(ttl__isnull=False)
36
+ .exclude(type=RecordTypeChoices.SOA)
37
+ .exclude(type=RecordTypeChoices.PTR, maanged=True)
38
+ )
39
+ for record in ttl_records:
40
+ records = Record.objects.filter(
41
+ name=record.name,
42
+ zone=record.zone,
43
+ type=record.type,
44
+ ).exclude(type=RecordTypeChoices.PTR, maanged=True)
45
+
46
+ if records.count() == 1:
47
+ if options.get("verbosity") > 2:
48
+ self.stdout.write(f"Ignoring single record {record.id} ({record})")
49
+ continue
50
+
51
+ if options.get("max"):
52
+ ttl = records.aggregate(Max("ttl")).get("ttl__max")
53
+ else:
54
+ ttl = records.aggregate(Min("ttl")).get("ttl__min")
55
+
56
+ for record in records.exclude(ttl=ttl):
57
+ if options.get("verbosity") > 1:
58
+ self.stdout.write(
59
+ f"Updating TTL for record {record.id} ({record}) to {ttl}"
60
+ )
61
+ record.ttl = ttl
62
+ record.save(update_fields=["ttl"], update_rrset_ttl=False)
@@ -6,7 +6,7 @@ from dns import name as dns_name
6
6
 
7
7
  from django.core.exceptions import ValidationError
8
8
  from django.db import transaction, models
9
- from django.db.models import Q, ExpressionWrapper, BooleanField
9
+ from django.db.models import Q, ExpressionWrapper, BooleanField, Min
10
10
  from django.db.models.functions import Length
11
11
  from django.urls import reverse
12
12
 
@@ -38,6 +38,10 @@ from netbox_dns.validators import (
38
38
  import netbox_dns.models.zone as zone
39
39
 
40
40
 
41
+ def min_ttl(*ttl_list):
42
+ return min((ttl for ttl in ttl_list if ttl is not None), default=None)
43
+
44
+
41
45
  class RecordManager(models.Manager.from_queryset(RestrictedQuerySet)):
42
46
  """Special Manager for records providing the activity status annotation"""
43
47
 
@@ -207,7 +211,8 @@ class Record(NetBoxModel):
207
211
  try:
208
212
  name = (
209
213
  dns_name.from_text(
210
- self.name, origin=dns_name.from_text(self.zone.name, origin=None)
214
+ str(self.name),
215
+ origin=dns_name.from_text(self.zone.name, origin=None),
211
216
  )
212
217
  .relativize(dns_name.root)
213
218
  .to_unicode()
@@ -309,7 +314,7 @@ class Record(NetBoxModel):
309
314
 
310
315
  return ptr_zone
311
316
 
312
- def update_ptr_record(self, update_rfc2317_cname=True):
317
+ def update_ptr_record(self, update_rfc2317_cname=True, save_zone_serial=True):
313
318
  ptr_zone = self.ptr_zone
314
319
 
315
320
  if (
@@ -339,14 +344,16 @@ class Record(NetBoxModel):
339
344
  not ptr_record.zone.is_rfc2317_zone
340
345
  and ptr_record.rfc2317_cname_record is not None
341
346
  ):
342
- ptr_record.rfc2317_cname_record.delete()
347
+ ptr_record.rfc2317_cname_record.delete(
348
+ save_zone_serial=save_zone_serial
349
+ )
343
350
 
344
351
  with transaction.atomic():
345
352
  if ptr_record is not None:
346
353
  if ptr_record.zone.pk != ptr_zone.pk:
347
354
  if ptr_record.rfc2317_cname_record is not None:
348
355
  ptr_record.rfc2317_cname_record.delete()
349
- ptr_record.delete()
356
+ ptr_record.delete(save_zone_serial=save_zone_serial)
350
357
  ptr_record = None
351
358
 
352
359
  else:
@@ -358,7 +365,7 @@ class Record(NetBoxModel):
358
365
  ptr_record.name = ptr_name
359
366
  ptr_record.value = ptr_value
360
367
  ptr_record.ttl = self.ttl
361
- ptr_record.save()
368
+ ptr_record.save(save_zone_serial=save_zone_serial)
362
369
 
363
370
  if ptr_record is None:
364
371
  ptr_record = Record(
@@ -369,11 +376,14 @@ class Record(NetBoxModel):
369
376
  value=ptr_value,
370
377
  managed=True,
371
378
  )
372
- ptr_record.save(update_rfc2317_cname=update_rfc2317_cname)
379
+ ptr_record.save(
380
+ update_rfc2317_cname=update_rfc2317_cname,
381
+ save_zone_serial=save_zone_serial,
382
+ )
373
383
 
374
384
  self.ptr_record = ptr_record
375
385
 
376
- def update_rfc2317_cname_record(self):
386
+ def update_rfc2317_cname_record(self, save_zone_serial=True):
377
387
  if self.zone.rfc2317_parent_managed:
378
388
  cname_name = dns_name.from_text(
379
389
  ipaddress.ip_address(self.ip_address).reverse_pointer
@@ -383,7 +393,13 @@ class Record(NetBoxModel):
383
393
  self.rfc2317_cname_record.name = cname_name
384
394
  self.rfc2317_cname_record.zone = self.zone.rfc2317_parent_zone
385
395
  self.rfc2317_cname_record.value = self.fqdn
386
- self.rfc2317_cname_record.save()
396
+ self.rfc2317_cname_record.ttl = min_ttl(
397
+ self.rfc2317_cname_record.rfc2317_ptr_records.exclude(pk=self.pk)
398
+ .aggregate(Min("ttl"))
399
+ .get("ttl__min"),
400
+ self.ttl,
401
+ )
402
+ self.rfc2317_cname_record.save(save_zone_serial=save_zone_serial)
387
403
  else:
388
404
  rfc2317_cname_record = Record.objects.filter(
389
405
  name=cname_name,
@@ -392,20 +408,34 @@ class Record(NetBoxModel):
392
408
  managed=True,
393
409
  value=self.fqdn,
394
410
  ).first()
395
- if rfc2317_cname_record is None:
396
- rfc2317_cname_record = Record.objects.create(
411
+
412
+ if rfc2317_cname_record is not None:
413
+ rfc2317_cname_record.ttl = min_ttl(
414
+ rfc2317_cname_record.rfc2317_ptr_records.exclude(pk=self.pk)
415
+ .aggregate(Min("ttl"))
416
+ .get("ttl__min"),
417
+ self.ttl,
418
+ )
419
+ rfc2317_cname_record.save(
420
+ update_fields=["ttl"], save_zone_serial=save_zone_serial
421
+ )
422
+
423
+ else:
424
+ rfc2317_cname_record = Record(
397
425
  name=cname_name,
398
426
  type=RecordTypeChoices.CNAME,
399
427
  zone=self.zone.rfc2317_parent_zone,
400
428
  managed=True,
401
429
  value=self.fqdn,
430
+ ttl=self.ttl,
402
431
  )
432
+ rfc2317_cname_record.save(save_zone_serial=save_zone_serial)
403
433
 
404
434
  self.rfc2317_cname_record = rfc2317_cname_record
405
435
 
406
436
  else:
407
437
  if self.rfc2317_cname_record is not None:
408
- self.rfc2317_cname_record.delete()
438
+ self.rfc2317_cname_record.delete(save_zone_serial=save_zone_serial)
409
439
  self.rfc2317_cname_record = None
410
440
 
411
441
  def validate_name(self):
@@ -475,7 +505,7 @@ class Record(NetBoxModel):
475
505
  }
476
506
  ) from None
477
507
 
478
- def check_unique(self):
508
+ def check_unique_record(self):
479
509
  if not get_plugin_config("netbox_dns", "enforce_unique_records", False):
480
510
  return
481
511
 
@@ -489,6 +519,10 @@ class Record(NetBoxModel):
489
519
  value=self.value,
490
520
  status__in=Record.ACTIVE_STATUS_LIST,
491
521
  )
522
+
523
+ if self.pk is not None:
524
+ records = records.exclude(pk=self.pk)
525
+
492
526
  if len(records):
493
527
  raise ValidationError(
494
528
  {
@@ -496,6 +530,64 @@ class Record(NetBoxModel):
496
530
  }
497
531
  ) from None
498
532
 
533
+ def check_unique_rrset_ttl(self):
534
+ if self.pk is not None:
535
+ return
536
+
537
+ if not get_plugin_config("netbox_dns", "enforce_unique_rrset_ttl", False):
538
+ return
539
+
540
+ if self.type == RecordTypeChoices.PTR and self.managed:
541
+ return
542
+
543
+ records = (
544
+ Record.objects.filter(
545
+ zone=self.zone,
546
+ name=self.name,
547
+ type=self.type,
548
+ )
549
+ .exclude(ttl=self.ttl)
550
+ .exclude(type=RecordTypeChoices.PTR, managed=True)
551
+ )
552
+
553
+ if not records.exists():
554
+ return
555
+
556
+ conflicting_ttls = ", ".join(set(str(record.ttl) for record in records))
557
+ raise ValidationError(
558
+ {
559
+ "ttl": f"There is at least one active {self.type} record for name {self.name} in zone {self.zone} and TTL is different ({conflicting_ttls})."
560
+ }
561
+ ) from None
562
+
563
+ def update_rrset_ttl(self, ttl=None):
564
+ if self.pk is None:
565
+ return
566
+
567
+ if not get_plugin_config("netbox_dns", "enforce_unique_rrset_ttl", False):
568
+ return
569
+
570
+ if self.type == RecordTypeChoices.PTR and self.managed:
571
+ return
572
+
573
+ if ttl is None:
574
+ ttl = self.ttl
575
+
576
+ records = (
577
+ Record.objects.filter(
578
+ zone=self.zone,
579
+ name=self.name,
580
+ type=self.type,
581
+ )
582
+ .exclude(pk=self.pk)
583
+ .exclude(ttl=ttl)
584
+ .exclude(type=RecordTypeChoices.PTR, managed=True)
585
+ )
586
+
587
+ for record in records:
588
+ record.ttl = ttl
589
+ record.save(update_fields=["ttl"], update_rrset_ttl=False)
590
+
499
591
  def clean_fields(self, *args, **kwargs):
500
592
  self.type = self.type.upper()
501
593
  super().clean_fields(*args, **kwargs)
@@ -503,7 +595,9 @@ class Record(NetBoxModel):
503
595
  def clean(self, *args, **kwargs):
504
596
  self.validate_name()
505
597
  self.validate_value()
506
- self.check_unique()
598
+ self.check_unique_record()
599
+ if self.pk is None:
600
+ self.check_unique_rrset_ttl()
507
601
 
508
602
  if not self.is_active:
509
603
  return
@@ -578,14 +672,24 @@ class Record(NetBoxModel):
578
672
  }
579
673
  ) from None
580
674
 
581
- def save(self, *args, update_rfc2317_cname=True, **kwargs):
675
+ def save(
676
+ self,
677
+ *args,
678
+ update_rfc2317_cname=True,
679
+ save_zone_serial=True,
680
+ update_rrset_ttl=True,
681
+ **kwargs,
682
+ ):
582
683
  self.full_clean()
583
684
 
685
+ if self.pk is not None and update_rrset_ttl:
686
+ self.update_rrset_ttl()
687
+
584
688
  if self.is_ptr_record:
585
689
  if self.zone.is_rfc2317_zone:
586
690
  self.ip_address = self.address_from_rfc2317_name
587
691
  if update_rfc2317_cname:
588
- self.update_rfc2317_cname_record()
692
+ self.update_rfc2317_cname_record(save_zone_serial=save_zone_serial)
589
693
  else:
590
694
  self.ip_address = self.address_from_name
591
695
 
@@ -595,7 +699,10 @@ class Record(NetBoxModel):
595
699
  self.ip_address = None
596
700
 
597
701
  if self.is_address_record:
598
- self.update_ptr_record(update_rfc2317_cname=update_rfc2317_cname)
702
+ self.update_ptr_record(
703
+ update_rfc2317_cname=update_rfc2317_cname,
704
+ save_zone_serial=save_zone_serial,
705
+ )
599
706
  elif self.ptr_record is not None:
600
707
  self.ptr_record.delete()
601
708
  self.ptr_record = None
@@ -604,15 +711,24 @@ class Record(NetBoxModel):
604
711
 
605
712
  zone = self.zone
606
713
  if self.type != RecordTypeChoices.SOA and zone.soa_serial_auto:
607
- zone.update_serial()
714
+ zone.update_serial(save_zone_serial=save_zone_serial)
608
715
 
609
- def delete(self, *args, **kwargs):
716
+ def delete(self, *args, save_zone_serial=True, **kwargs):
610
717
  if self.rfc2317_cname_record:
611
- if (
612
- self.rfc2317_cname_record.pk
613
- and self.rfc2317_cname_record.rfc2317_ptr_records.count() == 1
614
- ):
615
- self.rfc2317_cname_record.delete()
718
+ if self.rfc2317_cname_record.pk:
719
+ if self.rfc2317_cname_record.rfc2317_ptr_records.count() == 1:
720
+ self.rfc2317_cname_record.delete()
721
+ else:
722
+ self.rfc2317_cname_record.ttl = (
723
+ self.rfc2317_cname_record.rfc2317_ptr_records.exclude(
724
+ pk=self.pk
725
+ )
726
+ .aggregate(Min("ttl"))
727
+ .get("ttl__min")
728
+ )
729
+ self.rfc2317_cname_record.save(
730
+ update_fields=["ttl"], save_zone_serial=save_zone_serial
731
+ )
616
732
 
617
733
  if self.ptr_record:
618
734
  self.ptr_record.delete()
@@ -621,7 +737,7 @@ class Record(NetBoxModel):
621
737
 
622
738
  zone = self.zone
623
739
  if zone.soa_serial_auto:
624
- zone.update_serial()
740
+ zone.update_serial(save_zone_serial=save_zone_serial)
625
741
 
626
742
 
627
743
  @register_search