netbox-plugin-dns 1.1.0b2__tar.gz → 1.1b3__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.
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/PKG-INFO +1 -1
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/__init__.py +1 -1
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/forms/view.py +88 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/forms/zone.py +8 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/management/commands/setup_autodns.py +5 -1
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/models/record.py +19 -10
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/models/zone.py +10 -5
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/signals/ipam_autodns.py +62 -11
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/template_content.py +12 -0
- netbox_plugin_dns-1.1b3/netbox_dns/templates/netbox_dns/view/button.html +9 -0
- netbox_plugin_dns-1.1b3/netbox_dns/templates/netbox_dns/view/prefix.html +41 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/urls/view.py +6 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/utilities/ipam_autodns.py +53 -30
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/views/view.py +26 -1
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/pyproject.toml +1 -1
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/LICENSE +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/README.md +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/api/nested_serializers.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/api/serializers.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/api/serializers_/__init__.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/api/serializers_/contact.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/api/serializers_/nameserver.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/api/serializers_/prefix.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/api/serializers_/record.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/api/serializers_/record_template.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/api/serializers_/registrar.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/api/serializers_/view.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/api/serializers_/zone.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/api/serializers_/zone_template.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/api/urls.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/api/views.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/apps.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/choices/__init__.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/choices/record.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/choices/zone.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/fields/__init__.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/fields/address.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/fields/ipam.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/fields/network.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/fields/rfc2317.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/filtersets/__init__.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/filtersets/contact.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/filtersets/nameserver.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/filtersets/record.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/filtersets/record_template.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/filtersets/registrar.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/filtersets/view.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/filtersets/zone.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/filtersets/zone_template.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/forms/__init__.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/forms/contact.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/forms/nameserver.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/forms/record.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/forms/record_template.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/forms/registrar.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/forms/zone_template.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/graphql/__init__.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/graphql/filters.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/graphql/schema.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/graphql/types.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/management/commands/cleanup_database.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/management/commands/cleanup_rrset_ttl.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/management/commands/update_soa.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0001_squashed_netbox_dns_0_15.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0001_squashed_netbox_dns_0_22.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0002_contact_description_registrar_description.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0003_default_view.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0004_create_and_assign_default_view.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0005_alter_zone_view_not_null.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0006_templating.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0007_view_prefixes.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0020_netbox_3_4.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0021_record_ip_address.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0022_search.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0023_alter_record_value.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0024_tenancy.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0025_ipam_coupling_cf.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0026_domain_registration.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0027_alter_registrar_iana_id.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0028_rfc2317_fields.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0029_record_fqdn.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/__init__.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/mixins/__init__.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/mixins/object_modification.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/models/__init__.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/models/contact.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/models/nameserver.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/models/record_template.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/models/registrar.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/models/view.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/models/zone_template.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/navigation.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/signals/__init__.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/tables/__init__.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/tables/contact.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/tables/nameserver.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/tables/record.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/tables/record_template.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/tables/registrar.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/tables/view.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/tables/zone.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/tables/zone_template.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/contact.html +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/nameserver.html +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/record/managed.html +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/record/related.html +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/record.html +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/recordtemplate.html +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/registrar.html +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/view/related.html +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/view.html +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/zone/base.html +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/zone/child.html +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/zone/child_zone.html +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/zone/managed_record.html +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/zone/record.html +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/zone/registration.html +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/zone/rfc2317_child_zone.html +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/zone.html +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/zonetemplate.html +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/urls/__init__.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/urls/contact.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/urls/nameserver.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/urls/record.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/urls/record_template.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/urls/registrar.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/urls/zone.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/urls/zone_template.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/utilities/__init__.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/utilities/conversions.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/validators/__init__.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/validators/dns_name.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/validators/dns_value.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/validators/rfc2317.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/views/__init__.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/views/contact.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/views/nameserver.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/views/record.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/views/record_template.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/views/registrar.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/views/zone.py +0 -0
- {netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/views/zone_template.py +0 -0
|
@@ -21,6 +21,7 @@ from utilities.forms.rendering import FieldSet
|
|
|
21
21
|
from tenancy.models import Tenant
|
|
22
22
|
from tenancy.forms import TenancyForm, TenancyFilterForm
|
|
23
23
|
from ipam.models import Prefix
|
|
24
|
+
from netbox.context import current_request
|
|
24
25
|
|
|
25
26
|
from netbox_dns.models import View
|
|
26
27
|
from netbox_dns.fields import PrefixDynamicModelMultipleChoiceField
|
|
@@ -37,6 +38,7 @@ __all__ = (
|
|
|
37
38
|
"ViewFilterForm",
|
|
38
39
|
"ViewImportForm",
|
|
39
40
|
"ViewBulkEditForm",
|
|
41
|
+
"ViewPrefixEditForm",
|
|
40
42
|
)
|
|
41
43
|
|
|
42
44
|
|
|
@@ -97,6 +99,21 @@ class ViewForm(ViewPrefixUpdateMixin, TenancyForm, NetBoxModelForm):
|
|
|
97
99
|
if settings.PLUGINS_CONFIG["netbox_dns"].get("autodns_disabled"):
|
|
98
100
|
del self.fields["prefixes"]
|
|
99
101
|
|
|
102
|
+
if request := current_request.get():
|
|
103
|
+
if not request.user.has_perm("ipam.view_prefix"):
|
|
104
|
+
self._saved_prefixes = self.initial["prefixes"]
|
|
105
|
+
self.initial["prefixes"] = []
|
|
106
|
+
self.fields["prefixes"].disabled = True
|
|
107
|
+
self.fields["prefixes"].widget.attrs[
|
|
108
|
+
"placeholder"
|
|
109
|
+
] = "You do not have permission to modify assigned prefixes"
|
|
110
|
+
|
|
111
|
+
def clean_prefixes(self):
|
|
112
|
+
if hasattr(self, "_saved_prefixes"):
|
|
113
|
+
return self._saved_prefixes
|
|
114
|
+
|
|
115
|
+
return self.cleaned_data["prefixes"]
|
|
116
|
+
|
|
100
117
|
prefixes = PrefixDynamicModelMultipleChoiceField(
|
|
101
118
|
queryset=Prefix.objects.all(),
|
|
102
119
|
required=False,
|
|
@@ -201,3 +218,74 @@ class ViewBulkEditForm(NetBoxModelBulkEditForm):
|
|
|
201
218
|
)
|
|
202
219
|
|
|
203
220
|
nullable_fields = ("description", "tenant")
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
class ViewPrefixEditForm(forms.ModelForm):
|
|
224
|
+
views = DynamicModelMultipleChoiceField(
|
|
225
|
+
queryset=View.objects.all(),
|
|
226
|
+
required=False,
|
|
227
|
+
label="Assigned DNS Views",
|
|
228
|
+
help_text="Explicitly assigning DNS views overrides all inherited views for this prefix",
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
class Meta:
|
|
232
|
+
model = Prefix
|
|
233
|
+
fields = ("views",)
|
|
234
|
+
|
|
235
|
+
def __init__(self, *args, **kwargs):
|
|
236
|
+
super().__init__(*args, **kwargs)
|
|
237
|
+
|
|
238
|
+
self.initial["views"] = self.instance.netbox_dns_views.all()
|
|
239
|
+
self._permission_denied = False
|
|
240
|
+
|
|
241
|
+
if request := current_request.get():
|
|
242
|
+
if not request.user.has_perm("netbox_dns.change_view"):
|
|
243
|
+
self._permission_denied = True
|
|
244
|
+
self.initial["views"] = []
|
|
245
|
+
self.fields["views"].disabled = True
|
|
246
|
+
self.fields["views"].widget.attrs[
|
|
247
|
+
"placeholder"
|
|
248
|
+
] = "You do not have permission to modify assigned views"
|
|
249
|
+
|
|
250
|
+
def clean(self, *args, **kwargs):
|
|
251
|
+
if self._permission_denied:
|
|
252
|
+
return
|
|
253
|
+
|
|
254
|
+
prefix = self.instance
|
|
255
|
+
|
|
256
|
+
super().clean(*args, **kwargs)
|
|
257
|
+
|
|
258
|
+
views = self.cleaned_data.get("views")
|
|
259
|
+
old_views = prefix.netbox_dns_views.all()
|
|
260
|
+
|
|
261
|
+
check_views = View.objects.none()
|
|
262
|
+
|
|
263
|
+
if not views.exists():
|
|
264
|
+
if (parent := prefix.get_parents().last()) is not None:
|
|
265
|
+
check_views = parent.netbox_dns_views.all().difference(old_views)
|
|
266
|
+
|
|
267
|
+
else:
|
|
268
|
+
check_views = views.difference(old_views)
|
|
269
|
+
|
|
270
|
+
for view in check_views:
|
|
271
|
+
try:
|
|
272
|
+
for ip_address in get_ip_addresses_by_prefix(prefix, check_view=False):
|
|
273
|
+
check_dns_records(ip_address, view=view)
|
|
274
|
+
except ValidationError as exc:
|
|
275
|
+
self.add_error("views", exc.messages)
|
|
276
|
+
|
|
277
|
+
def save(self, *args, **kwargs):
|
|
278
|
+
prefix = self.instance
|
|
279
|
+
|
|
280
|
+
if self._permission_denied:
|
|
281
|
+
return prefix
|
|
282
|
+
|
|
283
|
+
old_views = prefix.netbox_dns_views.all()
|
|
284
|
+
views = self.cleaned_data.get("views")
|
|
285
|
+
|
|
286
|
+
for view in views.difference(old_views):
|
|
287
|
+
view.prefixes.add(prefix)
|
|
288
|
+
for view in old_views.difference(views):
|
|
289
|
+
view.prefixes.remove(prefix)
|
|
290
|
+
|
|
291
|
+
return prefix
|
|
@@ -81,6 +81,14 @@ class ZoneTemplateUpdateMixin:
|
|
|
81
81
|
else:
|
|
82
82
|
zone_data = self.cleaned_data.copy()
|
|
83
83
|
|
|
84
|
+
custom_fields = dict()
|
|
85
|
+
for key, value in zone_data.copy().items():
|
|
86
|
+
if key.startswith("cf_"):
|
|
87
|
+
custom_fields[key[3:]] = value
|
|
88
|
+
zone_data.pop(key)
|
|
89
|
+
if custom_fields:
|
|
90
|
+
zone_data["custom_field_data"] = custom_fields
|
|
91
|
+
|
|
84
92
|
zone_data.pop("template", None)
|
|
85
93
|
zone_data.pop("tenant_group", None)
|
|
86
94
|
zone_data.pop("_init_time", None)
|
|
@@ -30,7 +30,7 @@ class Command(BaseCommand):
|
|
|
30
30
|
name=cf, object_types=ipaddress_object_type
|
|
31
31
|
).delete()
|
|
32
32
|
if options.get("verbosity"):
|
|
33
|
-
self.stdout.write(f"
|
|
33
|
+
self.stdout.write(f"Removed custom field '{cf}'")
|
|
34
34
|
except CustomField.DoesNotExist:
|
|
35
35
|
pass
|
|
36
36
|
return
|
|
@@ -84,6 +84,7 @@ class Command(BaseCommand):
|
|
|
84
84
|
)
|
|
85
85
|
if cf_ttl.group_name != "AutoDNS":
|
|
86
86
|
cf_ttl.group_name = "AutoDNS"
|
|
87
|
+
cf_ttl.description = ("TTL for DNS records created for this address",)
|
|
87
88
|
cf_ttl.save()
|
|
88
89
|
if options.get("verbosity"):
|
|
89
90
|
self.stdout.write("Updated custom field 'ipaddress_dns_record_ttl'")
|
|
@@ -112,6 +113,9 @@ class Command(BaseCommand):
|
|
|
112
113
|
)
|
|
113
114
|
if cf_disable_ptr.group_name != "AutoDNS":
|
|
114
115
|
cf_disable_ptr.group_name = "AutoDNS"
|
|
116
|
+
cf_disable_ptr.description = (
|
|
117
|
+
"Disable DNS PTR record generation for this address",
|
|
118
|
+
)
|
|
115
119
|
cf_disable_ptr.save()
|
|
116
120
|
if options.get("verbosity"):
|
|
117
121
|
self.stdout.write(
|
|
@@ -461,8 +461,11 @@ class Record(ObjectModificationMixin, NetBoxModel):
|
|
|
461
461
|
self.rfc2317_cname_record.delete(save_zone_serial=save_zone_serial)
|
|
462
462
|
self.rfc2317_cname_record = None
|
|
463
463
|
|
|
464
|
-
def update_from_ip_address(self, ip_address):
|
|
465
|
-
|
|
464
|
+
def update_from_ip_address(self, ip_address, zone=None):
|
|
465
|
+
if zone is None:
|
|
466
|
+
zone = self.zone
|
|
467
|
+
|
|
468
|
+
data = record_data_from_ip_address(ip_address, zone)
|
|
466
469
|
|
|
467
470
|
if data is None:
|
|
468
471
|
self.delete()
|
|
@@ -490,9 +493,12 @@ class Record(ObjectModificationMixin, NetBoxModel):
|
|
|
490
493
|
**data,
|
|
491
494
|
)
|
|
492
495
|
|
|
493
|
-
def validate_name(self):
|
|
496
|
+
def validate_name(self, new_zone=None):
|
|
497
|
+
if new_zone is None:
|
|
498
|
+
new_zone = self.zone
|
|
499
|
+
|
|
494
500
|
try:
|
|
495
|
-
_zone = dns_name.from_text(
|
|
501
|
+
_zone = dns_name.from_text(new_zone.name, origin=dns_name.root)
|
|
496
502
|
name = dns_name.from_text(self.name, origin=None)
|
|
497
503
|
fqdn = dns_name.from_text(self.name, origin=_zone)
|
|
498
504
|
|
|
@@ -512,7 +518,7 @@ class Record(ObjectModificationMixin, NetBoxModel):
|
|
|
512
518
|
if not fqdn.is_subdomain(_zone):
|
|
513
519
|
raise ValidationError(
|
|
514
520
|
{
|
|
515
|
-
"name": f"{self.name} is not a name in {
|
|
521
|
+
"name": f"{self.name} is not a name in {new_zone.name}",
|
|
516
522
|
}
|
|
517
523
|
)
|
|
518
524
|
|
|
@@ -544,15 +550,18 @@ class Record(ObjectModificationMixin, NetBoxModel):
|
|
|
544
550
|
except ValidationError as exc:
|
|
545
551
|
raise ValidationError({"value": exc}) from None
|
|
546
552
|
|
|
547
|
-
def check_unique_record(self):
|
|
553
|
+
def check_unique_record(self, new_zone=None):
|
|
548
554
|
if not get_plugin_config("netbox_dns", "enforce_unique_records", False):
|
|
549
555
|
return
|
|
550
556
|
|
|
551
557
|
if not self.is_active:
|
|
552
558
|
return
|
|
553
559
|
|
|
560
|
+
if new_zone is None:
|
|
561
|
+
new_zone = self.zone
|
|
562
|
+
|
|
554
563
|
records = Record.objects.filter(
|
|
555
|
-
zone=
|
|
564
|
+
zone=new_zone,
|
|
556
565
|
name=self.name,
|
|
557
566
|
type=self.type,
|
|
558
567
|
value=self.value,
|
|
@@ -664,10 +673,10 @@ class Record(ObjectModificationMixin, NetBoxModel):
|
|
|
664
673
|
self.type = self.type.upper()
|
|
665
674
|
super().clean_fields(*args, **kwargs)
|
|
666
675
|
|
|
667
|
-
def clean(self, *args, **kwargs):
|
|
668
|
-
self.validate_name()
|
|
676
|
+
def clean(self, *args, new_zone=None, **kwargs):
|
|
677
|
+
self.validate_name(new_zone=new_zone)
|
|
669
678
|
self.validate_value()
|
|
670
|
-
self.check_unique_record()
|
|
679
|
+
self.check_unique_record(new_zone=new_zone)
|
|
671
680
|
if self.pk is None:
|
|
672
681
|
self.check_unique_rrset_ttl()
|
|
673
682
|
|
|
@@ -654,13 +654,18 @@ class Zone(ObjectModificationMixin, NetBoxModel):
|
|
|
654
654
|
)
|
|
655
655
|
|
|
656
656
|
if old_zone.name != self.name or old_zone.view != self.view:
|
|
657
|
-
|
|
658
|
-
|
|
657
|
+
for ip_address in get_ip_addresses_by_zone(self):
|
|
658
|
+
try:
|
|
659
|
+
check_dns_records(ip_address, zone=self)
|
|
660
|
+
except ValidationError as exc:
|
|
661
|
+
raise ValidationError(exc.messages)
|
|
662
|
+
|
|
663
|
+
ip_addresses = IPAddress.objects.filter(
|
|
664
|
+
netbox_dns_records__in=self.record_set.filter(
|
|
659
665
|
ipam_ip_address__isnull=False
|
|
660
|
-
)
|
|
666
|
+
)
|
|
661
667
|
)
|
|
662
|
-
|
|
663
|
-
for ip_address in update_ip_addresses:
|
|
668
|
+
for ip_address in ip_addresses:
|
|
664
669
|
try:
|
|
665
670
|
check_dns_records(ip_address, zone=self)
|
|
666
671
|
except ValidationError as exc:
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from netaddr import IPNetwork
|
|
2
2
|
|
|
3
|
+
from django.conf import settings
|
|
3
4
|
from django.dispatch import receiver
|
|
4
5
|
from django.db.models.signals import pre_delete, pre_save, post_save, m2m_changed
|
|
5
6
|
from django.core.exceptions import ValidationError
|
|
@@ -26,12 +27,47 @@ AUTODNS_CUSTOM_FIELDS = {
|
|
|
26
27
|
"ipaddress_dns_record_disable_ptr": False,
|
|
27
28
|
}
|
|
28
29
|
|
|
30
|
+
IPADDRESS_ACTIVE_STATUS = settings.PLUGINS_CONFIG["netbox_dns"][
|
|
31
|
+
"autodns_ipaddress_active_status"
|
|
32
|
+
]
|
|
33
|
+
ENFORCE_UNIQUE_RECORDS = settings.PLUGINS_CONFIG["netbox_dns"]["enforce_unique_records"]
|
|
34
|
+
|
|
29
35
|
|
|
30
36
|
@receiver(post_clean, sender=IPAddress)
|
|
31
37
|
def ipam_autodns_ipaddress_post_clean(instance, **kwargs):
|
|
32
38
|
if not isinstance(instance.address, IPNetwork):
|
|
33
39
|
return
|
|
34
40
|
|
|
41
|
+
if instance.custom_field_data.get("ipaddress_dns_disabled"):
|
|
42
|
+
return
|
|
43
|
+
|
|
44
|
+
# +
|
|
45
|
+
# Check for uniqueness of IP address and dns_name. If unique records are
|
|
46
|
+
# enforced, report an error when trying to create the same IP address with
|
|
47
|
+
# the same dns_name. Ignore existing IP addresses that have their CF
|
|
48
|
+
# "ipaddress_dns_disabled" set to "True".
|
|
49
|
+
# -
|
|
50
|
+
duplicate_addresses = IPAddress.objects.filter(
|
|
51
|
+
address=instance.address,
|
|
52
|
+
vrf=instance.vrf,
|
|
53
|
+
dns_name=instance.dns_name,
|
|
54
|
+
status__in=IPADDRESS_ACTIVE_STATUS,
|
|
55
|
+
)
|
|
56
|
+
if instance.pk is not None:
|
|
57
|
+
duplicate_addresses = duplicate_addresses.exclude(pk=instance.pk)
|
|
58
|
+
|
|
59
|
+
if ENFORCE_UNIQUE_RECORDS and instance.status in IPADDRESS_ACTIVE_STATUS:
|
|
60
|
+
for ip_address in duplicate_addresses.only("custom_field_data"):
|
|
61
|
+
if not ip_address.custom_field_data.get("ipaddress_dns_disabled"):
|
|
62
|
+
raise ValidationError(
|
|
63
|
+
{
|
|
64
|
+
"dns_name": "Unique DNS records are enforced and there is already "
|
|
65
|
+
f"an active IP address {instance.address} with DNS name {instance.dns_name}. "
|
|
66
|
+
"Plesase choose a different name or disable record creation for this "
|
|
67
|
+
"IP address."
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
|
|
35
71
|
# +
|
|
36
72
|
# Check NetBox DNS record permission for changes to IPAddress custom fields
|
|
37
73
|
#
|
|
@@ -42,21 +78,23 @@ def ipam_autodns_ipaddress_post_clean(instance, **kwargs):
|
|
|
42
78
|
instance.pk is not None
|
|
43
79
|
and any(
|
|
44
80
|
(
|
|
45
|
-
cf_data.get(cf)
|
|
46
|
-
!= IPAddress.objects.get(pk=instance.pk).custom_field_data.get(
|
|
47
|
-
|
|
81
|
+
cf_data.get(cf, cf_default)
|
|
82
|
+
!= IPAddress.objects.get(pk=instance.pk).custom_field_data.get(
|
|
83
|
+
cf, cf_default
|
|
84
|
+
)
|
|
85
|
+
for cf, cf_default in AUTODNS_CUSTOM_FIELDS.items()
|
|
48
86
|
)
|
|
49
87
|
)
|
|
50
|
-
and not check_record_permission(
|
|
88
|
+
and not check_record_permission()
|
|
51
89
|
) or (
|
|
52
90
|
instance.pk is None
|
|
53
91
|
and any(
|
|
54
92
|
(
|
|
55
|
-
cf_data.get(cf) != cf_default
|
|
93
|
+
cf_data.get(cf, cf_default) != cf_default
|
|
56
94
|
for cf, cf_default in AUTODNS_CUSTOM_FIELDS.items()
|
|
57
95
|
)
|
|
58
96
|
)
|
|
59
|
-
and not check_record_permission(
|
|
97
|
+
and not check_record_permission(change=False, delete=False)
|
|
60
98
|
):
|
|
61
99
|
raise ValidationError(
|
|
62
100
|
f"User '{request.user}' is not allowed to alter AutoDNS custom fields"
|
|
@@ -87,16 +125,29 @@ def ipam_autodns_ipaddress_post_save(instance, **kwargs):
|
|
|
87
125
|
def ipam_autodns_prefix_pre_save(instance, **kwargs):
|
|
88
126
|
"""
|
|
89
127
|
Changes that modify the prefix hierarchy cannot be validated properly before
|
|
90
|
-
commiting them. So the solution in this case is to
|
|
91
|
-
|
|
128
|
+
commiting them. So the solution in this case is to ask the user to deassign
|
|
129
|
+
the prefix from any views it is assigned to and retry.
|
|
92
130
|
"""
|
|
131
|
+
request = current_request.get()
|
|
132
|
+
|
|
93
133
|
if instance.pk is None or not instance.netbox_dns_views.exists():
|
|
94
134
|
return
|
|
95
135
|
|
|
96
|
-
saved_prefix = Prefix.objects.get(
|
|
136
|
+
saved_prefix = Prefix.objects.prefetch_related("netbox_dns_views").get(
|
|
137
|
+
pk=instance.pk
|
|
138
|
+
)
|
|
97
139
|
if saved_prefix.prefix != instance.prefix or saved_prefix.vrf != instance.vrf:
|
|
98
|
-
for view in
|
|
99
|
-
|
|
140
|
+
dns_views = ", ".join([view.name for view in instance.netbox_dns_views.all()])
|
|
141
|
+
if request is not None:
|
|
142
|
+
raise AbortRequest(
|
|
143
|
+
f"This prefix is currently assigned to the following DNS views: {dns_views}"
|
|
144
|
+
f"Please deassign it from these views before making changes to the prefix "
|
|
145
|
+
f"or VRF."
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
raise ValidationError(
|
|
149
|
+
f"Prefix is assigned to DNS views {dns_views}. Prefix and VRF must not be changed"
|
|
150
|
+
)
|
|
100
151
|
|
|
101
152
|
|
|
102
153
|
@receiver(pre_delete, sender=Prefix)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from django.conf import settings
|
|
2
|
+
from django.urls import reverse
|
|
2
3
|
|
|
3
4
|
from netbox.plugins.utils import get_plugin_config
|
|
4
5
|
from netbox.plugins import PluginTemplateExtension
|
|
@@ -63,6 +64,17 @@ class RelatedDNSViews(PluginTemplateExtension):
|
|
|
63
64
|
extra_context=context,
|
|
64
65
|
)
|
|
65
66
|
|
|
67
|
+
def buttons(self):
|
|
68
|
+
return self.render(
|
|
69
|
+
"netbox_dns/view/button.html",
|
|
70
|
+
extra_context={
|
|
71
|
+
"url": reverse(
|
|
72
|
+
"plugins:netbox_dns:prefix_views",
|
|
73
|
+
kwargs={"pk": self.context.get("object").pk},
|
|
74
|
+
),
|
|
75
|
+
},
|
|
76
|
+
)
|
|
77
|
+
|
|
66
78
|
|
|
67
79
|
class IPRelatedDNSRecords(PluginTemplateExtension):
|
|
68
80
|
model = "ipam.ipaddress"
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{% load perms %}
|
|
2
|
+
|
|
3
|
+
{% if perms.netbox_dns.change_view %}
|
|
4
|
+
<a href="{{ url }}?return_url={{ object.get_absolute_url }}">
|
|
5
|
+
<button type="submit" class="btn btn-primary" name="assign-view">
|
|
6
|
+
<i class="mdi mdi-eye-outline" aria-hidden="true"></i> DNS Views
|
|
7
|
+
</button>
|
|
8
|
+
</a>
|
|
9
|
+
{% endif %}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{% extends 'generic/_base.html' %}
|
|
2
|
+
|
|
3
|
+
{% block title %}
|
|
4
|
+
Configure DNS views for {{ object|meta:"verbose_name" }} {{ object }} {% if object.vrf %}[{{ object.vrf }}]{% endif %}
|
|
5
|
+
{% endblock title %}
|
|
6
|
+
|
|
7
|
+
{% block content %}
|
|
8
|
+
<div class="tab-pane show active" id="edit-form" role="tabpanel" aria-labelledby="object-list-tab">
|
|
9
|
+
|
|
10
|
+
<form action="" method="post" enctype="multipart/form-data" class="object-edit mt-5">
|
|
11
|
+
{% csrf_token %}
|
|
12
|
+
|
|
13
|
+
<div id="form_fields" hx-disinherit="hx-select hx-swap">
|
|
14
|
+
{% if inherited_from %}
|
|
15
|
+
<div class="card">
|
|
16
|
+
<table class="table table-hover attr-table">
|
|
17
|
+
<th>Views inherited from prefix {{ inherited_from }} {% if inherited_from.vrf %}[{{ inherited_from.vrf }}] {% endif %}</th>
|
|
18
|
+
{% for view in inherited_views %}
|
|
19
|
+
<tr><td>{{ view|linkify }}</td><td>{{ view.description }}</td></tr>
|
|
20
|
+
{% endfor %}
|
|
21
|
+
</table>
|
|
22
|
+
</div>
|
|
23
|
+
{% endif %}
|
|
24
|
+
{% block form %}
|
|
25
|
+
{% include 'htmx/form.html' %}
|
|
26
|
+
{% endblock form %}
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<div class="text-end my-3">
|
|
30
|
+
{% block buttons %}
|
|
31
|
+
<a href="{{ return_url }}" class="btn btn-outline-secondary">Cancel</a>
|
|
32
|
+
<button type="submit" name="_update" class="btn btn-primary">Save</button>
|
|
33
|
+
{% endblock buttons %}
|
|
34
|
+
</div>
|
|
35
|
+
</form>
|
|
36
|
+
</div>
|
|
37
|
+
{% endblock content %}
|
|
38
|
+
|
|
39
|
+
{% block modals %}
|
|
40
|
+
{% include 'inc/htmx_modal.html' with size='lg' %}
|
|
41
|
+
{% endblock %}
|
|
@@ -12,6 +12,7 @@ from netbox_dns.views import (
|
|
|
12
12
|
ViewBulkEditView,
|
|
13
13
|
ViewBulkDeleteView,
|
|
14
14
|
ViewZoneListView,
|
|
15
|
+
ViewPrefixEditView,
|
|
15
16
|
)
|
|
16
17
|
|
|
17
18
|
view_urlpatterns = [
|
|
@@ -36,4 +37,9 @@ view_urlpatterns = [
|
|
|
36
37
|
name="view_changelog",
|
|
37
38
|
kwargs={"model": View},
|
|
38
39
|
),
|
|
40
|
+
path(
|
|
41
|
+
"prefixes/<int:pk>/assign-views/",
|
|
42
|
+
ViewPrefixEditView.as_view(),
|
|
43
|
+
name="prefix_views",
|
|
44
|
+
),
|
|
39
45
|
]
|
|
@@ -52,7 +52,13 @@ def _get_record_status(ip_address):
|
|
|
52
52
|
)
|
|
53
53
|
|
|
54
54
|
|
|
55
|
-
def
|
|
55
|
+
def _valid_entry(ip_address, zone):
|
|
56
|
+
return zone.view in _get_assigned_views(ip_address) and dns_name.from_text(
|
|
57
|
+
ip_address.dns_name
|
|
58
|
+
).is_subdomain(dns_name.from_text(zone.name))
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def get_zones(ip_address, view=None, old_zone=None):
|
|
56
62
|
if view is None:
|
|
57
63
|
views = _get_assigned_views(ip_address)
|
|
58
64
|
if not views:
|
|
@@ -72,10 +78,13 @@ def get_zones(ip_address, view=None):
|
|
|
72
78
|
active=True,
|
|
73
79
|
)
|
|
74
80
|
|
|
75
|
-
if not zones:
|
|
76
|
-
return []
|
|
77
|
-
|
|
78
81
|
zone_map = defaultdict(list)
|
|
82
|
+
|
|
83
|
+
if old_zone is not None:
|
|
84
|
+
zones = zones.exclude(pk=old_zone.pk)
|
|
85
|
+
if _valid_entry(ip_address, old_zone):
|
|
86
|
+
zone_map[old_zone.view].append(old_zone)
|
|
87
|
+
|
|
79
88
|
for zone in zones:
|
|
80
89
|
zone_map[zone.view].append(zone)
|
|
81
90
|
|
|
@@ -91,35 +100,49 @@ def check_dns_records(ip_address, zone=None, view=None):
|
|
|
91
100
|
|
|
92
101
|
if zone is None:
|
|
93
102
|
zones = get_zones(ip_address, view=view)
|
|
94
|
-
else:
|
|
95
|
-
zones = [zone]
|
|
96
|
-
|
|
97
|
-
if ip_address.pk is not None:
|
|
98
|
-
for record in ip_address.netbox_dns_records.filter(zone__in=zones):
|
|
99
|
-
if (
|
|
100
|
-
record.fqdn != ip_address.dns_name
|
|
101
|
-
or record.value != ip_address.address.ip
|
|
102
|
-
or record.status != _get_record_status(ip_address)
|
|
103
|
-
):
|
|
104
|
-
record.update_from_ip_address(ip_address)
|
|
105
103
|
|
|
106
|
-
|
|
107
|
-
|
|
104
|
+
if ip_address.pk is not None:
|
|
105
|
+
for record in ip_address.netbox_dns_records.filter(zone__in=zones):
|
|
106
|
+
if (
|
|
107
|
+
record.fqdn != ip_address.dns_name
|
|
108
|
+
or record.value != ip_address.address.ip
|
|
109
|
+
or record.status != _get_record_status(ip_address)
|
|
110
|
+
):
|
|
111
|
+
record.update_from_ip_address(ip_address)
|
|
112
|
+
|
|
113
|
+
if record is not None:
|
|
114
|
+
record.clean()
|
|
115
|
+
|
|
116
|
+
zones = _zone.Zone.objects.filter(
|
|
117
|
+
pk__in=[zone.pk for zone in zones]
|
|
118
|
+
).exclude(
|
|
119
|
+
pk__in=set(
|
|
120
|
+
ip_address.netbox_dns_records.all().values_list("zone", flat=True)
|
|
121
|
+
)
|
|
122
|
+
)
|
|
108
123
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
ip_address
|
|
124
|
+
for zone in zones:
|
|
125
|
+
record = _record.Record.create_from_ip_address(
|
|
126
|
+
ip_address,
|
|
127
|
+
zone,
|
|
112
128
|
)
|
|
113
|
-
)
|
|
114
129
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
130
|
+
if record is not None:
|
|
131
|
+
record.clean()
|
|
132
|
+
|
|
133
|
+
if ip_address.pk is None:
|
|
134
|
+
return
|
|
135
|
+
|
|
136
|
+
try:
|
|
137
|
+
new_zone = get_zones(ip_address, old_zone=zone)[0]
|
|
138
|
+
except IndexError:
|
|
139
|
+
return
|
|
140
|
+
|
|
141
|
+
for record in ip_address.netbox_dns_records.filter(zone=zone):
|
|
142
|
+
record.update_from_ip_address(ip_address, new_zone)
|
|
120
143
|
|
|
121
144
|
if record is not None:
|
|
122
|
-
record.clean()
|
|
145
|
+
record.clean(new_zone=new_zone)
|
|
123
146
|
|
|
124
147
|
|
|
125
148
|
def update_dns_records(ip_address):
|
|
@@ -240,7 +263,7 @@ def get_ip_addresses_by_zone(zone):
|
|
|
240
263
|
|
|
241
264
|
|
|
242
265
|
def check_record_permission(add=True, change=True, delete=True):
|
|
243
|
-
checks = locals()
|
|
266
|
+
checks = locals().copy()
|
|
244
267
|
|
|
245
268
|
request = current_request.get()
|
|
246
269
|
|
|
@@ -249,8 +272,8 @@ def check_record_permission(add=True, change=True, delete=True):
|
|
|
249
272
|
|
|
250
273
|
return all(
|
|
251
274
|
(
|
|
252
|
-
request.user.has_perm(f"
|
|
253
|
-
for perm, check in
|
|
275
|
+
request.user.has_perm(f"netbox_dns.{perm}_record")
|
|
276
|
+
for perm, check in checks.items()
|
|
254
277
|
if check
|
|
255
278
|
)
|
|
256
279
|
)
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
from utilities.views import ViewTab, register_model_view
|
|
2
2
|
|
|
3
3
|
from netbox.views import generic
|
|
4
|
+
from ipam.models import Prefix
|
|
4
5
|
|
|
5
6
|
from netbox_dns.models import View, Zone
|
|
6
7
|
from netbox_dns.filtersets import ViewFilterSet, ZoneFilterSet
|
|
7
|
-
from netbox_dns.forms import
|
|
8
|
+
from netbox_dns.forms import (
|
|
9
|
+
ViewForm,
|
|
10
|
+
ViewFilterForm,
|
|
11
|
+
ViewImportForm,
|
|
12
|
+
ViewBulkEditForm,
|
|
13
|
+
ViewPrefixEditForm,
|
|
14
|
+
)
|
|
8
15
|
from netbox_dns.tables import ViewTable, ZoneTable
|
|
16
|
+
from netbox_dns.utilities import get_views_by_prefix
|
|
9
17
|
|
|
10
18
|
|
|
11
19
|
__all__ = (
|
|
@@ -17,6 +25,7 @@ __all__ = (
|
|
|
17
25
|
"ViewBulkEditView",
|
|
18
26
|
"ViewBulkDeleteView",
|
|
19
27
|
"ViewZoneListView",
|
|
28
|
+
"ViewPrefixEditView",
|
|
20
29
|
)
|
|
21
30
|
|
|
22
31
|
|
|
@@ -61,6 +70,22 @@ class ViewBulkDeleteView(generic.BulkDeleteView):
|
|
|
61
70
|
table = ViewTable
|
|
62
71
|
|
|
63
72
|
|
|
73
|
+
class ViewPrefixEditView(generic.ObjectEditView):
|
|
74
|
+
queryset = Prefix.objects.all()
|
|
75
|
+
form = ViewPrefixEditForm
|
|
76
|
+
template_name = "netbox_dns/view/prefix.html"
|
|
77
|
+
|
|
78
|
+
def get_extra_context(self, request, instance):
|
|
79
|
+
parents = instance.get_parents()
|
|
80
|
+
if parents:
|
|
81
|
+
return {
|
|
82
|
+
"inherited_views": get_views_by_prefix(parents.last()),
|
|
83
|
+
"inherited_from": parents.filter(netbox_dns_views__isnull=False).last(),
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return {}
|
|
87
|
+
|
|
88
|
+
|
|
64
89
|
@register_model_view(View, "zones")
|
|
65
90
|
class ViewZoneListView(generic.ObjectChildrenView):
|
|
66
91
|
queryset = View.objects.all().prefetch_related("zone_set")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/api/serializers_/__init__.py
RENAMED
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/api/serializers_/contact.py
RENAMED
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/api/serializers_/nameserver.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/api/serializers_/record_template.py
RENAMED
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/api/serializers_/registrar.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/api/serializers_/zone_template.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/filtersets/record_template.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/filtersets/zone_template.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/management/commands/update_soa.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0003_default_view.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0006_templating.py
RENAMED
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0007_view_prefixes.py
RENAMED
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0020_netbox_3_4.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0025_ipam_coupling_cf.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0028_rfc2317_fields.py
RENAMED
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/migrations/0029_record_fqdn.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/mixins/object_modification.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/contact.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/record.html
RENAMED
|
File without changes
|
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/registrar.html
RENAMED
|
File without changes
|
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/view.html
RENAMED
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/zone/base.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{netbox_plugin_dns-1.1.0b2 → netbox_plugin_dns-1.1b3}/netbox_dns/templates/netbox_dns/zone.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|