git: cf3c83159f3d - main - net-mgmt/netbox: Update to 3.7.0

From: Kai Knoblich <kai_at_FreeBSD.org>
Date: Fri, 12 Jan 2024 05:04:38 UTC
The branch main has been updated by kai:

URL: https://cgit.FreeBSD.org/ports/commit/?id=cf3c83159f3dad8355b948caef141c6349a4ff19

commit cf3c83159f3dad8355b948caef141c6349a4ff19
Author:     Kai Knoblich <kai@FreeBSD.org>
AuthorDate: 2024-01-12 05:00:42 +0000
Commit:     Kai Knoblich <kai@FreeBSD.org>
CommitDate: 2024-01-12 05:03:23 +0000

    net-mgmt/netbox: Update to 3.7.0
    
    * Introduce non-default SENTRY option.
    
    Kudos to Thomas Kurschel for some extra testing.
    
    Changelog:
    
    It contains many bugfixes/enhancements and the following new features:
    
    * VPN Tunnels
    * Event Rules
    * Virtual Machine Disks
    * Object Protection Rules
    * Improved Custom Field Visibility Controls
    * Improved Global Search Results
    * Table Column Registration for Plugins
    * Data Backend Registration for Plugins
    
    https://netbox.readthedocs.io/en/stable/release-notes/version-3.7/
    
    MFH:            No (feature release)
---
 net-mgmt/netbox/Makefile                           |  31 ++--
 net-mgmt/netbox/distinfo                           |   6 +-
 net-mgmt/netbox/files/netboxrc.sample.in           |   1 -
 ...tbox_utilities_templatetags_builtins_filters.py |  29 ++++
 net-mgmt/netbox/files/pkg-message.in               |  53 ++++++-
 net-mgmt/netbox/pkg-plist                          | 176 +++++++++++++++++----
 6 files changed, 244 insertions(+), 52 deletions(-)

diff --git a/net-mgmt/netbox/Makefile b/net-mgmt/netbox/Makefile
index 4216bfc9c2b0..5d1eaccd1462 100644
--- a/net-mgmt/netbox/Makefile
+++ b/net-mgmt/netbox/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=	netbox
 DISTVERSIONPREFIX=	v
-DISTVERSION=	3.6.9
+DISTVERSION=	3.7.0
 CATEGORIES=	net-mgmt python
 
 MAINTAINER=	kai@FreeBSD.org
@@ -23,7 +23,7 @@ LICENSE_FILE=	${WRKSRC}/LICENSE.txt
 # - www/py-dj42-django-tables2
 # - www/py-dj42-djangorestframework
 #
-RUN_DEPENDS=	${PYTHON_PKGNAMEPREFIX}django42>=4.2.6<4.3:www/py-django42@${PY_FLAVOR} \
+RUN_DEPENDS=	${PYTHON_PKGNAMEPREFIX}django42>=4.2.8<4.3:www/py-django42@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}dj42-django-cors-headers>=4.3.1<5:www/py-dj42-django-cors-headers@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}dj42-django-debug-toolbar>=4.2.0<5:www/py-dj42-django-debug-toolbar@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}dj42-django-filter>=23.5<24:www/py-dj42-django-filter@${PY_FLAVOR} \
@@ -32,33 +32,32 @@ RUN_DEPENDS=	${PYTHON_PKGNAMEPREFIX}django42>=4.2.6<4.3:www/py-django42@${PY_FLA
 		${PYTHON_PKGNAMEPREFIX}dj42-django-prometheus>=2.3.1<2.4:www/py-dj42-django-prometheus@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}dj42-django-redis>=5.4.0<6:www/py-dj42-django-redis@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}dj42-django-rich>=1.8.0<2:www/py-dj42-django-rich@${PY_FLAVOR} \
-		${PYTHON_PKGNAMEPREFIX}dj42-django-rq>=2.9.0<2.11:devel/py-dj42-django-rq@${PY_FLAVOR} \
-		${PYTHON_PKGNAMEPREFIX}dj42-django-tables2>=2.7<2.8:www/py-dj42-django-tables2@${PY_FLAVOR} \
-		${PYTHON_PKGNAMEPREFIX}dj42-django-taggit>=4.0.0<5:www/py-dj42-django-taggit@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}dj42-django-rq>=2.10.1<2.11:devel/py-dj42-django-rq@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}dj42-django-tables2>=2.7.0<2.8:www/py-dj42-django-tables2@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}dj42-django-taggit>=5.0.1<6:www/py-dj42-django-taggit@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}dj42-django-timezone-field>=6.1.0<7:www/py-dj42-django-timezone-field@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}dj42-djangorestframework>=3.14.0<3.15.0:www/py-dj42-djangorestframework@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}dj42-drf-spectacular>=0.27.0<1:www/py-dj42-drf-spectacular@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}dj42-drf-spectacular-sidecar>=2023.12.1:www/py-dj42-drf-spectacular-sidecar@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}dj42-graphene-django>=3.0.0<3.0.0_99:devel/py-dj42-graphene-django@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}django-pglocks>=1.0.4<1.1:www/py-django-pglocks@${PY_FLAVOR} \
-		${PYTHON_PKGNAMEPREFIX}bleach>=6.0.0<7:www/py-bleach@${PY_FLAVOR} \
-		${PYTHON_PKGNAMEPREFIX}feedparser>=6.0.8<7:textproc/py-feedparser@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}bleach>=6.1.0<7:www/py-bleach@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}feedparser>=6.0.10<7:textproc/py-feedparser@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}Jinja2>=3.1.2<4:devel/py-Jinja2@${PY_FLAVOR} \
-		${PYTHON_PKGNAMEPREFIX}markdown>=3.3.7<3.4:textproc/py-markdown@${PY_FLAVOR} \
-		${PYTHON_PKGNAMEPREFIX}mkdocs-material>=9.4.6<10:textproc/py-mkdocs-material@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}markdown>=3.3.7<3.6:textproc/py-markdown@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}mkdocs-material>=9.5.3<10:textproc/py-mkdocs-material@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}mkdocstrings>=0.24.0<1:textproc/py-mkdocstrings@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}mkdocstrings-python-legacy>0:textproc/py-mkdocstrings-python-legacy@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}netaddr>=0.9.0<1:net/py-netaddr@${PY_FLAVOR} \
-		${PYTHON_PKGNAMEPREFIX}pillow>=10.0.1:graphics/py-pillow@${PY_FLAVOR} \
-		${PYTHON_PKGNAMEPREFIX}psycopg>=3.1.10<4:databases/py-psycopg@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}pillow>=10.1.0:graphics/py-pillow@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}psycopg>=3.1.16<4:databases/py-psycopg@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}requests>=2.31.0<3:www/py-requests@${PY_FLAVOR} \
-		${PYTHON_PKGNAMEPREFIX}sentry-sdk>=1.21.1<2:devel/py-sentry-sdk@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}social-auth-app-django>=5.4.0<6:www/py-social-auth-app-django@${PY_FLAVOR} \
-		${PYTHON_PKGNAMEPREFIX}social-auth-core>=4.4.2<5:security/py-social-auth-core@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}social-auth-core>=4.5.1<5:security/py-social-auth-core@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}svgwrite>=1.4.3<2:graphics/py-svgwrite@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}tablib>=3.5.0<4:textproc/py-tablib@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}tzdata>=2023.3:devel/py-tzdata@${PY_FLAVOR} \
-		${PYTHON_PKGNAMEPREFIX}yaml>=6.0<7:devel/py-yaml@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}yaml>=6.0.1<7:devel/py-yaml@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}gunicorn>=21.2.0<22:www/py-gunicorn@${PY_FLAVOR}
 
 USES=		cpe pgsql:12+ python
@@ -73,15 +72,17 @@ NO_ARCH=	yes
 
 OPTIONS_DEFINE=	EXAMPLES
 OPTIONS_GROUP=	BACKENDS
-OPTIONS_GROUP_BACKENDS=	GIT LDAP S3
+OPTIONS_GROUP_BACKENDS=	GIT LDAP S3 SENTRY
 
 GIT_DESC=	Git backend support
 LDAP_DESC=	LDAP backend support
 S3_DESC=	Amazon S3 backend support
+SENTRY_DESC=	Sentry monitoring support
 
 GIT_RUN_DEPENDS=	${PYTHON_PKGNAMEPREFIX}dulwich>0:devel/py-dulwich@${PY_FLAVOR}
 LDAP_RUN_DEPENDS=	${PYTHON_PKGNAMEPREFIX}dj42-django-auth-ldap>0:www/py-dj42-django-auth-ldap
 S3_RUN_DEPENDS=		${PYTHON_PKGNAMEPREFIX}boto3>0:www/py-boto3@${PY_FLAVOR}
+SENTRY_RUN_DEPENDS=	${PYTHON_PKGNAMEPREFIX}sentry-sdk>0:devel/py-sentry-sdk@${PY_FLAVOR}
 
 do-install:
 	cd ${WRKSRC}/netbox ; \
diff --git a/net-mgmt/netbox/distinfo b/net-mgmt/netbox/distinfo
index 60c1eed0895a..f617e178c1a5 100644
--- a/net-mgmt/netbox/distinfo
+++ b/net-mgmt/netbox/distinfo
@@ -1,3 +1,3 @@
-TIMESTAMP = 1703851409
-SHA256 (netbox-community-netbox-v3.6.9_GH0.tar.gz) = bd7852664dfb9b0d156c25230cfecca029830e1c31c970b4ec314a93339d60d3
-SIZE (netbox-community-netbox-v3.6.9_GH0.tar.gz) = 7286934
+TIMESTAMP = 1703865948
+SHA256 (netbox-community-netbox-v3.7.0_GH0.tar.gz) = 3ee70909c7acc0d0104ee7d339fb3188af2a66c10f8f22935bb14d73c990488a
+SIZE (netbox-community-netbox-v3.7.0_GH0.tar.gz) = 8069413
diff --git a/net-mgmt/netbox/files/netboxrc.sample.in b/net-mgmt/netbox/files/netboxrc.sample.in
index 79ad884f632a..9cd8a29d5569 100644
--- a/net-mgmt/netbox/files/netboxrc.sample.in
+++ b/net-mgmt/netbox/files/netboxrc.sample.in
@@ -101,7 +101,6 @@ netbox_upgrade()
 		%%PYTHON_CMD%% manage.py remove_stale_contenttypes --no-input
 		%%PYTHON_CMD%% manage.py reindex --lazy
 		%%PYTHON_CMD%% manage.py clearsessions
-		%%PYTHON_CMD%% manage.py clearcache
 		echo "Please restart NetBox and the WSGI environment."
 	else
 		echo "NetBox is not running!"
diff --git a/net-mgmt/netbox/files/patch-netbox_utilities_templatetags_builtins_filters.py b/net-mgmt/netbox/files/patch-netbox_utilities_templatetags_builtins_filters.py
new file mode 100644
index 000000000000..6913656e19e5
--- /dev/null
+++ b/net-mgmt/netbox/files/patch-netbox_utilities_templatetags_builtins_filters.py
@@ -0,0 +1,29 @@
+Add backwards compatibility for textproc/py-markdown < 3.4.
+
+Previous releases of py-markdown cannot access the "use_align_attribute"
+configuration option, which was introduced with py-markdown 3.4.
+
+--- netbox/utilities/templatetags/builtins/filters.py.orig	2023-12-29 15:02:38 UTC
++++ netbox/utilities/templatetags/builtins/filters.py
+@@ -163,12 +163,20 @@ def render_markdown(value):
+     if not value:
+         return ''
+ 
++    TE_Shim = None
++
++    try:
++        TE_Shim = TableExtension(use_align_attribute=True)
++    except KeyError:
++        TE_Shim = TableExtension()
++        pass
++
+     # Render Markdown
+     html = markdown(value, extensions=[
+         'def_list',
+         'fenced_code',
+         StrikethroughExtension(),
+-        TableExtension(use_align_attribute=True),
++        TE_Shim,
+     ])
+ 
+     # If the string is not empty wrap it in rendered-markdown to style tables
diff --git a/net-mgmt/netbox/files/pkg-message.in b/net-mgmt/netbox/files/pkg-message.in
index e5ac681ad52b..29b2c056fbfd 100644
--- a/net-mgmt/netbox/files/pkg-message.in
+++ b/net-mgmt/netbox/files/pkg-message.in
@@ -29,7 +29,6 @@ The following steps are required to finish the upgrade:
 # python%%PYTHON_VER%% manage.py remove_stale_contenttypes --no-input
 # python%%PYTHON_VER%% manage.py reindex --lazy
 # python%%PYTHON_VER%% manage.py clearsessions
-# python%%PYTHON_VER%% manage.py clearcache
 
 2. Restart WSGI/httpd environment (supervisord/apache/nginx/etc.)
 EOD
@@ -324,4 +323,56 @@ EOD
    * www/py-boto3			-> non-default S3 option
 EOD
 }
+{ type: upgrade
+  maximum_version: 3.7.0
+  message: <<EOD
+1. The NetBox 3.7 release contains some breaking changes, so the following
+   items should be checked before upgrading:
+
+   * The following fields have been removed from the Webhook model:
+
+     "content_types", "type_create", "type_update", "type_delete",
+     "type_job_start", "type_job_end", "enabled", and "conditions".
+
+     Webhooks are now tied to events via event rules. New event rules will be
+     created for any existing webhooks automatically upon upgrade.
+
+   * The "ui_visibility" field on the custom field model has been replaced with
+     two new fields: "ui_visible" and "ui_editable".
+
+     These new fields will have their values mapped from the original field
+     automatically upon upgrade.
+
+   * The "FeatureQuery" class used internally for querying content types by
+     model feature has been removed. It has been replaced by the new
+     "with_feature()" manager method on NetBox's proxy model for ContentType
+     ("core.models.ContentType").
+
+   * The internal ConfigRevision model has moved from "extras" to "core".
+     Configuration history will be retained throughout the upgrade process.
+
+   * The L2VPN and L2VPNTermination models have moved from the "ipam" app to
+     the new "vpn" app. All object data will be retained, however please note
+     that the relevant API endpoints have likewise moved to "/api/vpn/".
+
+   * The "CustomFieldsMixin", "SavedFiltersMixin", and "TagsMixin" classes
+     have moved from the "extras.forms.mixins" module to
+     "netbox.forms.mixins".
+
+   * The "netbox.models.features.WebhooksMixin" class has been renamed
+     to "EventRulesMixin".
+
+2. The following dependency is now optional and has therefore been converted
+   to a corresponding SENTRY option:
+
+   * devel/py-sentry-sdk	-> non-default SENTRY option
+
+3. Please note that the command "python%%PYTHON_VER%% manage.py clearcache" has
+   been removed.
+
+   The general update instructions in this pkg-message and the netbox sample rc
+   script (available via the EXAMPLES option) have also been updated
+   accordingly.
+EOD
+}
 ]
diff --git a/net-mgmt/netbox/pkg-plist b/net-mgmt/netbox/pkg-plist
index af5794a78bb3..c9e644b54e0b 100644
--- a/net-mgmt/netbox/pkg-plist
+++ b/net-mgmt/netbox/pkg-plist
@@ -43,6 +43,7 @@
 %%DATADIR%%/circuits/migrations/0040_provider_remove_deprecated_fields.py
 %%DATADIR%%/circuits/migrations/0041_standardize_description_comments.py
 %%DATADIR%%/circuits/migrations/0042_provideraccount.py
+%%DATADIR%%/circuits/migrations/0043_circuittype_color.py
 %%DATADIR%%/circuits/migrations/__init__.py
 %%DATADIR%%/circuits/models/__init__.py
 %%DATADIR%%/circuits/models/circuits.py
@@ -83,7 +84,6 @@
 %%DATADIR%%/core/jobs.py
 %%DATADIR%%/core/management/__init__.py
 %%DATADIR%%/core/management/commands/__init__.py
-%%DATADIR%%/core/management/commands/clearcache.py
 %%DATADIR%%/core/management/commands/makemigrations.py
 %%DATADIR%%/core/management/commands/nbshell.py
 %%DATADIR%%/core/management/commands/rqworker.py
@@ -93,14 +93,23 @@
 %%DATADIR%%/core/migrations/0003_job.py
 %%DATADIR%%/core/migrations/0004_replicate_jobresults.py
 %%DATADIR%%/core/migrations/0005_job_created_auto_now.py
+%%DATADIR%%/core/migrations/0006_datasource_type_remove_choices.py
+%%DATADIR%%/core/migrations/0007_job_add_error_field.py
+%%DATADIR%%/core/migrations/0008_contenttype_proxy.py
+%%DATADIR%%/core/migrations/0009_configrevision.py
+%%DATADIR%%/core/migrations/0010_gfk_indexes.py
 %%DATADIR%%/core/migrations/__init__.py
 %%DATADIR%%/core/models/__init__.py
+%%DATADIR%%/core/models/config.py
+%%DATADIR%%/core/models/contenttypes.py
 %%DATADIR%%/core/models/data.py
 %%DATADIR%%/core/models/files.py
 %%DATADIR%%/core/models/jobs.py
 %%DATADIR%%/core/search.py
 %%DATADIR%%/core/signals.py
 %%DATADIR%%/core/tables/__init__.py
+%%DATADIR%%/core/tables/columns.py
+%%DATADIR%%/core/tables/config.py
 %%DATADIR%%/core/tables/data.py
 %%DATADIR%%/core/tables/jobs.py
 %%DATADIR%%/core/tests/__init__.py
@@ -198,6 +207,9 @@
 %%DATADIR%%/dcim/migrations/0180_powerfeed_tenant.py
 %%DATADIR%%/dcim/migrations/0181_rename_device_role_device_role.py
 %%DATADIR%%/dcim/migrations/0182_zero_length_cable_fix.py
+%%DATADIR%%/dcim/migrations/0183_devicetype_exclude_from_utilization.py
+%%DATADIR%%/dcim/migrations/0184_protect_child_interfaces.py
+%%DATADIR%%/dcim/migrations/0185_gfk_indexes.py
 %%DATADIR%%/dcim/migrations/__init__.py
 %%DATADIR%%/dcim/models/__init__.py
 %%DATADIR%%/dcim/models/cables.py
@@ -286,6 +298,7 @@
 %%DATADIR%%/docs/features/context-data.md
 %%DATADIR%%/docs/features/customization.md
 %%DATADIR%%/docs/features/devices-cabling.md
+%%DATADIR%%/docs/features/event-rules.md
 %%DATADIR%%/docs/features/facilities.md
 %%DATADIR%%/docs/features/ipam.md
 %%DATADIR%%/docs/features/journaling.md
@@ -296,6 +309,7 @@
 %%DATADIR%%/docs/features/tenancy.md
 %%DATADIR%%/docs/features/virtualization.md
 %%DATADIR%%/docs/features/vlan-management.md
+%%DATADIR%%/docs/features/vpn-tunnels.md
 %%DATADIR%%/docs/features/wireless.md
 %%DATADIR%%/docs/getting-started/planning.md
 %%DATADIR%%/docs/getting-started/populating-data.md
@@ -334,6 +348,7 @@
 %%DATADIR%%/docs/media/development/github_new_issue.png
 %%DATADIR%%/docs/media/installation/netbox_application_stack.png
 %%DATADIR%%/docs/media/installation/upgrade_paths.png
+%%DATADIR%%/docs/media/misc/netbox_logo.png
 %%DATADIR%%/docs/media/models/dcim_cable_trace.png
 %%DATADIR%%/docs/media/power_distribution.png
 %%DATADIR%%/docs/media/release-notes/netbox30_ui.png
@@ -398,6 +413,7 @@
 %%DATADIR%%/docs/models/extras/customfield.md
 %%DATADIR%%/docs/models/extras/customfieldchoiceset.md
 %%DATADIR%%/docs/models/extras/customlink.md
+%%DATADIR%%/docs/models/extras/eventrule.md
 %%DATADIR%%/docs/models/extras/exporttemplate.md
 %%DATADIR%%/docs/models/extras/imageattachment.md
 %%DATADIR%%/docs/models/extras/journalentry.md
@@ -412,8 +428,6 @@
 %%DATADIR%%/docs/models/ipam/fhrpgroupassignment.md
 %%DATADIR%%/docs/models/ipam/ipaddress.md
 %%DATADIR%%/docs/models/ipam/iprange.md
-%%DATADIR%%/docs/models/ipam/l2vpn.md
-%%DATADIR%%/docs/models/ipam/l2vpntermination.md
 %%DATADIR%%/docs/models/ipam/prefix.md
 %%DATADIR%%/docs/models/ipam/rir.md
 %%DATADIR%%/docs/models/ipam/role.md
@@ -431,8 +445,19 @@
 %%DATADIR%%/docs/models/virtualization/cluster.md
 %%DATADIR%%/docs/models/virtualization/clustergroup.md
 %%DATADIR%%/docs/models/virtualization/clustertype.md
+%%DATADIR%%/docs/models/virtualization/virtualdisk.md
 %%DATADIR%%/docs/models/virtualization/virtualmachine.md
 %%DATADIR%%/docs/models/virtualization/vminterface.md
+%%DATADIR%%/docs/models/vpn/ikepolicy.md
+%%DATADIR%%/docs/models/vpn/ikeproposal.md
+%%DATADIR%%/docs/models/vpn/ipsecpolicy.md
+%%DATADIR%%/docs/models/vpn/ipsecprofile.md
+%%DATADIR%%/docs/models/vpn/ipsecproposal.md
+%%DATADIR%%/docs/models/vpn/l2vpn.md
+%%DATADIR%%/docs/models/vpn/l2vpntermination.md
+%%DATADIR%%/docs/models/vpn/tunnel.md
+%%DATADIR%%/docs/models/vpn/tunnelgroup.md
+%%DATADIR%%/docs/models/vpn/tunneltermination.md
 %%DATADIR%%/docs/models/wireless/wirelesslan.md
 %%DATADIR%%/docs/models/wireless/wirelesslangroup.md
 %%DATADIR%%/docs/models/wireless/wirelesslink.md
@@ -440,6 +465,7 @@
 %%DATADIR%%/docs/netbox_logo.svg
 %%DATADIR%%/docs/plugins/development/background-tasks.md
 %%DATADIR%%/docs/plugins/development/dashboard-widgets.md
+%%DATADIR%%/docs/plugins/development/data-backends.md
 %%DATADIR%%/docs/plugins/development/exceptions.md
 %%DATADIR%%/docs/plugins/development/filtersets.md
 %%DATADIR%%/docs/plugins/development/forms.md
@@ -477,8 +503,8 @@
 %%DATADIR%%/docs/release-notes/version-3.4.md
 %%DATADIR%%/docs/release-notes/version-3.5.md
 %%DATADIR%%/docs/release-notes/version-3.6.md
+%%DATADIR%%/docs/release-notes/version-3.7.md
 %%DATADIR%%/extras/__init__.py
-%%DATADIR%%/extras/admin.py
 %%DATADIR%%/extras/api/__init__.py
 %%DATADIR%%/extras/api/customfields.py
 %%DATADIR%%/extras/api/mixins.py
@@ -499,6 +525,7 @@
 %%DATADIR%%/extras/data/iata.py
 %%DATADIR%%/extras/data/iso_3166.py
 %%DATADIR%%/extras/data/un_locode.py
+%%DATADIR%%/extras/events.py
 %%DATADIR%%/extras/fields.py
 %%DATADIR%%/extras/filters.py
 %%DATADIR%%/extras/filtersets.py
@@ -507,7 +534,6 @@
 %%DATADIR%%/extras/forms/bulk_import.py
 %%DATADIR%%/extras/forms/filtersets.py
 %%DATADIR%%/extras/forms/misc.py
-%%DATADIR%%/extras/forms/mixins.py
 %%DATADIR%%/extras/forms/model_forms.py
 %%DATADIR%%/extras/forms/reports.py
 %%DATADIR%%/extras/forms/scripts.py
@@ -565,6 +591,13 @@
 %%DATADIR%%/extras/migrations/0096_customfieldchoiceset.py
 %%DATADIR%%/extras/migrations/0097_customfield_remove_choices.py
 %%DATADIR%%/extras/migrations/0098_webhook_custom_field_data_webhook_tags.py
+%%DATADIR%%/extras/migrations/0099_cachedvalue_ordering.py
+%%DATADIR%%/extras/migrations/0100_customfield_ui_attrs.py
+%%DATADIR%%/extras/migrations/0101_eventrule.py
+%%DATADIR%%/extras/migrations/0102_move_configrevision.py
+%%DATADIR%%/extras/migrations/0103_gfk_indexes.py
+%%DATADIR%%/extras/migrations/0104_stagedchange_remove_change_logging.py
+%%DATADIR%%/extras/migrations/0105_customfield_min_max_values.py
 %%DATADIR%%/extras/migrations/__init__.py
 %%DATADIR%%/extras/models/__init__.py
 %%DATADIR%%/extras/models/change_logging.py
@@ -597,38 +630,20 @@
 %%DATADIR%%/extras/templatetags/custom_links.py
 %%DATADIR%%/extras/templatetags/dashboard.py
 %%DATADIR%%/extras/templatetags/log_levels.py
-%%DATADIR%%/extras/templatetags/plugins.py
 %%DATADIR%%/extras/tests/__init__.py
-%%DATADIR%%/extras/tests/dummy_plugin/__init__.py
-%%DATADIR%%/extras/tests/dummy_plugin/admin.py
-%%DATADIR%%/extras/tests/dummy_plugin/api/serializers.py
-%%DATADIR%%/extras/tests/dummy_plugin/api/urls.py
-%%DATADIR%%/extras/tests/dummy_plugin/api/views.py
-%%DATADIR%%/extras/tests/dummy_plugin/graphql.py
-%%DATADIR%%/extras/tests/dummy_plugin/middleware.py
-%%DATADIR%%/extras/tests/dummy_plugin/migrations/0001_initial.py
-%%DATADIR%%/extras/tests/dummy_plugin/migrations/__init__.py
-%%DATADIR%%/extras/tests/dummy_plugin/models.py
-%%DATADIR%%/extras/tests/dummy_plugin/navigation.py
-%%DATADIR%%/extras/tests/dummy_plugin/preferences.py
-%%DATADIR%%/extras/tests/dummy_plugin/search.py
-%%DATADIR%%/extras/tests/dummy_plugin/template_content.py
-%%DATADIR%%/extras/tests/dummy_plugin/urls.py
-%%DATADIR%%/extras/tests/dummy_plugin/views.py
 %%DATADIR%%/extras/tests/test_api.py
 %%DATADIR%%/extras/tests/test_changelog.py
 %%DATADIR%%/extras/tests/test_conditions.py
 %%DATADIR%%/extras/tests/test_custom_validation.py
 %%DATADIR%%/extras/tests/test_customfields.py
-%%DATADIR%%/extras/tests/test_customvalidator.py
+%%DATADIR%%/extras/tests/test_customvalidation.py
+%%DATADIR%%/extras/tests/test_event_rules.py
 %%DATADIR%%/extras/tests/test_filtersets.py
 %%DATADIR%%/extras/tests/test_forms.py
 %%DATADIR%%/extras/tests/test_models.py
-%%DATADIR%%/extras/tests/test_plugins.py
 %%DATADIR%%/extras/tests/test_scripts.py
 %%DATADIR%%/extras/tests/test_tags.py
 %%DATADIR%%/extras/tests/test_views.py
-%%DATADIR%%/extras/tests/test_webhooks.py
 %%DATADIR%%/extras/urls.py
 %%DATADIR%%/extras/utils.py
 %%DATADIR%%/extras/validators.py
@@ -688,12 +703,13 @@
 %%DATADIR%%/ipam/migrations/0065_asnrange.py
 %%DATADIR%%/ipam/migrations/0066_iprange_mark_utilized.py
 %%DATADIR%%/ipam/migrations/0067_ipaddress_index_host.py
+%%DATADIR%%/ipam/migrations/0068_move_l2vpn.py
+%%DATADIR%%/ipam/migrations/0069_gfk_indexes.py
 %%DATADIR%%/ipam/migrations/__init__.py
 %%DATADIR%%/ipam/models/__init__.py
 %%DATADIR%%/ipam/models/asns.py
 %%DATADIR%%/ipam/models/fhrp.py
 %%DATADIR%%/ipam/models/ip.py
-%%DATADIR%%/ipam/models/l2vpn.py
 %%DATADIR%%/ipam/models/services.py
 %%DATADIR%%/ipam/models/vlans.py
 %%DATADIR%%/ipam/models/vrfs.py
@@ -704,7 +720,6 @@
 %%DATADIR%%/ipam/tables/asn.py
 %%DATADIR%%/ipam/tables/fhrp.py
 %%DATADIR%%/ipam/tables/ip.py
-%%DATADIR%%/ipam/tables/l2vpn.py
 %%DATADIR%%/ipam/tables/services.py
 %%DATADIR%%/ipam/tables/vlans.py
 %%DATADIR%%/ipam/tables/vrfs.py
@@ -749,10 +764,12 @@
 %%DATADIR%%/netbox/constants.py
 %%DATADIR%%/netbox/context.py
 %%DATADIR%%/netbox/context_processors.py
+%%DATADIR%%/netbox/data_backends.py
 %%DATADIR%%/netbox/denormalized.py
 %%DATADIR%%/netbox/filtersets.py
 %%DATADIR%%/netbox/forms/__init__.py
 %%DATADIR%%/netbox/forms/base.py
+%%DATADIR%%/netbox/forms/mixins.py
 %%DATADIR%%/netbox/graphql/__init__.py
 %%DATADIR%%/netbox/graphql/fields.py
 %%DATADIR%%/netbox/graphql/scalars.py
@@ -765,28 +782,57 @@
 %%DATADIR%%/netbox/models/features.py
 %%DATADIR%%/netbox/navigation/__init__.py
 %%DATADIR%%/netbox/navigation/menu.py
+%%DATADIR%%/netbox/plugins/__init__.py
+%%DATADIR%%/netbox/plugins/navigation.py
+%%DATADIR%%/netbox/plugins/registration.py
+%%DATADIR%%/netbox/plugins/templates.py
+%%DATADIR%%/netbox/plugins/urls.py
+%%DATADIR%%/netbox/plugins/utils.py
+%%DATADIR%%/netbox/plugins/views.py
 %%DATADIR%%/netbox/preferences.py
 %%DATADIR%%/netbox/registry.py
 %%DATADIR%%/netbox/search/__init__.py
 %%DATADIR%%/netbox/search/backends.py
+%%DATADIR%%/netbox/search/utils.py
 %%DATADIR%%/netbox/settings.py
 %%DATADIR%%/netbox/signals.py
 %%DATADIR%%/netbox/staging.py
 %%DATADIR%%/netbox/tables/__init__.py
 %%DATADIR%%/netbox/tables/columns.py
 %%DATADIR%%/netbox/tables/tables.py
+%%DATADIR%%/netbox/tables/template_code.py
 %%DATADIR%%/netbox/tests/__init__.py
+%%DATADIR%%/netbox/tests/dummy_plugin/__init__.py
+%%DATADIR%%/netbox/tests/dummy_plugin/admin.py
+%%DATADIR%%/netbox/tests/dummy_plugin/api/serializers.py
+%%DATADIR%%/netbox/tests/dummy_plugin/api/urls.py
+%%DATADIR%%/netbox/tests/dummy_plugin/api/views.py
+%%DATADIR%%/netbox/tests/dummy_plugin/data_backends.py
+%%DATADIR%%/netbox/tests/dummy_plugin/graphql.py
+%%DATADIR%%/netbox/tests/dummy_plugin/middleware.py
+%%DATADIR%%/netbox/tests/dummy_plugin/migrations/0001_initial.py
+%%DATADIR%%/netbox/tests/dummy_plugin/migrations/__init__.py
+%%DATADIR%%/netbox/tests/dummy_plugin/models.py
+%%DATADIR%%/netbox/tests/dummy_plugin/navigation.py
+%%DATADIR%%/netbox/tests/dummy_plugin/preferences.py
+%%DATADIR%%/netbox/tests/dummy_plugin/search.py
+%%DATADIR%%/netbox/tests/dummy_plugin/tables.py
+%%DATADIR%%/netbox/tests/dummy_plugin/template_content.py
+%%DATADIR%%/netbox/tests/dummy_plugin/urls.py
+%%DATADIR%%/netbox/tests/dummy_plugin/views.py
 %%DATADIR%%/netbox/tests/test_api.py
 %%DATADIR%%/netbox/tests/test_authentication.py
 %%DATADIR%%/netbox/tests/test_config.py
 %%DATADIR%%/netbox/tests/test_graphql.py
 %%DATADIR%%/netbox/tests/test_import.py
+%%DATADIR%%/netbox/tests/test_plugins.py
 %%DATADIR%%/netbox/tests/test_registry.py
 %%DATADIR%%/netbox/tests/test_search.py
 %%DATADIR%%/netbox/tests/test_staging.py
 %%DATADIR%%/netbox/tests/test_tables.py
 %%DATADIR%%/netbox/tests/test_views.py
 %%DATADIR%%/netbox/urls.py
+%%DATADIR%%/netbox/utils.py
 %%DATADIR%%/netbox/views/__init__.py
 %%DATADIR%%/netbox/views/errors.py
 %%DATADIR%%/netbox/views/generic/__init__.py
@@ -927,6 +973,8 @@
 %%DATADIR%%/templates/circuits/provider.html
 %%DATADIR%%/templates/circuits/provideraccount.html
 %%DATADIR%%/templates/circuits/providernetwork.html
+%%DATADIR%%/templates/core/configrevision.html
+%%DATADIR%%/templates/core/configrevision_restore.html
 %%DATADIR%%/templates/core/datafile.html
 %%DATADIR%%/templates/core/datasource.html
 %%DATADIR%%/templates/core/job.html
@@ -1023,8 +1071,6 @@
 %%DATADIR%%/templates/extras/admin/plugins_list.html
 %%DATADIR%%/templates/extras/configcontext.html
 %%DATADIR%%/templates/extras/configcontext_list.html
-%%DATADIR%%/templates/extras/configrevision.html
-%%DATADIR%%/templates/extras/configrevision_restore.html
 %%DATADIR%%/templates/extras/configtemplate.html
 %%DATADIR%%/templates/extras/configtemplate_list.html
 %%DATADIR%%/templates/extras/customfield.html
@@ -1038,6 +1084,7 @@
 %%DATADIR%%/templates/extras/dashboard/widgets/objectcounts.html
 %%DATADIR%%/templates/extras/dashboard/widgets/objectlist.html
 %%DATADIR%%/templates/extras/dashboard/widgets/rssfeed.html
+%%DATADIR%%/templates/extras/eventrule.html
 %%DATADIR%%/templates/extras/exporttemplate.html
 %%DATADIR%%/templates/extras/exporttemplate_list.html
 %%DATADIR%%/templates/extras/htmx/report_result.html
@@ -1126,9 +1173,6 @@
 %%DATADIR%%/templates/ipam/iprange.html
 %%DATADIR%%/templates/ipam/iprange/base.html
 %%DATADIR%%/templates/ipam/iprange/ip_addresses.html
-%%DATADIR%%/templates/ipam/l2vpn.html
-%%DATADIR%%/templates/ipam/l2vpntermination.html
-%%DATADIR%%/templates/ipam/l2vpntermination_edit.html
 %%DATADIR%%/templates/ipam/prefix.html
 %%DATADIR%%/templates/ipam/prefix/base.html
 %%DATADIR%%/templates/ipam/prefix/ip_addresses.html
@@ -1168,12 +1212,25 @@
 %%DATADIR%%/templates/virtualization/cluster_add_devices.html
 %%DATADIR%%/templates/virtualization/clustergroup.html
 %%DATADIR%%/templates/virtualization/clustertype.html
+%%DATADIR%%/templates/virtualization/virtualdisk.html
 %%DATADIR%%/templates/virtualization/virtualmachine.html
 %%DATADIR%%/templates/virtualization/virtualmachine/base.html
 %%DATADIR%%/templates/virtualization/virtualmachine/interfaces.html
 %%DATADIR%%/templates/virtualization/virtualmachine/render_config.html
+%%DATADIR%%/templates/virtualization/virtualmachine/virtual_disks.html
 %%DATADIR%%/templates/virtualization/virtualmachine_list.html
 %%DATADIR%%/templates/virtualization/vminterface.html
+%%DATADIR%%/templates/vpn/ikepolicy.html
+%%DATADIR%%/templates/vpn/ikeproposal.html
+%%DATADIR%%/templates/vpn/ipsecpolicy.html
+%%DATADIR%%/templates/vpn/ipsecprofile.html
+%%DATADIR%%/templates/vpn/ipsecproposal.html
+%%DATADIR%%/templates/vpn/l2vpn.html
+%%DATADIR%%/templates/vpn/l2vpntermination.html
+%%DATADIR%%/templates/vpn/l2vpntermination_edit.html
+%%DATADIR%%/templates/vpn/tunnel.html
+%%DATADIR%%/templates/vpn/tunnelgroup.html
+%%DATADIR%%/templates/vpn/tunneltermination.html
 %%DATADIR%%/templates/wireless/inc/authentication_attrs.html
 %%DATADIR%%/templates/wireless/inc/wirelesslink_interface.html
 %%DATADIR%%/templates/wireless/wirelesslan.html
@@ -1208,6 +1265,8 @@
 %%DATADIR%%/tenancy/migrations/0009_standardize_description_comments.py
 %%DATADIR%%/tenancy/migrations/0010_tenant_relax_uniqueness.py
 %%DATADIR%%/tenancy/migrations/0011_contactassignment_tags.py
+%%DATADIR%%/tenancy/migrations/0012_contactassignment_custom_fields.py
+%%DATADIR%%/tenancy/migrations/0013_gfk_indexes.py
 %%DATADIR%%/tenancy/migrations/__init__.py
 %%DATADIR%%/tenancy/models/__init__.py
 %%DATADIR%%/tenancy/models/contacts.py
@@ -1223,6 +1282,16 @@
 %%DATADIR%%/tenancy/tests/test_views.py
 %%DATADIR%%/tenancy/urls.py
 %%DATADIR%%/tenancy/views.py
+%%DATADIR%%/translations/en/LC_MESSAGES/django.mo
+%%DATADIR%%/translations/en/LC_MESSAGES/django.po
+%%DATADIR%%/translations/es/LC_MESSAGES/django.mo
+%%DATADIR%%/translations/es/LC_MESSAGES/django.po
+%%DATADIR%%/translations/fr/LC_MESSAGES/django.mo
+%%DATADIR%%/translations/fr/LC_MESSAGES/django.po
+%%DATADIR%%/translations/pt/LC_MESSAGES/django.mo
+%%DATADIR%%/translations/pt/LC_MESSAGES/django.po
+%%DATADIR%%/translations/ru/LC_MESSAGES/django.mo
+%%DATADIR%%/translations/ru/LC_MESSAGES/django.po
 %%DATADIR%%/users/__init__.py
 %%DATADIR%%/users/admin.py
 %%DATADIR%%/users/api/__init__.py
@@ -1350,6 +1419,7 @@
 %%DATADIR%%/utilities/templatetags/mptt.py
 %%DATADIR%%/utilities/templatetags/navigation.py
 %%DATADIR%%/utilities/templatetags/perms.py
+%%DATADIR%%/utilities/templatetags/plugins.py
 %%DATADIR%%/utilities/templatetags/tabs.py
 %%DATADIR%%/utilities/testing/__init__.py
 %%DATADIR%%/utilities/testing/api.py
@@ -1406,11 +1476,14 @@
 %%DATADIR%%/virtualization/migrations/0034_standardize_description_comments.py
 %%DATADIR%%/virtualization/migrations/0035_virtualmachine_interface_count.py
 %%DATADIR%%/virtualization/migrations/0036_virtualmachine_config_template.py
+%%DATADIR%%/virtualization/migrations/0037_protect_child_interfaces.py
+%%DATADIR%%/virtualization/migrations/0038_virtualdisk.py
 %%DATADIR%%/virtualization/migrations/__init__.py
 %%DATADIR%%/virtualization/models/__init__.py
 %%DATADIR%%/virtualization/models/clusters.py
 %%DATADIR%%/virtualization/models/virtualmachines.py
 %%DATADIR%%/virtualization/search.py
+%%DATADIR%%/virtualization/signals.py
 %%DATADIR%%/virtualization/tables/__init__.py
 %%DATADIR%%/virtualization/tables/clusters.py
 %%DATADIR%%/virtualization/tables/virtualmachines.py
@@ -1421,6 +1494,45 @@
 %%DATADIR%%/virtualization/tests/test_views.py
 %%DATADIR%%/virtualization/urls.py
 %%DATADIR%%/virtualization/views.py
+%%DATADIR%%/vpn/__init__.py
+%%DATADIR%%/vpn/admin.py
+%%DATADIR%%/vpn/api/__init__.py
+%%DATADIR%%/vpn/api/nested_serializers.py
+%%DATADIR%%/vpn/api/serializers.py
+%%DATADIR%%/vpn/api/urls.py
+%%DATADIR%%/vpn/api/views.py
+%%DATADIR%%/vpn/apps.py
+%%DATADIR%%/vpn/choices.py
+%%DATADIR%%/vpn/constants.py
+%%DATADIR%%/vpn/filtersets.py
+%%DATADIR%%/vpn/forms/__init__.py
+%%DATADIR%%/vpn/forms/bulk_edit.py
+%%DATADIR%%/vpn/forms/bulk_import.py
+%%DATADIR%%/vpn/forms/filtersets.py
+%%DATADIR%%/vpn/forms/model_forms.py
+%%DATADIR%%/vpn/graphql/__init__.py
+%%DATADIR%%/vpn/graphql/gfk_mixins.py
+%%DATADIR%%/vpn/graphql/schema.py
+%%DATADIR%%/vpn/graphql/types.py
+%%DATADIR%%/vpn/migrations/0001_initial.py
+%%DATADIR%%/vpn/migrations/0002_move_l2vpn.py
+%%DATADIR%%/vpn/migrations/__init__.py
+%%DATADIR%%/vpn/models/__init__.py
+%%DATADIR%%/vpn/models/crypto.py
+%%DATADIR%%/vpn/models/l2vpn.py
+%%DATADIR%%/vpn/models/tunnels.py
+%%DATADIR%%/vpn/search.py
+%%DATADIR%%/vpn/tables/__init__.py
+%%DATADIR%%/vpn/tables/crypto.py
+%%DATADIR%%/vpn/tables/l2vpn.py
+%%DATADIR%%/vpn/tables/tunnels.py
+%%DATADIR%%/vpn/tests/__init__.py
+%%DATADIR%%/vpn/tests/test_api.py
+%%DATADIR%%/vpn/tests/test_filtersets.py
+%%DATADIR%%/vpn/tests/test_models.py
+%%DATADIR%%/vpn/tests/test_views.py
+%%DATADIR%%/vpn/urls.py
+%%DATADIR%%/vpn/views.py
 %%DATADIR%%/wireless/__init__.py
 %%DATADIR%%/wireless/api/__init__.py
 %%DATADIR%%/wireless/api/nested_serializers.py