GithubHelp home page GithubHelp logo

sjm-steffann / netbox-ddns Goto Github PK

View Code? Open in Web Editor NEW
93.0 16.0 18.0 82 KB

Dynamic DNS Connector for NetBox

License: Apache License 2.0

Python 94.31% HTML 5.69%
netbox dns dns-updates netbox-plugin hacktoberfest

netbox-ddns's Introduction

Dynamic DNS Connector for NetBox

This plugin lets you define DNS servers that support RFC3007 Dynamic DNS Updates. For each server you specify which domains and reverse DNS domains it is responsible for, and after that NetBox will automatically send DNS Updates to those servers whenever you change the DNS name of an IP Address in NetBox.

Updates are sent from the worker process in the background. You can see their progress either by configuring Django logging or by looking at the Background Tasks in the NetBox admin back-end.

For now all configuration is done in the NetBox admin back-end. A later version will provide a nicer user interface.

Compatibility

This plugin in compatible with NetBox v3.0.0 and greater, support for Netbox v2.11.0 is dropped in v1.1.4 due to UI implementation.

Important

Netbox 4.0 - Admin interface disabled by default
Can be re-enabled by specifying DJANGO_ADMIN_ENABLED = True in configuration.py
If static files are not loaded, re-run upgrade.sh this will copy back the required static assets.

Installation

First, add netbox-ddns to your /opt/netbox/local_requirements.txt file. Create it if it doesn't exist.

Then enable the plugin in /opt/netbox/netbox/netbox/configuration.py, like:

PLUGINS = [
    'netbox_ddns',
]

And finally run /opt/netbox/upgrade.sh. This will download and install the plugin and update the database when necessary. Don't forget to run sudo systemctl restart netbox netbox-rq like upgrade.sh tells you!

netbox-ddns's People

Contributors

blipnet avatar jacobw avatar secure-xxx avatar steffann avatar tsv1991 avatar wmclendon avatar ywatchman avatar zejar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

netbox-ddns's Issues

Support netbox 3.2.x versions

When I upgrade Netbox to version 3.2.0, netbox_ddns plugin can not been installed.

Traceback (most recent call last):
  File "/opt/netbox-3.2.0/netbox/manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "/opt/netbox-3.2.0/venv/lib64/python3.9/site-packages/django/core/management/__init__.py", line 446, in execute_from_command_line
    utility.execute()
  File "/opt/netbox-3.2.0/venv/lib64/python3.9/site-packages/django/core/management/__init__.py", line 420, in execute
    django.setup()
  File "/opt/netbox-3.2.0/venv/lib64/python3.9/site-packages/django/__init__.py", line 24, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/opt/netbox-3.2.0/venv/lib64/python3.9/site-packages/django/apps/registry.py", line 124, in populate
    app_config.ready()
  File "/opt/netbox-3.2.0/venv/lib64/python3.9/site-packages/netbox_ddns/__init__.py", line 25, in ready
    super().ready()
  File "/opt/netbox-3.2.0/netbox/extras/plugins/__init__.py", line 68, in ready
    template_extensions = import_object(f"{self.__module__}.{self.template_extensions}")
  File "/opt/netbox-3.2.0/netbox/extras/plugins/utils.py", line 31, in import_object
    spec.loader.exec_module(module)
  File "<frozen importlib._bootstrap_external>", line 850, in exec_module
  File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
  File "/opt/netbox-3.2.0/venv/lib64/python3.9/site-packages/netbox_ddns/template_content.py", line 5, in <module>
    from . import tables
  File "/opt/netbox-3.2.0/venv/lib64/python3.9/site-packages/netbox_ddns/tables.py", line 4, in <module>
    from utilities.tables import BaseTable, ToggleColumn
ImportError: cannot import name 'BaseTable' from 'utilities.tables' (/opt/netbox-3.2.0/netbox/utilities/tables.py)```

Publish to PyPi

Feature Request: Publish to PyPi

Reason:

Publishing to PyPi would allow users to update this plugin using pip & automatically via the NetBox upgrade process when it is added to the local-requirements.txt file in the NetBox directory.

Add Support for Netbox 3.4

Hello,
like a couple of time ago, now i cant use netbox_ddns with Netbox 3.4.
I have installed Netbox 3.4.2 and while running upgrade.sh theres the following message:
django.core.exceptions.ImproperlyConfigured: Plugin netbox_ddns requires NetBox maximum version 3.3.999.

Can you please add support for that version?

Does not work with netbox 3.7

File "/opt/netbox-3.7.0/netbox/netbox/settings.py", line 798, in
plugin_config.validate(PLUGINS_CONFIG[plugin_name], VERSION)
File "/opt/netbox-3.7.0/netbox/netbox/plugins/init.py", line 141, in validate
raise ImproperlyConfigured(
django.core.exceptions.ImproperlyConfigured: Plugin netbox_ddns requires NetBox maximum version 3.6.999.

Add a list view for all DNS names

Proposed Functionality

Add a view, that lists all DNS names, so it's easy to see what is managed by DDNS plugin.

Use Case

A single view would ease managing multiple hostnames with DDNS.

It would be nice to be able to view, edit and delete the DNS Names from single view, instead of going through all of them one by one.

Pypi release that supports v3.2?

Hello,

I saw that in issue #24 and in PR #25 this plugin was updated to support Netbox v3.2, however it doesn't appear a new pypi release was done, so anyone that just has netbox-ddns in their local requirements will fail indicating it only supports v3.1 during the setup.sh run -- at the least, mine did.

For anyone else that runs into this, I was able to fix this by updating my local_requirements.txt file to have this instead:

#netbox-ddns
# using this to get the main branch...
git+https://github.com/sjm-steffann/netbox-ddns.git

This seems to have resolved my issue -- at the least, Netbox is back up and got no errors with the plugin included!

Bug: Prefix is not validated when adding reverse zone

When not providing a CIDR in the prefix field, the following exception is thrown:

10:00:27: Internal Server Error: /admin/netbox_ddns/reversezone/add/
Traceback (most recent call last):
  File "/opt/netbox/current/venv-py3/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/opt/netbox/current/venv-py3/lib/python3.6/site-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/opt/netbox/current/venv-py3/lib/python3.6/site-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/opt/netbox/current/venv-py3/lib/python3.6/site-packages/django/contrib/admin/options.py", line 607, in wrapper
    return self.admin_site.admin_view(view)(*args, **kwargs)
  File "/opt/netbox/current/venv-py3/lib/python3.6/site-packages/django/utils/decorators.py", line 130, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/opt/netbox/current/venv-py3/lib/python3.6/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func
    response = view_func(request, *args, **kwargs)
  File "/opt/netbox/current/venv-py3/lib/python3.6/site-packages/django/contrib/admin/sites.py", line 231, in inner
    return view(request, *args, **kwargs)
  File "/opt/netbox/current/venv-py3/lib/python3.6/site-packages/django/contrib/admin/options.py", line 1638, in add_view
    return self.changeform_view(request, None, form_url, extra_context)
  File "/opt/netbox/current/venv-py3/lib/python3.6/site-packages/django/utils/decorators.py", line 43, in _wrapper
    return bound_method(*args, **kwargs)
  File "/opt/netbox/current/venv-py3/lib/python3.6/site-packages/django/utils/decorators.py", line 130, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/opt/netbox/current/venv-py3/lib/python3.6/site-packages/django/contrib/admin/options.py", line 1522, in changeform_view
    return self._changeform_view(request, object_id, form_url, extra_context)
  File "/opt/netbox/current/venv-py3/lib/python3.6/site-packages/django/contrib/admin/options.py", line 1558, in _changeform_view
    form_validated = form.is_valid()
  File "/opt/netbox/current/venv-py3/lib/python3.6/site-packages/django/forms/forms.py", line 180, in is_valid
    return self.is_bound and not self.errors
  File "/opt/netbox/current/venv-py3/lib/python3.6/site-packages/django/forms/forms.py", line 175, in errors
    self.full_clean()
  File "/opt/netbox/current/venv-py3/lib/python3.6/site-packages/django/forms/forms.py", line 378, in full_clean
    self._post_clean()
  File "/opt/netbox/current/venv-py3/lib/python3.6/site-packages/django/forms/models.py", line 404, in _post_clean
    self.instance.full_clean(exclude=exclude, validate_unique=False)
  File "/opt/netbox/current/venv-py3/lib/python3.6/site-packages/django/db/models/base.py", line 1207, in full_clean
    self.clean()
  File "/opt/netbox/current/venv-py3/lib/python3.6/site-packages/netbox_ddns/models.py", line 230, in clean
    if self.prefix.version == 4:
AttributeError: 'str' object has no attribute 'version'

Support Netbox 3.1.x

When I try to upgrade Netbox From 3.0.x to 3.1.x, i get error message:

django.core.exceptions.ImproperlyConfigured: Plugin netbox_ddns requires NetBox maximum version 3.0.999.

I think that version v1.2.0 will be great work with Netbox 3.1.x

Broken with netbox-v2.11.6

If this plugin has been installed anytime in the past in a netbox instance, that instance will no longer work correctly when updated to netbox-v2.11.4 or newer.

How does one undo the db changes, if one wishes to not use this plugin anymore?

2021-06-16 09:12:53.764 PDT [1327333] ERROR:  update or delete on table "ipam_ipaddress" violates foreign key constraint "netbox_ddns_dnsstatu_ip_address_id_b2a2168d_fk_ipam_ipad" on tab
le "netbox_ddns_dnsstatus"
2021-06-16 09:12:53.764 PDT [1327333] DETAIL:  Key (id)=(2167) is still referenced from table "netbox_ddns_dnsstatus".
2021-06-16 09:12:53.764 PDT [1327333] STATEMENT:  COMMIT

Installation steps not applicable for Netbox Docker setup

upgrade.sh will fail with dependencies error when running netbox-docker (gcc related). Also no systemctl is included on Alpine docker image from main build https://github.com/netbox-community/netbox-docker

× python setup.py egg_info did not run successfully.
│ exit code: 1
╰─> [7 lines of output]
/usr/lib/gcc/x86_64-alpine-linux-musl/10.3.1/../../../../x86_64-alpine-linux-musl/bin/ld: cannot find Scrt1.o: No such file or directory
/usr/lib/gcc/x86_64-alpine-linux-musl/10.3.1/../../../../x86_64-alpine-linux-musl/bin/ld: cannot find crti.o: No such file or directory
/usr/lib/gcc/x86_64-alpine-linux-musl/10.3.1/../../../../x86_64-alpine-linux-musl/bin/ld: cannot find -lssp_nonshared
collect2: error: ld returned 1 exit status
sys.argv ['/tmp/pip-install-8azecwv0/ruamel-yaml-clib_499f18dc73c743ea86e47acc6c498bf1/setup.py', 'egg_info', '--egg-base', '/tmp/pip-pip-egg-info-249cq7qa']
test compiling /tmp/tmp_ruamel_9j_rnwv4/test_ruamel_yaml.c -> test_ruamel_yaml link error /tmp/tmp_ruamel_9j_rnwv4/test_ruamel_yaml.c
Exception: command '/usr/bin/gcc' failed with exit code 1
[end of output]

note: This error originates from a subprocess, and is likely not a problem with pip.
error: metadata-generation-failed

Reverse DNS does not update 10.0.0.0/24 against BIND9 DNS

I see in Netbox Background Tasks that when trying to add a test.mgmt.local 10.0.0.10, the Forward DNS gets updated fine but not the Reverse DNS. It doesn't look like Netbox is trying to add PTR for any 10 networks. Is this a bug or by design?

No support for toplevel domains?

I am trying to use toplevel names for internal DNS zones but it looks like this is not supported. I am using devicename.location. However when i try to recreate DNS records the reverse record gets updated (dns server log also show this) but the forward domain (location) is not

Nov  6 01:58:35 ns01 pdns_server[1385748]: UPDATE (51429) from x.x.x.x for 168.192.in-addr.arpa: Processing started.
Nov  6 01:58:35 ns01 pdns_server[1385748]: UPDATE (51429) from x.x.x.x for 168.192.in-addr.arpa: starting transaction.
Nov  6 01:58:35 ns01 pdns_server[1385748]: UPDATE (51429) from x.x.x.x for 168.192.in-addr.arpa: Replace for record 252.110.168.192.in-addr.arpa|PTR requested, but no changes made.
Nov  6 01:58:35 ns01 pdns_server[1385748]: UPDATE (51429) from x.x.x.x for 168.192.in-addr.arpa: Update completed, 0 changes, rolling back.

Netbox fails with the message

Last update	Nov. 6, 2021 12:58 a.m.
Forward DNS	Create: Server not authoritative
Reverse DNS	Create: Success

note location.nl as forward DNS is working fine and the pdns database looks good for the "location" zone

Allow creating delegations for prefixes

Proposed functionality

Add NS records for .arpa zones to delegate prefixes.

Use case

By allowing the creation of NS records, you can define customer's nameservers so they can control their zone locally.

Database changes

....

Plugin is not sending DNS updates "socket.gaierror: [Errno -8]"

Hello,
I get the following errors when I try to update or create a DNS record:

Traceback (most recent call last):
File "/opt/netbox/venv/lib/python3.10/site-packages/rq/worker.py", line 1359, in perform_job
rv = job.perform()
File "/opt/netbox/venv/lib/python3.10/site-packages/rq/job.py", line 1178, in perform
self._result = self._execute()
File "/opt/netbox/venv/lib/python3.10/site-packages/rq/job.py", line 1215, in _execute
result = self.func(*self.args, **self.kwargs)
File "/opt/netbox/venv/lib/python3.10/site-packages/netbox_ddns/background_tasks.py", line 189, in dns_delete
delete_forward(dns_name, address, status, output)
File "/opt/netbox/venv/lib/python3.10/site-packages/netbox_ddns/background_tasks.py", line 83, in delete_forward
response = dns.query.udp(update, zone.server.address, port=zone.server.server_port)
File "/opt/netbox/venv/lib/python3.10/site-packages/netbox_ddns/models.py", line 116, in address
addrinfo = socket.getaddrinfo(self.server, 'domain', proto=socket.IPPROTO_UDP)
File "/usr/lib/python3.10/socket.py", line 955, in getaddrinfo
for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -8] Servname not supported for ai_socktype

Could you please help me with that issue?
Netbox v3.4.4

Error when adding extra DNS names

When clicking on the "+ Add extra DNS name" button under the Extra DNS Names section of an IP Address, I get the following error:

Server Error

There was a problem with your request. Please contact an administrator.

The complete exception is provided below:

<class 'AttributeError'>

'NoneType' object has no attribute 'model'

Python version: 3.7.3
NetBox version: 2.9.3

Error in frontend ipam/ip-addresses view when adding extra DNS name

Hi all,

First of all, thank you for this magnificent plugin as it allows me to manage my intenal DNS seamlessly from Netbox.
I'm using Netbox v3.1.6 in a k8s cluster with a customized image in which I've installed the plugin. Everything is working great functionally and both forward as reverse records are being correctly updated in my Powerdns server.

I have however encountered an error after adding an extra DNS name to a Netbox IP object (both through the frontend as admin panel). The extra record is added correctly in the database and is being pushed to the DNS, however, whenever such an extra DNS name is added, when I open the IP address details in the Netbox frontend, I encountered following error:

Request Method:  GET
http://xxxxx/ipam/ip-addresses/7/
3.2.11
TypeError
for linkify=True, '9' must have a method get_absolute_url
/usr/lib/python3.9/site-packages/django_tables2/columns/base.py, line 114, in compose_url
/usr/sbin/uwsgi
3.9.7
['.',  '',  '/usr/lib/python39.zip',  '/usr/lib/python3.9',  '/usr/lib/python3.9/lib-dynload',  '/usr/lib/python3.9/site-packages']

In template /app/netbox/netbox/templates/inc/table.html, error at line 20

for linkify=True, '9' must have a method get_absolute_url

I'm not a dev myself and have no experience with Django but decided to do some digging and came to the conclusion the inc/table.html template was expecting a different table class as it was looking for missing attributes.

After some trial and error, I got results after one change to tables.py line 33, replacing:
class PrefixTable(BaseTable):
with:
class PrefixTable(tables.Table):

And everything was displaying and working fine!

netboxddns

I'm lacking test data to determine if this is a bug or related to wrong configuration on my side (although all Netbox settings are on default and no other plugins are installed). So I was wondering other users experience the same issue and this is something that needs fixing.

Full trace:

Environment:


Request Method: GET
Request URL: http://xxxx/ipam/ip-addresses/7/

Django Version: 3.2.11
Python Version: 3.9.7
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.humanize',
 'corsheaders',
 'debug_toolbar',
 'graphiql_debug_toolbar',
 'django_filters',
 'django_tables2',
 'django_prometheus',
 'graphene_django',
 'mptt',
 'rest_framework',
 'social_django',
 'taggit',
 'timezone_field',
 'circuits',
 'dcim',
 'ipam',
 'extras',
 'tenancy',
 'users',
 'utilities',
 'virtualization',
 'wireless',
 'django_rq',
 'drf_yasg',
 'netbox_ddns.NetBoxDDNSConfig']
Installed Middleware:
['graphiql_debug_toolbar.middleware.DebugToolbarMiddleware',
 'django_prometheus.middleware.PrometheusBeforeMiddleware',
 'corsheaders.middleware.CorsMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware',
 'django.middleware.security.SecurityMiddleware',
 'netbox.middleware.ExceptionHandlingMiddleware',
 'netbox.middleware.RemoteUserMiddleware',
 'netbox.middleware.LoginRequiredMiddleware',
 'netbox.middleware.DynamicConfigMiddleware',
 'netbox.middleware.APIVersionMiddleware',
 'netbox.middleware.ObjectChangeMiddleware',
 'django_prometheus.middleware.PrometheusAfterMiddleware']


Template error:
In template /app/netbox/netbox/templates/inc/table.html, error at line 20
   for linkify=True, '9' must have a method get_absolute_url
   10 :           {% else %}
   11 :             <th {{ column.attrs.th.as_html }}>{{ column.header }}</th>
   12 :           {% endif %}
   13 :         {% endfor %}
   14 :       </tr>
   15 :     </thead>
   16 :   {% endif %}
   17 :   <tbody>
   18 :     {% for row in table.page.object_list|default:table.rows %}
   19 :       <tr {{ row.attrs.as_html }}>
   20 :          {% for column, cell in row.items %} 
   21 :           <td {{ column.attrs.td.as_html }}>{{ cell }}</td>
   22 :         {% endfor %}
   23 :       </tr>
   24 :     {% empty %}
   25 :       {% if table.empty_text %}
   26 :         <tr>
   27 :           <td colspan="{{ table.columns|length }}" class="text-center text-muted">&mdash; {{ table.empty_text }} &mdash;</td>
   28 :         </tr>
   29 :       {% endif %}
   30 :     {% endfor %}


Traceback (most recent call last):
  File "/usr/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/usr/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/lib/python3.9/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/app/netbox/netbox/./utilities/views.py", line 93, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "/usr/lib/python3.9/site-packages/django/views/generic/base.py", line 98, in dispatch
    return handler(request, *args, **kwargs)
  File "/app/netbox/netbox/./netbox/views/generic.py", line 71, in get
    return render(request, self.get_template_name(), {
  File "/usr/lib/python3.9/site-packages/django/shortcuts.py", line 19, in render
    content = loader.render_to_string(template_name, context, request, using=using)
  File "/usr/lib/python3.9/site-packages/django/template/loader.py", line 62, in render_to_string
    return template.render(context, request)
  File "/usr/lib/python3.9/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 170, in render
    return self._render(context)
  File "/usr/lib/python3.9/site-packages/django/test/utils.py", line 100, in instrumented_test_render
    return self.nodelist.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/usr/lib/python3.9/site-packages/django/test/utils.py", line 100, in instrumented_test_render
    return self.nodelist.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/usr/lib/python3.9/site-packages/django/test/utils.py", line 100, in instrumented_test_render
    return self.nodelist.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/usr/lib/python3.9/site-packages/django/test/utils.py", line 100, in instrumented_test_render
    return self.nodelist.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/library.py", line 192, in render
    output = self.func(*resolved_args, **resolved_kwargs)
  File "/app/netbox/netbox/./extras/templatetags/plugins.py", line 59, in plugin_left_page
    return _get_registered_content(obj, 'left_page', context)
  File "/app/netbox/netbox/./extras/templatetags/plugins.py", line 40, in _get_registered_content
    content = getattr(instance, method)()
  File "/usr/lib/python3.9/site-packages/netbox_ddns/template_content.py", line 30, in left_page
    self.render('netbox_ddns/ipaddress/dns_extra.html', {
  File "/app/netbox/netbox/./extras/plugins/__init__.py", line 134, in render
    return get_template(template_name).render({**self.context, **extra_context})
  File "/usr/lib/python3.9/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 170, in render
    return self._render(context)
  File "/usr/lib/python3.9/site-packages/django/test/utils.py", line 100, in instrumented_test_render
    return self.nodelist.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/defaulttags.py", line 312, in render
    return nodelist.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/lib/python3.9/site-packages/django_tables2/templatetags/django_tables2.py", line 167, in render
    return template.render(context={"table": table}, request=request)
  File "/usr/lib/python3.9/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 170, in render
    return self._render(context)
  File "/usr/lib/python3.9/site-packages/django/test/utils.py", line 100, in instrumented_test_render
    return self.nodelist.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/defaulttags.py", line 211, in render
    nodelist.append(node.render_annotated(context))
  File "/usr/lib/python3.9/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/lib/python3.9/site-packages/django/template/defaulttags.py", line 167, in render
    values = list(values)
  File "/usr/lib/python3.9/site-packages/django_tables2/rows.py", line 244, in items
    column.current_value = self.get_cell(column.name)
  File "/usr/lib/python3.9/site-packages/django_tables2/rows.py", line 197, in get_cell
    return self._get_and_render_with(
  File "/usr/lib/python3.9/site-packages/django_tables2/rows.py", line 173, in _get_and_render_with
    return render_func(bound_column, value)
  File "/usr/lib/python3.9/site-packages/django_tables2/rows.py", line 208, in _call_render
    return bound_column.link(content, **render_kwargs) if bound_column.link else content
  File "/usr/lib/python3.9/site-packages/django_tables2/columns/base.py", line 152, in __call__
    attrs = self.get_attrs(**kwargs)
  File "/usr/lib/python3.9/site-packages/django_tables2/columns/base.py", line 147, in get_attrs
    attrs["href"] = self.compose_url(**kwargs)
  File "/usr/lib/python3.9/site-packages/django_tables2/columns/base.py", line 114, in compose_url
    raise TypeError(

Exception Type: TypeError at /ipam/ip-addresses/7/
Exception Value: for linkify=True, '9' must have a method get_absolute_url

Align datetime format with netbox

Netbox have a helper called annotated_date that fixes the datetime format.

In netbox_ddns/templates/netbox_ddns/ipaddress/dns_info.html

Add following at top:
{% load helpers %}

Add the filter where last_updated is printed:

                <tr>
                    <th scope="row">Last update</th>
                    <td>
                        {{ object.dnsstatus.last_update|annotated_date}}
                    </td>
                </tr>

Thanks for a really great plugin

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.