netbox-plugin-dns 1.1.1__py3-none-any.whl → 1.1.3__py3-none-any.whl

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 (88) hide show
  1. netbox_dns/__init__.py +8 -6
  2. netbox_dns/api/nested_serializers.py +3 -2
  3. netbox_dns/api/serializers_/nameserver.py +2 -1
  4. netbox_dns/api/serializers_/record.py +5 -4
  5. netbox_dns/api/serializers_/record_template.py +2 -1
  6. netbox_dns/api/serializers_/view.py +3 -1
  7. netbox_dns/api/serializers_/zone.py +12 -11
  8. netbox_dns/api/serializers_/zone_template.py +8 -7
  9. netbox_dns/api/views.py +9 -4
  10. netbox_dns/choices/record.py +4 -2
  11. netbox_dns/choices/zone.py +6 -4
  12. netbox_dns/fields/address.py +2 -1
  13. netbox_dns/fields/network.py +2 -1
  14. netbox_dns/fields/rfc2317.py +7 -3
  15. netbox_dns/filtersets/nameserver.py +3 -2
  16. netbox_dns/filtersets/record.py +10 -9
  17. netbox_dns/filtersets/record_template.py +3 -2
  18. netbox_dns/filtersets/view.py +3 -2
  19. netbox_dns/filtersets/zone.py +24 -22
  20. netbox_dns/filtersets/zone_template.py +15 -14
  21. netbox_dns/forms/nameserver.py +41 -17
  22. netbox_dns/forms/record.py +43 -26
  23. netbox_dns/forms/record_template.py +49 -28
  24. netbox_dns/forms/registrar.py +21 -17
  25. netbox_dns/forms/registration_contact.py +37 -25
  26. netbox_dns/forms/view.py +75 -34
  27. netbox_dns/forms/zone.py +167 -120
  28. netbox_dns/forms/zone_template.py +53 -43
  29. netbox_dns/graphql/schema.py +0 -10
  30. netbox_dns/graphql/types.py +1 -0
  31. netbox_dns/locale/de/LC_MESSAGES/django.mo +0 -0
  32. netbox_dns/locale/en/LC_MESSAGES/django.mo +0 -0
  33. netbox_dns/management/commands/rebuild_dnssync.py +14 -1
  34. netbox_dns/migrations/0010_view_ip_address_filter.py +18 -0
  35. netbox_dns/mixins/object_modification.py +30 -8
  36. netbox_dns/models/nameserver.py +6 -2
  37. netbox_dns/models/record.py +95 -40
  38. netbox_dns/models/record_template.py +16 -8
  39. netbox_dns/models/registrar.py +11 -7
  40. netbox_dns/models/registration_contact.py +23 -11
  41. netbox_dns/models/view.py +54 -5
  42. netbox_dns/models/zone.py +77 -50
  43. netbox_dns/models/zone_template.py +12 -10
  44. netbox_dns/navigation.py +30 -28
  45. netbox_dns/signals/ipam_dnssync.py +25 -18
  46. netbox_dns/tables/ipam_dnssync.py +2 -1
  47. netbox_dns/tables/nameserver.py +2 -0
  48. netbox_dns/tables/record.py +21 -11
  49. netbox_dns/tables/record_template.py +12 -5
  50. netbox_dns/tables/registrar.py +2 -0
  51. netbox_dns/tables/registration_contact.py +2 -0
  52. netbox_dns/tables/view.py +4 -2
  53. netbox_dns/tables/zone.py +15 -2
  54. netbox_dns/tables/zone_template.py +7 -0
  55. netbox_dns/templates/netbox_dns/nameserver.html +6 -5
  56. netbox_dns/templates/netbox_dns/record/managed.html +2 -1
  57. netbox_dns/templates/netbox_dns/record/related.html +26 -14
  58. netbox_dns/templates/netbox_dns/record.html +39 -20
  59. netbox_dns/templates/netbox_dns/recordtemplate.html +27 -15
  60. netbox_dns/templates/netbox_dns/registrar.html +11 -10
  61. netbox_dns/templates/netbox_dns/registrationcontact.html +16 -15
  62. netbox_dns/templates/netbox_dns/view/button.html +2 -1
  63. netbox_dns/templates/netbox_dns/view/prefix.html +7 -4
  64. netbox_dns/templates/netbox_dns/view/related.html +26 -10
  65. netbox_dns/templates/netbox_dns/view.html +22 -9
  66. netbox_dns/templates/netbox_dns/zone/base.html +2 -1
  67. netbox_dns/templates/netbox_dns/zone/child.html +3 -2
  68. netbox_dns/templates/netbox_dns/zone/record.html +3 -2
  69. netbox_dns/templates/netbox_dns/zone/registration.html +8 -7
  70. netbox_dns/templates/netbox_dns/zone.html +28 -30
  71. netbox_dns/templates/netbox_dns/zonetemplate.html +27 -17
  72. netbox_dns/utilities/ipam_dnssync.py +71 -28
  73. netbox_dns/validators/dns_name.py +11 -4
  74. netbox_dns/validators/dns_value.py +9 -4
  75. netbox_dns/validators/rfc2317.py +6 -3
  76. netbox_dns/views/nameserver.py +4 -2
  77. netbox_dns/views/record_template.py +4 -3
  78. netbox_dns/views/registrar.py +3 -1
  79. netbox_dns/views/registration_contact.py +2 -1
  80. netbox_dns/views/view.py +2 -1
  81. netbox_dns/views/zone.py +6 -4
  82. netbox_dns/views/zone_template.py +8 -7
  83. {netbox_plugin_dns-1.1.1.dist-info → netbox_plugin_dns-1.1.3.dist-info}/METADATA +1 -1
  84. netbox_plugin_dns-1.1.3.dist-info/RECORD +150 -0
  85. {netbox_plugin_dns-1.1.1.dist-info → netbox_plugin_dns-1.1.3.dist-info}/WHEEL +1 -1
  86. netbox_plugin_dns-1.1.1.dist-info/RECORD +0 -147
  87. {netbox_plugin_dns-1.1.1.dist-info → netbox_plugin_dns-1.1.3.dist-info}/LICENSE +0 -0
  88. {netbox_plugin_dns-1.1.1.dist-info → netbox_plugin_dns-1.1.3.dist-info}/top_level.txt +0 -0
@@ -2,6 +2,7 @@
2
2
  {% load helpers %}
3
3
  {% load render_table from django_tables2 %}
4
4
  {% load perms %}
5
+ {% load i18n %}
5
6
 
6
7
  {% block content %}
7
8
  {% include 'inc/table_controls_htmx.html' with table_modal="ZoneTable_config" %}
@@ -23,12 +24,12 @@
23
24
  {% block bulk_buttons %}{% endblock %}
24
25
  {% if bulk_edit_url and perms.netbox_dns.change_zone %}
25
26
  <button type="submit" name="_edit" formaction="{% url bulk_edit_url %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-warning">
26
- <i class="mdi mdi-pencil" aria-hidden="true"></i> Edit Selected
27
+ <i class="mdi mdi-pencil" aria-hidden="true"></i> {% trans "Edit Selected" %}
27
28
  </button>
28
29
  {% endif %}
29
30
  {% if bulk_delete_url and perms.netbox_dns.delete_zone %}
30
31
  <button type="submit" name="_delete" formaction="{% url bulk_delete_url %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-danger">
31
- <i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete Selected
32
+ <i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> {% trans "Delete Selected" %}
32
33
  </button>
33
34
  {% endif %}
34
35
  </div>
@@ -2,6 +2,7 @@
2
2
  {% load helpers %}
3
3
  {% load render_table from django_tables2 %}
4
4
  {% load perms %}
5
+ {% load i18n %}
5
6
 
6
7
  {% block content %}
7
8
  {% include 'inc/table_controls_htmx.html' with table_modal="RecordTable_config" %}
@@ -23,12 +24,12 @@
23
24
  {% block bulk_buttons %}{% endblock %}
24
25
  {% if bulk_edit_url and perms.netbox_dns.change_record %}
25
26
  <button type="submit" name="_edit" formaction="{% url bulk_edit_url %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-warning">
26
- <i class="mdi mdi-pencil" aria-hidden="true"></i> Edit Selected
27
+ <i class="mdi mdi-pencil" aria-hidden="true"></i> {% trans "Edit Selected" %}
27
28
  </button>
28
29
  {% endif %}
29
30
  {% if bulk_delete_url and perms.netbox_dns.delete_record %}
30
31
  <button type="submit" name="_delete" formaction="{% url bulk_delete_url %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-danger">
31
- <i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete Selected
32
+ <i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> {% trans "Delete Selected" %}
32
33
  </button>
33
34
  {% endif %}
34
35
  </div>
@@ -1,32 +1,33 @@
1
1
  {% extends 'netbox_dns/zone/base.html' %}
2
2
  {% load helpers %}
3
+ {% load i18n %}
3
4
 
4
5
  {% block content %}
5
6
  <div class="card">
6
- <h5 class="card-header">Domain Registration</h5>
7
+ <h5 class="card-header">{% trans "Domain Registration" %}</h5>
7
8
  <table class="table table-hover attr-table">
8
9
  <tr>
9
- <th scope="row">Registrar</th>
10
+ <th scope="row">{% trans "Registrar" %}</th>
10
11
  <td>{{ object.registrar|linkify|placeholder }}</td>
11
12
  </tr>
12
13
  <tr>
13
- <th scope="row">Registry Domain ID</th>
14
+ <th scope="row">{% trans "Registry Domain ID" %}</th>
14
15
  <td>{{ object.registry_domain_id|placeholder }}</td>
15
16
  </tr>
16
17
  <tr>
17
- <th scope="row">Registrant</th>
18
+ <th scope="row">{% trans "Registrant" %}</th>
18
19
  <td>{{ object.registrant|linkify|placeholder }}</td>
19
20
  </tr>
20
21
  <tr>
21
- <th scope="row">Administrative Contact</th>
22
+ <th scope="row">{% trans "Administrative Contact" %}</th>
22
23
  <td>{{ object.admin_c|linkify|placeholder }}</td>
23
24
  </tr>
24
25
  <tr>
25
- <th scope="row">Technical Contact</th>
26
+ <th scope="row">{% trans "Technical Contact" %}</th>
26
27
  <td>{{ object.tech_c|linkify|placeholder }}</td>
27
28
  </tr>
28
29
  <tr>
29
- <th scope="row">Billing Contact</th>
30
+ <th scope="row">{% trans "Billing Contact" %}</th>
30
31
  <td>{{ object.billing_c|linkify|placeholder }}</td>
31
32
  </tr>
32
33
  </table>
@@ -1,43 +1,41 @@
1
1
  {% extends 'netbox_dns/zone/base.html' %}
2
2
  {% load helpers %}
3
- {% load render_table from django_tables2 %}
3
+ {% load i18n %}
4
4
 
5
5
  {% block content %}
6
6
  <div class="row">
7
7
  <div class="col col-md-6">
8
8
  <div class="card">
9
- <h5 class="card-header">
10
- Zone
11
- </h5>
9
+ <h5 class="card-header">{% trans "Zone" %}</h5>
12
10
  <table class="table table-hover attr-table">
13
11
  <tr>
14
- <th scope="row">Name</th>
12
+ <th scope="row">{% trans "Name" %}</th>
15
13
  <td>{{ object.name }}</td>
16
14
  </tr>
17
15
  {% if unicode_name %}
18
16
  <tr>
19
- <th scope="row">IDN</th>
17
+ <th scope="row">{% trans "IDN" %}</th>
20
18
  <td>{{ unicode_name }}</td>
21
19
  </tr>
22
20
  {% endif %}
23
21
  {% if parent_zone %}
24
22
  <tr>
25
- <th scope="row">Parent Zone</th>
23
+ <th scope="row">{% trans "Parent Zone" %}</th>
26
24
  <td>{{ parent_zone|linkify }}</td>
27
25
  </tr>
28
26
  {% endif %}
29
27
  <tr>
30
- <th scope="row">View</th>
28
+ <th scope="row">{% trans "View" context "DNS" %}</th>
31
29
  <td>{{ object.view|linkify }}</td>
32
30
  </tr>
33
31
  {% if object.description %}
34
32
  <tr>
35
- <th scope="row">Description</th>
33
+ <th scope="row">{% trans "Description" %}</th>
36
34
  <td style="word-break:break-all;">{{ object.description }}</td>
37
35
  </tr>
38
36
  {% endif %}
39
37
  <tr>
40
- <th scope="row">Tenant</th>
38
+ <th scope="row">{% trans "Tenant" %}</th>
41
39
  <td>
42
40
  {% if object.tenant.group %}
43
41
  {{ object.tenant.group|linkify }} /
@@ -46,11 +44,11 @@
46
44
  </td>
47
45
  </tr>
48
46
  <tr>
49
- <th scope="row">Status</th>
47
+ <th scope="row">{% trans "Status" %}</th>
50
48
  <td>{% badge object.get_status_display bg_color=object.get_status_color %}</td>
51
49
  </tr>
52
50
  <tr>
53
- <th scope="row">Nameservers</th>
51
+ <th scope="row">{% trans "Nameservers" %}</th>
54
52
  <td>
55
53
  <table>
56
54
  {% for nameserver in object.nameservers.all %}
@@ -60,7 +58,7 @@
60
58
  </td>
61
59
  {% if nameserver_warnings %}
62
60
  <tr>
63
- <th class="text-warning" scope="row">Warnings</th>
61
+ <th class="text-warning" scope="row">{% trans "Warnings" %}</th>
64
62
  <td>
65
63
  <table>
66
64
  {% for warning in nameserver_warnings %}
@@ -74,7 +72,7 @@
74
72
  {% endif %}
75
73
  {% if nameserver_errors %}
76
74
  <tr>
77
- <th class="text-danger" scope="row">Errors</th>
75
+ <th class="text-danger" scope="row">{% trans "Errors" %}</th>
78
76
  <td>
79
77
  <table>
80
78
  {% for error in nameserver_errors %}
@@ -88,11 +86,11 @@
88
86
  {% endif %}
89
87
  </tr>
90
88
  <tr>
91
- <th scope="row">Default TTL</th>
89
+ <th scope="row">{% trans "Default TTL" %}</th>
92
90
  <td>{{ object.default_ttl }}</td>
93
91
  </tr>
94
92
  <tr>
95
- <th scope="row">Description</th>
93
+ <th scope="row">{% trans "Description" %}</th>
96
94
  <td>{{ object.description }}</td>
97
95
  </tr>
98
96
  </table>
@@ -103,64 +101,64 @@
103
101
  </div>
104
102
  <div class="col col-md-6">
105
103
  <div class="card">
106
- <h5 class="card-header">Zone SOA</h5>
104
+ <h5 class="card-header">{% trans "Zone SOA" %}</h5>
107
105
  <table class="table table-hover attr-table">
108
106
  <tr>
109
- <th scope="row">TTL</th>
107
+ <th scope="row">{% trans "TTL" %}</th>
110
108
  <td>{{ object.soa_ttl }}</td>
111
109
  </tr>
112
110
  <tr>
113
- <th scope="row">MName</th>
111
+ <th scope="row">{% trans "MName" %}</th>
114
112
  <td>{{ object.soa_mname|linkify }}</td>
115
113
  </tr>
116
114
  <tr>
117
- <th scope="row">RName</th>
115
+ <th scope="row">{% trans "RName" %}</th>
118
116
  <td>{{ object.soa_rname }}</td>
119
117
  </tr>
120
118
  {% if object.soa_serial_auto %}
121
119
  <tr>
122
- <th scope="row">Serial (auto-generated)</th>
120
+ <th scope="row">{% trans "Serial (auto-generated)" %}</th>
123
121
  <td>{{ object.soa_serial }}</td>
124
122
  </tr>
125
123
  {% else %}
126
124
  <tr>
127
- <th scope="row">Serial</th>
125
+ <th scope="row">{% trans "Serial" context "SOA" %}</th>
128
126
  <td>{{ object.soa_serial }}</td>
129
127
  </tr>
130
128
  {% endif %}
131
129
  <tr>
132
- <th scope="row">Refresh</th>
130
+ <th scope="row">{% trans "Refresh" %}</th>
133
131
  <td>{{ object.soa_refresh }}</td>
134
132
  </tr>
135
133
  <tr>
136
- <th scope="row">Retry</th>
134
+ <th scope="row">{% trans "Retry" %}</th>
137
135
  <td>{{ object.soa_retry }}</td>
138
136
  </tr>
139
137
  <tr>
140
- <th scope="row">Expire</th>
138
+ <th scope="row">{% trans "Expire" %}</th>
141
139
  <td>{{ object.soa_expire }}</td>
142
140
  </tr>
143
141
  <tr>
144
- <th scope="row">Minimum TTL</th>
142
+ <th scope="row">{% trans "Minimum TTL" %}</th>
145
143
  <td>{{ object.soa_minimum }}</td>
146
144
  </tr>
147
145
  </table>
148
146
  </div>
149
147
  {% if object.rfc2317_prefix %}
150
148
  <div class="card">
151
- <h5 class="card-header">RFC2317</h5>
149
+ <h5 class="card-header">{% trans "RFC2317" %}</h5>
152
150
  <table class="table table-hover attr-table">
153
151
  <tr>
154
- <th scope="row">Prefix</th>
152
+ <th scope="row">{% trans "Prefix" %}</th>
155
153
  <td>{{ object.rfc2317_prefix }}</td>
156
154
  </tr>
157
155
  <tr>
158
- <th scope="row">Parent Managed</th>
156
+ <th scope="row">{% trans "Parent Managed" %}</th>
159
157
  <td>{% checkmark object.rfc2317_parent_managed %}</td>
160
158
  </tr>
161
159
  {% if object.rfc2317_parent_managed %}
162
160
  <tr>
163
- <th scope="row">Parent Zone</th>
161
+ <th scope="row">{% trans "Parent Zone" %}</th>
164
162
  <td>{{ object.rfc2317_parent_zone|linkify }}</td>
165
163
  </tr>
166
164
  {% endif %}
@@ -3,27 +3,26 @@
3
3
  {% load plugins %}
4
4
  {% load render_table from django_tables2 %}
5
5
  {% load perms %}
6
+ {% load i18n %}
6
7
 
7
8
  {% block content %}
8
9
  <div class="row">
9
10
  <div class="col col-md-6">
10
11
  <div class="card">
11
- <h5 class="card-header">
12
- Zone Template
13
- </h5>
12
+ <h5 class="card-header">{% trans "Zone Template" %}</h5>
14
13
  <table class="table table-hover attr-table">
15
14
  <tr>
16
- <th scope="row">Name</th>
15
+ <th scope="row">{% trans "Name" %}</th>
17
16
  <td>{{ object.name }}</td>
18
17
  </tr>
19
18
  {% if object.description %}
20
19
  <tr>
21
- <th scope="row">Description</th>
20
+ <th scope="row">{% trans "Description" %}</th>
22
21
  <td style="word-break:break-all;">{{ object.description }}</td>
23
22
  </tr>
24
23
  {% endif %}
25
24
  <tr>
26
- <th scope="row">Tenant</th>
25
+ <th scope="row">{% trans "Tenant" %}</th>
27
26
  <td>
28
27
  {% if object.tenant.group %}
29
28
  {{ object.tenant.group|linkify }} /
@@ -32,7 +31,7 @@
32
31
  </td>
33
32
  </tr>
34
33
  <tr>
35
- <th scope="row">Nameservers</th>
34
+ <th scope="row">{% trans "Nameservers" %}</th>
36
35
  <td>
37
36
  <table>
38
37
  {% for nameserver in object.nameservers.all %}
@@ -42,7 +41,7 @@
42
41
  </td>
43
42
  </tr>
44
43
  <tr>
45
- <th scope="row">Description</th>
44
+ <th scope="row">{% trans "Description" %}</th>
46
45
  <td>{{ object.description }}</td>
47
46
  </tr>
48
47
  </table>
@@ -53,34 +52,45 @@
53
52
  </div>
54
53
  <div class="col col-md-6">
55
54
  <div class="card">
56
- <h5 class="card-header">Domain Registration</h5>
55
+ <h5 class="card-header">{% trans "Domain Registration" %}</h5>
57
56
  <table class="table table-hover attr-table">
58
57
  <tr>
59
- <th scope="row">Registrar</th>
58
+ <th scope="row">{% trans "Registrar" %}</th>
60
59
  <td>{{ object.registrar|linkify|placeholder }}</td>
61
60
  </tr>
62
61
  <tr>
63
- <th scope="row">Registrant</th>
62
+ <th scope="row">{% trans "Registrant" %}</th>
64
63
  <td>{{ object.registrant|linkify|placeholder }}</td>
65
64
  </tr>
66
65
  <tr>
67
- <th scope="row">Administrative Contact</th>
66
+ <th scope="row">{% trans "Administrative Contact" %}</th>
68
67
  <td>{{ object.admin_c|linkify|placeholder }}</td>
69
68
  </tr>
70
69
  <tr>
71
- <th scope="row">Technical Contact</th>
70
+ <th scope="row">{% trans "Technical Contact" %}</th>
72
71
  <td>{{ object.tech_c|linkify|placeholder }}</td>
73
72
  </tr>
74
73
  <tr>
75
- <th scope="row">Billing Contact</th>
74
+ <th scope="row">{% trans "Billing Contact" %}</th>
76
75
  <td>{{ object.billing_c|linkify|placeholder }}</td>
77
76
  </tr>
78
77
  </table>
79
78
  </div>
80
79
  </div>
81
80
  </div>
82
- <div class="col col-md-12">
83
- {% include 'inc/panel_table.html' with table=record_template_table heading="Record Templates" %}
84
- </div>
81
+ {% if record_template_table %}
82
+ <div class="col col-md-12">
83
+ <div class="card">
84
+ {% if record_template_table.rows|length == 1 %}
85
+ <h2 class="card-header">{% trans "Record Template" %}</h2>
86
+ {% else %}
87
+ <h2 class="card-header">{% trans "Record Templates" %}</h2>
88
+ {% endif %}
89
+ <div class="table-responsive">
90
+ {% render_table record_template_table 'inc/table.html' %}
91
+ </div>
92
+ </div>
93
+ </div>
94
+ {% endif %}
85
95
  </div>
86
96
  {% endblock %}
@@ -10,9 +10,6 @@ from django.db.models import Q
10
10
  from netbox.context import current_request
11
11
  from ipam.models import IPAddress, Prefix
12
12
 
13
- from netbox_dns.models import zone as _zone
14
- from netbox_dns.models import record as _record
15
- from netbox_dns.models import view as _view
16
13
  from netbox_dns.choices import RecordStatusChoices
17
14
 
18
15
 
@@ -26,6 +23,7 @@ __all__ = (
26
23
  "get_ip_addresses_by_view",
27
24
  "get_ip_addresses_by_zone",
28
25
  "check_record_permission",
26
+ "get_query_from_filter",
29
27
  )
30
28
 
31
29
 
@@ -74,6 +72,8 @@ def _match_data(ip_address, record):
74
72
 
75
73
 
76
74
  def get_zones(ip_address, view=None, old_zone=None):
75
+ from netbox_dns.models import Zone
76
+
77
77
  if view is None:
78
78
  views = _get_assigned_views(ip_address)
79
79
  if not views:
@@ -91,7 +91,7 @@ def get_zones(ip_address, view=None, old_zone=None):
91
91
  for i in range(min_labels + 1, len(fqdn.labels) + 1)
92
92
  ]
93
93
 
94
- zones = _zone.Zone.objects.filter(
94
+ zones = Zone.objects.filter(
95
95
  view__in=views,
96
96
  name__in=zone_name_candidates,
97
97
  active=True,
@@ -114,28 +114,28 @@ def get_zones(ip_address, view=None, old_zone=None):
114
114
 
115
115
 
116
116
  def check_dns_records(ip_address, zone=None, view=None):
117
+ from netbox_dns.models import Zone, Record
118
+
117
119
  if ip_address.dns_name == "":
118
120
  return
119
121
 
120
122
  if zone is None:
121
123
  zones = get_zones(ip_address, view=view)
122
124
 
123
- if ip_address.pk is not None:
125
+ if not ip_address._state.adding:
124
126
  for record in ip_address.netbox_dns_records.filter(zone__in=zones):
125
127
  if not _match_data(ip_address, record):
126
- record.update_from_ip_address(ip_address)
128
+ updated = record.update_from_ip_address(ip_address)
127
129
 
128
- if record is not None:
130
+ if updated:
129
131
  record.clean()
130
132
 
131
- zones = _zone.Zone.objects.filter(
132
- pk__in=[zone.pk for zone in zones]
133
- ).exclude(
133
+ zones = Zone.objects.filter(pk__in=[zone.pk for zone in zones]).exclude(
134
134
  pk__in=set(ip_address.netbox_dns_records.values_list("zone", flat=True))
135
135
  )
136
136
 
137
137
  for zone in zones:
138
- record = _record.Record.create_from_ip_address(
138
+ record = Record.create_from_ip_address(
139
139
  ip_address,
140
140
  zone,
141
141
  )
@@ -143,7 +143,7 @@ def check_dns_records(ip_address, zone=None, view=None):
143
143
  if record is not None:
144
144
  record.clean()
145
145
 
146
- if ip_address.pk is None:
146
+ if ip_address._state.adding:
147
147
  return
148
148
 
149
149
  try:
@@ -152,63 +152,91 @@ def check_dns_records(ip_address, zone=None, view=None):
152
152
  return
153
153
 
154
154
  for record in ip_address.netbox_dns_records.filter(zone=zone):
155
- record.update_from_ip_address(ip_address, new_zone)
155
+ updated = record.update_from_ip_address(ip_address, new_zone)
156
156
 
157
- if record is not None:
157
+ if updated:
158
158
  record.clean(new_zone=new_zone)
159
159
 
160
160
 
161
- def update_dns_records(ip_address):
161
+ def update_dns_records(ip_address, view=None, force=False):
162
+ from netbox_dns.models import Zone, Record
163
+
164
+ updated = False
165
+
162
166
  if ip_address.dns_name == "":
163
- delete_dns_records(ip_address)
164
- return
167
+ return delete_dns_records(ip_address)
168
+
169
+ zones = get_zones(ip_address, view=view)
165
170
 
166
- zones = get_zones(ip_address)
171
+ if not ip_address._state.adding:
172
+ if view is None:
173
+ address_records = ip_address.netbox_dns_records.all()
174
+ else:
175
+ address_records = ip_address.netbox_dns_records.filter(zone__view=view)
167
176
 
168
- if ip_address.pk is not None:
169
- for record in ip_address.netbox_dns_records.all():
177
+ for record in address_records:
170
178
  if record.zone not in zones or ip_address.custom_field_data.get(
171
179
  "ipaddress_dns_disabled"
172
180
  ):
173
181
  record.delete()
182
+ updated = True
174
183
  continue
175
184
 
176
185
  record.update_fqdn()
177
- if not _match_data(ip_address, record):
178
- record.update_from_ip_address(ip_address)
186
+ if not _match_data(ip_address, record) or force:
187
+ updated, deleted = record.update_from_ip_address(ip_address)
179
188
 
180
- if record is not None:
189
+ if deleted:
190
+ record.delete()
191
+ updated = True
192
+ elif updated:
181
193
  record.save()
194
+ updated = True
182
195
 
183
- zones = _zone.Zone.objects.filter(pk__in=[zone.pk for zone in zones]).exclude(
196
+ zones = Zone.objects.filter(pk__in=[zone.pk for zone in zones]).exclude(
184
197
  pk__in=set(
185
198
  ip_address.netbox_dns_records.all().values_list("zone", flat=True)
186
199
  )
187
200
  )
188
201
 
189
202
  for zone in zones:
190
- record = _record.Record.create_from_ip_address(
203
+ record = Record.create_from_ip_address(
191
204
  ip_address,
192
205
  zone,
193
206
  )
194
207
 
195
208
  if record is not None:
196
209
  record.save()
210
+ updated = True
211
+
212
+ return updated
197
213
 
198
214
 
199
- def delete_dns_records(ip_address):
200
- for record in ip_address.netbox_dns_records.all():
215
+ def delete_dns_records(ip_address, view=None):
216
+ deleted = False
217
+
218
+ if view is None:
219
+ address_records = ip_address.netbox_dns_records.all()
220
+ else:
221
+ address_records = ip_address.netbox_dns_records.filter(zone__view=view)
222
+
223
+ for record in address_records:
201
224
  record.delete()
225
+ deleted = True
226
+
227
+ return deleted
202
228
 
203
229
 
204
230
  def get_views_by_prefix(prefix):
231
+ from netbox_dns.models import View
232
+
205
233
  if (views := prefix.netbox_dns_views.all()).exists():
206
234
  return views
207
235
 
208
236
  if (parent := prefix.get_parents().filter(netbox_dns_views__isnull=False)).exists():
209
237
  return parent.last().netbox_dns_views.all()
210
238
 
211
- return _view.View.objects.none()
239
+ return View.objects.none()
212
240
 
213
241
 
214
242
  def get_ip_addresses_by_prefix(prefix, check_view=True):
@@ -293,3 +321,18 @@ def check_record_permission(add=True, change=True, delete=True):
293
321
  if check
294
322
  )
295
323
  )
324
+
325
+
326
+ def get_query_from_filter(ip_address_filter):
327
+ query = Q()
328
+
329
+ if not isinstance(ip_address_filter, list):
330
+ ip_address_filter = [ip_address_filter]
331
+
332
+ for condition in ip_address_filter:
333
+ if condition:
334
+ query |= Q(**condition)
335
+ else:
336
+ return Q()
337
+
338
+ return query
@@ -1,6 +1,7 @@
1
1
  import re
2
2
 
3
3
  from django.core.exceptions import ValidationError
4
+ from django.utils.translation import gettext as _
4
5
 
5
6
  from netbox.plugins.utils import get_plugin_config
6
7
 
@@ -55,7 +56,9 @@ def validate_fqdn(name, always_tolerant=False):
55
56
  regex = rf"^(\*|{label})(\.{zone_label})+\.?$"
56
57
 
57
58
  if not re.match(regex, name, flags=re.IGNORECASE) or _has_invalid_double_dash(name):
58
- raise ValidationError(f"{name} is not a valid fully qualified DNS host name")
59
+ raise ValidationError(
60
+ _("{name} is not a valid fully qualified DNS host name").format(name=name)
61
+ )
59
62
 
60
63
 
61
64
  def validate_rname(name, always_tolerant=False):
@@ -63,7 +66,7 @@ def validate_rname(name, always_tolerant=False):
63
66
  regex = rf"^(\*|{label})(\\\.{label})*(\.{zone_label}){{2,}}\.?$"
64
67
 
65
68
  if not re.match(regex, name, flags=re.IGNORECASE) or _has_invalid_double_dash(name):
66
- raise ValidationError(f"{name} is not a valid RNAME")
69
+ raise ValidationError(_("{name} is not a valid RName").format(name=name))
67
70
 
68
71
 
69
72
  def validate_generic_name(
@@ -76,7 +79,9 @@ def validate_generic_name(
76
79
  regex = rf"^([*@]|(\*\.)?{label}(\.{zone_label})*\.?)$"
77
80
 
78
81
  if not re.match(regex, name, flags=re.IGNORECASE) or _has_invalid_double_dash(name):
79
- raise ValidationError(f"{name} is not a valid DNS host name")
82
+ raise ValidationError(
83
+ _("{name} is not a valid DNS host name").format(name=name)
84
+ )
80
85
 
81
86
 
82
87
  def validate_domain_name(
@@ -97,4 +102,6 @@ def validate_domain_name(
97
102
  regex = rf"^{label}(\.{zone_label})*\.?$"
98
103
 
99
104
  if not re.match(regex, name, flags=re.IGNORECASE) or _has_invalid_double_dash(name):
100
- raise ValidationError(f"{name} is not a valid DNS domain name")
105
+ raise ValidationError(
106
+ _("{name} is not a valid DNS domain name").format(name=name)
107
+ )
@@ -2,6 +2,7 @@ import dns
2
2
  from dns import rdata, name as dns_name
3
3
 
4
4
  from django.core.exceptions import ValidationError
5
+ from django.utils.translation import gettext as _
5
6
 
6
7
  from netbox_dns.choices import RecordClassChoices, RecordTypeChoices
7
8
  from netbox_dns.validators import (
@@ -20,15 +21,19 @@ def validate_record_value(record_type, value):
20
21
  name.to_unicode()
21
22
  except dns_name.IDNAException as exc:
22
23
  raise ValidationError(
23
- f"{name.to_text()} is not a valid IDN: {exc}."
24
- ) from None
24
+ "{name} is not a valid IDN: {error}.".format(
25
+ name=name.to_text(), error=exc
26
+ )
27
+ )
25
28
 
26
29
  try:
27
30
  rr = rdata.from_text(RecordClassChoices.IN, record_type, value)
28
31
  except dns.exception.SyntaxError as exc:
29
32
  raise ValidationError(
30
- f"Record value {value} is not a valid value for a {record_type} record: {exc}."
31
- ) from None
33
+ _(
34
+ "Record value {value} is not a valid value for a {type} record: {error}."
35
+ ).format(value=value, type=record_type, error=exc)
36
+ )
32
37
 
33
38
  match record_type:
34
39
  case RecordTypeChoices.CNAME: