From 6f5c2f1e2973e75e7c8772e1bddbcd703a6b8fd4 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 11 May 2022 14:13:50 -0400 Subject: [PATCH 01/12] Enable & document Sentry integration --- docs/administration/error-reporting.md | 27 ++++++++++++++++++++ docs/configuration/optional-settings.md | 33 +++++++++++++++++++++++++ docs/release-notes/version-3.2.md | 1 + mkdocs.yml | 1 + netbox/netbox/settings.py | 25 +++++++++++++++++++ 5 files changed, 87 insertions(+) create mode 100644 docs/administration/error-reporting.md diff --git a/docs/administration/error-reporting.md b/docs/administration/error-reporting.md new file mode 100644 index 000000000..b2977bf39 --- /dev/null +++ b/docs/administration/error-reporting.md @@ -0,0 +1,27 @@ +# Error Reporting + +## Sentry + +NetBox v3.2.3 and later support native integration with [Sentry](https://sentry.io/) for automatic error reporting. To enable this feature, begin by creating a new project in Sentry to represent your NetBox deployment and obtain its corresponding data source name (DSN). This looks like a URL similar to the example below: + +``` +https://examplePublicKey@o0.ingest.sentry.io/0 +``` + +Once you have obtained a DSN, configure Sentry in NetBox's `configuration.py` file with the following parameters: + +```python +SENTRY_ENABLED = True +SENTRY_DSN = "https://YourDSNgoesHere@o0.ingest.sentry.io/0" +``` + +You can optionally attach one or more arbitrary tags to the outgoing error reports if desired by setting the `SENTRY_TAGS` parameter: + +```python +SENTRY_TAGS = { + "custom.foo": "123", + "custom.bar": "abc", +} +``` + +Once the configuration has been saved, restart the NetBox service. diff --git a/docs/configuration/optional-settings.md b/docs/configuration/optional-settings.md index 76fd0a12c..4a2d62e91 100644 --- a/docs/configuration/optional-settings.md +++ b/docs/configuration/optional-settings.md @@ -404,6 +404,39 @@ The file path to the location where [custom scripts](../customization/custom-scr --- +## SENTRY_DSN + +Default: None + +Defines a Sentry data source name (DSN) for automated error reporting. `SENTRY_ENABLED` must be True for this parameter to take effect. For example: + +``` +SENTRY_DSN = "https://examplePublicKey@o0.ingest.sentry.io/0" +``` + +--- + +## SENTRY_ENABLED + +Default: False + +Set to True to enable automatic error reporting via [Sentry](https://sentry.io/). Requires `SENTRY_DSN` to be defined. + +--- + +## SENTRY_TAGS + +An optional dictionary of tags to apply to Sentry error reports. `SENTRY_ENABLED` must be True for this parameter to take effect. For example: + +``` +SENTRY_TAGS = { + "custom.foo": "123", + "custom.bar": "abc", +} +``` + +--- + ## SESSION_COOKIE_NAME Default: `sessionid` diff --git a/docs/release-notes/version-3.2.md b/docs/release-notes/version-3.2.md index 6eadb3d9e..bfd432741 100644 --- a/docs/release-notes/version-3.2.md +++ b/docs/release-notes/version-3.2.md @@ -11,6 +11,7 @@ * [#9278](https://github.com/netbox-community/netbox/issues/9278) - Linkify device types count under manufacturers list * [#9280](https://github.com/netbox-community/netbox/issues/9280) - Allow adopting existing components when installing a module * [#9314](https://github.com/netbox-community/netbox/issues/9314) - Add device and VM filters for FHRP group assignments +* [#9340](https://github.com/netbox-community/netbox/issues/9340) - Introduce support for error reporting via Sentry ### Bug Fixes diff --git a/mkdocs.yml b/mkdocs.yml index 225c6d4bf..0b7108cd0 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -123,6 +123,7 @@ nav: - Microsoft Azure AD: 'administration/authentication/microsoft-azure-ad.md' - Okta: 'administration/authentication/okta.md' - Permissions: 'administration/permissions.md' + - Error Reporting: 'administration/error-reporting.md' - Housekeeping: 'administration/housekeeping.md' - Replicating NetBox: 'administration/replicating-netbox.md' - NetBox Shell: 'administration/netbox-shell.md' diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 6dee1081a..e539ecbbe 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -8,9 +8,11 @@ import sys import warnings from urllib.parse import urlsplit +import sentry_sdk from django.contrib.messages import constants as messages from django.core.exceptions import ImproperlyConfigured, ValidationError from django.core.validators import URLValidator +from sentry_sdk.integrations.django import DjangoIntegration from netbox.config import PARAMS @@ -113,6 +115,9 @@ REMOTE_AUTH_GROUP_SEPARATOR = getattr(configuration, 'REMOTE_AUTH_GROUP_SEPARATO REPORTS_ROOT = getattr(configuration, 'REPORTS_ROOT', os.path.join(BASE_DIR, 'reports')).rstrip('/') RQ_DEFAULT_TIMEOUT = getattr(configuration, 'RQ_DEFAULT_TIMEOUT', 300) SCRIPTS_ROOT = getattr(configuration, 'SCRIPTS_ROOT', os.path.join(BASE_DIR, 'scripts')).rstrip('/') +SENTRY_DSN = getattr(configuration, 'SENTRY_DSN', None) +SENTRY_ENABLED = getattr(configuration, 'SENTRY_ENABLED', False) +SENTRY_TAGS = getattr(configuration, 'SENTRY_TAGS', {}) SESSION_FILE_PATH = getattr(configuration, 'SESSION_FILE_PATH', None) SESSION_COOKIE_NAME = getattr(configuration, 'SESSION_COOKIE_NAME', 'sessionid') SHORT_DATE_FORMAT = getattr(configuration, 'SHORT_DATE_FORMAT', 'Y-m-d') @@ -428,6 +433,26 @@ EXEMPT_PATHS = ( ) +# +# Sentry +# + +if SENTRY_ENABLED: + if not SENTRY_DSN: + raise ImproperlyConfigured("SENTRY_ENABLED is True but SENTRY_DSN has not been defined.") + sentry_sdk.init( + dsn=SENTRY_DSN, + release=VERSION, + integrations=[DjangoIntegration()], + traces_sample_rate=1.0, + send_default_pii=True, + http_proxy=HTTP_PROXIES.get('http') if HTTP_PROXIES else None, + https_proxy=HTTP_PROXIES.get('https') if HTTP_PROXIES else None + ) + for k, v in SENTRY_TAGS.items(): + sentry_sdk.set_tag(k, v) + + # # Django social auth # From c14659656474fe46ef06a92b8b99562d3c19ee78 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 11 May 2022 14:27:18 -0400 Subject: [PATCH 02/12] Implement a custom 404 handler to enable Sentry reporting --- docs/administration/error-reporting.md | 2 ++ netbox/netbox/urls.py | 1 + netbox/netbox/views/__init__.py | 14 +++++++++++--- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/docs/administration/error-reporting.md b/docs/administration/error-reporting.md index b2977bf39..8ec83bdf0 100644 --- a/docs/administration/error-reporting.md +++ b/docs/administration/error-reporting.md @@ -25,3 +25,5 @@ SENTRY_TAGS = { ``` Once the configuration has been saved, restart the NetBox service. + +To test Sentry operation, try generating a 404 (page not found) error by navigating to an invalid URL, such as `https://netbox/404-error-testing`. After receiving a 404 response from the NetBox server, you should see the issue appear shortly in Sentry. diff --git a/netbox/netbox/urls.py b/netbox/netbox/urls.py index e76efe0fe..e8ee4b7b6 100644 --- a/netbox/netbox/urls.py +++ b/netbox/netbox/urls.py @@ -100,4 +100,5 @@ urlpatterns = [ path('{}'.format(settings.BASE_PATH), include(_patterns)) ] +handler404 = 'netbox.views.handler_404' handler500 = 'netbox.views.server_error' diff --git a/netbox/netbox/views/__init__.py b/netbox/netbox/views/__init__.py index fad347c36..f159ee637 100644 --- a/netbox/netbox/views/__init__.py +++ b/netbox/netbox/views/__init__.py @@ -2,7 +2,6 @@ import platform import sys from django.conf import settings -from django.contrib.contenttypes.models import ContentType from django.core.cache import cache from django.db.models import F from django.http import HttpResponseServerError @@ -11,9 +10,10 @@ from django.template import loader from django.template.exceptions import TemplateDoesNotExist from django.urls import reverse from django.views.decorators.csrf import requires_csrf_token -from django.views.defaults import ERROR_500_TEMPLATE_NAME +from django.views.defaults import ERROR_500_TEMPLATE_NAME, page_not_found from django.views.generic import View from packaging import version +from sentry_sdk import capture_message from circuits.models import Circuit, Provider from dcim.models import ( @@ -190,13 +190,21 @@ class StaticMediaFailureView(View): """ Display a user-friendly error message with troubleshooting tips when a static media file fails to load. """ - def get(self, request): return render(request, 'media_failure.html', { 'filename': request.GET.get('filename') }) +def handler_404(request, exception): + """ + Wrap Django's default 404 handler to enable Sentry reporting. + """ + capture_message("Page not found", level="error") + + return page_not_found(request, exception) + + @requires_csrf_token def server_error(request, template_name=ERROR_500_TEMPLATE_NAME): """ From 312d6c890e64b6d2d4699916ff8c53cb72147337 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 11 May 2022 15:20:18 -0400 Subject: [PATCH 03/12] Add sentry-sdk as a dependency --- base_requirements.txt | 4 ++++ requirements.txt | 1 + 2 files changed, 5 insertions(+) diff --git a/base_requirements.txt b/base_requirements.txt index 095906914..6bb537a6a 100644 --- a/base_requirements.txt +++ b/base_requirements.txt @@ -102,6 +102,10 @@ psycopg2-binary # https://github.com/yaml/pyyaml PyYAML +# Sentry SDK +# https://github.com/getsentry/sentry-python +sentry-sdk + # Social authentication framework # https://github.com/python-social-auth/social-core social-auth-core diff --git a/requirements.txt b/requirements.txt index 32c13d455..1e40f0b3f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -24,6 +24,7 @@ netaddr==0.8.0 Pillow==9.1.0 psycopg2-binary==2.9.3 PyYAML==6.0 +sentry-sdk==1.5.12 social-auth-app-django==5.0.0 social-auth-core==4.2.0 svgwrite==1.4.2 From 991950650b22141d9e6bca28c53cedcf877a7c2f Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 11 May 2022 16:44:26 -0400 Subject: [PATCH 04/12] Add Sentry as a sponsor --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index d75c2c1a5..60f007946 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,8 @@ The complete documentation for NetBox can be found at [docs.netbox.dev](https://            [![NS1](https://raw.githubusercontent.com/wiki/netbox-community/netbox/images/sponsors/ns1.png)](https://ns1.com/)
+ [![Sentry](https://raw.githubusercontent.com/wiki/netbox-community/netbox/images/sponsors/sentry.png)](https://sentry.io/) +            [![Stellar Technologies](https://raw.githubusercontent.com/wiki/netbox-community/netbox/images/sponsors/stellar.png)](https://stellar.tech/) From 4cefe26f80488016247ca79978e0ece8f582ef60 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Thu, 12 May 2022 09:35:13 -0400 Subject: [PATCH 05/12] #9340: Add default Sentry DSN --- docs/administration/error-reporting.md | 23 ++++++++++++++++++++--- docs/configuration/optional-settings.md | 5 ++++- netbox/netbox/settings.py | 10 +++++++++- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/docs/administration/error-reporting.md b/docs/administration/error-reporting.md index 8ec83bdf0..e04372338 100644 --- a/docs/administration/error-reporting.md +++ b/docs/administration/error-reporting.md @@ -2,7 +2,17 @@ ## Sentry -NetBox v3.2.3 and later support native integration with [Sentry](https://sentry.io/) for automatic error reporting. To enable this feature, begin by creating a new project in Sentry to represent your NetBox deployment and obtain its corresponding data source name (DSN). This looks like a URL similar to the example below: +### Enabling Error Reporting + +NetBox v3.2.3 and later support native integration with [Sentry](https://sentry.io/) for automatic error reporting. To enable this functionality, simply set `SENTRY_ENABLED` to True in `configuration.py`. Errors will be sent to a Sentry ingestor maintained by the NetBox team for analysis. + +```python +SENTRY_ENABLED = True +``` + +### Using a Custom DSN + +If you prefer instead to use your own Sentry ingestor, you'll need to first create a new project under your Sentry account to represent your NetBox deployment and obtain its corresponding data source name (DSN). This looks like a URL similar to the example below: ``` https://examplePublicKey@o0.ingest.sentry.io/0 @@ -12,9 +22,11 @@ Once you have obtained a DSN, configure Sentry in NetBox's `configuration.py` fi ```python SENTRY_ENABLED = True -SENTRY_DSN = "https://YourDSNgoesHere@o0.ingest.sentry.io/0" +SENTRY_DSN = "https://examplePublicKey@o0.ingest.sentry.io/0" ``` +### Assigning Tags + You can optionally attach one or more arbitrary tags to the outgoing error reports if desired by setting the `SENTRY_TAGS` parameter: ```python @@ -24,6 +36,11 @@ SENTRY_TAGS = { } ``` +!!! warning "Reserved tag prefixes" + Avoid using any tag names which begin with `netbox.`, as this prefix is reserved by the NetBox application. + +### Testing + Once the configuration has been saved, restart the NetBox service. -To test Sentry operation, try generating a 404 (page not found) error by navigating to an invalid URL, such as `https://netbox/404-error-testing`. After receiving a 404 response from the NetBox server, you should see the issue appear shortly in Sentry. +To test Sentry operation, try generating a 404 (page not found) error by navigating to an invalid URL, such as `https://netbox/404-error-testing`. (Be sure that debug mode has been disabled.) After receiving a 404 response from the NetBox server, you should see the issue appear shortly in Sentry. diff --git a/docs/configuration/optional-settings.md b/docs/configuration/optional-settings.md index 4a2d62e91..58f8cb526 100644 --- a/docs/configuration/optional-settings.md +++ b/docs/configuration/optional-settings.md @@ -426,7 +426,7 @@ Set to True to enable automatic error reporting via [Sentry](https://sentry.io/) ## SENTRY_TAGS -An optional dictionary of tags to apply to Sentry error reports. `SENTRY_ENABLED` must be True for this parameter to take effect. For example: +An optional dictionary of tag names and values to apply to Sentry error reports. `SENTRY_ENABLED` must be True for this parameter to take effect. For example: ``` SENTRY_TAGS = { @@ -435,6 +435,9 @@ SENTRY_TAGS = { } ``` +!!! warning "Reserved tag prefixes" + Avoid using any tag names which begin with `netbox.`, as this prefix is reserved by the NetBox application. + --- ## SESSION_COOKIE_NAME diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index e539ecbbe..2dfbf9be6 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -1,3 +1,4 @@ +import hashlib import importlib import logging import os @@ -42,6 +43,7 @@ if sys.version_info < (3, 8): f"NetBox requires Python 3.8 or later. (Currently installed: Python {platform.python_version()})" ) +DEFAULT_SENTRY_DSN = 'https://198cf560b29d4054ab8e583a1d10ea58@o1242133.ingest.sentry.io/6396485' # # Configuration import @@ -115,7 +117,7 @@ REMOTE_AUTH_GROUP_SEPARATOR = getattr(configuration, 'REMOTE_AUTH_GROUP_SEPARATO REPORTS_ROOT = getattr(configuration, 'REPORTS_ROOT', os.path.join(BASE_DIR, 'reports')).rstrip('/') RQ_DEFAULT_TIMEOUT = getattr(configuration, 'RQ_DEFAULT_TIMEOUT', 300) SCRIPTS_ROOT = getattr(configuration, 'SCRIPTS_ROOT', os.path.join(BASE_DIR, 'scripts')).rstrip('/') -SENTRY_DSN = getattr(configuration, 'SENTRY_DSN', None) +SENTRY_DSN = getattr(configuration, 'SENTRY_DSN', DEFAULT_SENTRY_DSN) SENTRY_ENABLED = getattr(configuration, 'SENTRY_ENABLED', False) SENTRY_TAGS = getattr(configuration, 'SENTRY_TAGS', {}) SESSION_FILE_PATH = getattr(configuration, 'SESSION_FILE_PATH', None) @@ -451,6 +453,12 @@ if SENTRY_ENABLED: ) for k, v in SENTRY_TAGS.items(): sentry_sdk.set_tag(k, v) + # If using the default DSN, append a unique deployment ID tag for error correlation + if SENTRY_DSN == DEFAULT_SENTRY_DSN: + sentry_sdk.set_tag( + 'netbox.deployment_id', + hashlib.sha256(SECRET_KEY.encode('utf-8')).hexdigest()[:16] + ) # From 72b2ab03cc11abcf97984f3f0eac027b618066e2 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Thu, 12 May 2022 10:00:57 -0400 Subject: [PATCH 06/12] #9340: Introduce config parameters for Sentry sampling rates --- docs/configuration/error-reporting.md | 54 +++++++++++++++++++++++++ docs/configuration/optional-settings.md | 36 ----------------- mkdocs.yml | 1 + netbox/netbox/settings.py | 19 ++++++--- 4 files changed, 69 insertions(+), 41 deletions(-) create mode 100644 docs/configuration/error-reporting.md diff --git a/docs/configuration/error-reporting.md b/docs/configuration/error-reporting.md new file mode 100644 index 000000000..d1c47e2fb --- /dev/null +++ b/docs/configuration/error-reporting.md @@ -0,0 +1,54 @@ +# Error Reporting Settings + +## SENTRY_DSN + +Default: None + +Defines a Sentry data source name (DSN) for automated error reporting. `SENTRY_ENABLED` must be True for this parameter to take effect. For example: + +``` +SENTRY_DSN = "https://examplePublicKey@o0.ingest.sentry.io/0" +``` + +--- + +## SENTRY_ENABLED + +Default: False + +Set to True to enable automatic error reporting via [Sentry](https://sentry.io/). + +--- + +## SENTRY_SAMPLE_RATE + +Default: 1.0 (all) + +The sampling rate for errors. Must be a value between 0 (disabled) and 1.0 (report on all errors). + +--- + +## SENTRY_TAGS + +An optional dictionary of tag names and values to apply to Sentry error reports.For example: + +``` +SENTRY_TAGS = { + "custom.foo": "123", + "custom.bar": "abc", +} +``` + +!!! warning "Reserved tag prefixes" + Avoid using any tag names which begin with `netbox.`, as this prefix is reserved by the NetBox application. + +--- + +## SENTRY_TRACES_SAMPLE_RATE + +Default: 0 (disabled) + +The sampling rate for transactions. Must be a value between 0 (disabled) and 1.0 (report on all transactions). + +!!! warning "Consider performance implications" + A high sampling rate for transactions can induce significant performance penalties. If transaction reporting is desired, it is recommended to use a relatively low sample rate of 10% to 20% (0.1 to 0.2). diff --git a/docs/configuration/optional-settings.md b/docs/configuration/optional-settings.md index 58f8cb526..76fd0a12c 100644 --- a/docs/configuration/optional-settings.md +++ b/docs/configuration/optional-settings.md @@ -404,42 +404,6 @@ The file path to the location where [custom scripts](../customization/custom-scr --- -## SENTRY_DSN - -Default: None - -Defines a Sentry data source name (DSN) for automated error reporting. `SENTRY_ENABLED` must be True for this parameter to take effect. For example: - -``` -SENTRY_DSN = "https://examplePublicKey@o0.ingest.sentry.io/0" -``` - ---- - -## SENTRY_ENABLED - -Default: False - -Set to True to enable automatic error reporting via [Sentry](https://sentry.io/). Requires `SENTRY_DSN` to be defined. - ---- - -## SENTRY_TAGS - -An optional dictionary of tag names and values to apply to Sentry error reports. `SENTRY_ENABLED` must be True for this parameter to take effect. For example: - -``` -SENTRY_TAGS = { - "custom.foo": "123", - "custom.bar": "abc", -} -``` - -!!! warning "Reserved tag prefixes" - Avoid using any tag names which begin with `netbox.`, as this prefix is reserved by the NetBox application. - ---- - ## SESSION_COOKIE_NAME Default: `sessionid` diff --git a/mkdocs.yml b/mkdocs.yml index 0b7108cd0..5c973e0d6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -73,6 +73,7 @@ nav: - Required Settings: 'configuration/required-settings.md' - Optional Settings: 'configuration/optional-settings.md' - Dynamic Settings: 'configuration/dynamic-settings.md' + - Error Reporting: 'configuration/error-reporting.md' - Remote Authentication: 'configuration/remote-authentication.md' - Core Functionality: - IP Address Management: 'core-functionality/ipam.md' diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 2dfbf9be6..fafcf35a1 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -72,6 +72,9 @@ DATABASE = getattr(configuration, 'DATABASE') REDIS = getattr(configuration, 'REDIS') SECRET_KEY = getattr(configuration, 'SECRET_KEY') +# Calculate a unique deployment ID from the secret key +DEPLOYMENT_ID = hashlib.sha256(SECRET_KEY.encode('utf-8')).hexdigest()[:16] + # Set static config parameters ADMINS = getattr(configuration, 'ADMINS', []) AUTH_PASSWORD_VALIDATORS = getattr(configuration, 'AUTH_PASSWORD_VALIDATORS', []) @@ -119,6 +122,8 @@ RQ_DEFAULT_TIMEOUT = getattr(configuration, 'RQ_DEFAULT_TIMEOUT', 300) SCRIPTS_ROOT = getattr(configuration, 'SCRIPTS_ROOT', os.path.join(BASE_DIR, 'scripts')).rstrip('/') SENTRY_DSN = getattr(configuration, 'SENTRY_DSN', DEFAULT_SENTRY_DSN) SENTRY_ENABLED = getattr(configuration, 'SENTRY_ENABLED', False) +SENTRY_SAMPLE_RATE = getattr(configuration, 'SENTRY_SAMPLE_RATE', 1.0) +SENTRY_TRACES_SAMPLE_RATE = getattr(configuration, 'SENTRY_TRACES_SAMPLE_RATE', 0) SENTRY_TAGS = getattr(configuration, 'SENTRY_TAGS', {}) SESSION_FILE_PATH = getattr(configuration, 'SESSION_FILE_PATH', None) SESSION_COOKIE_NAME = getattr(configuration, 'SESSION_COOKIE_NAME', 'sessionid') @@ -442,23 +447,27 @@ EXEMPT_PATHS = ( if SENTRY_ENABLED: if not SENTRY_DSN: raise ImproperlyConfigured("SENTRY_ENABLED is True but SENTRY_DSN has not been defined.") + # If using the default DSN, force sampling rates + if SENTRY_DSN == DEFAULT_SENTRY_DSN: + SENTRY_SAMPLE_RATE = 1.0 + SENTRY_TRACES_SAMPLE_RATE = 0 + # Initialize the SDK sentry_sdk.init( dsn=SENTRY_DSN, release=VERSION, integrations=[DjangoIntegration()], - traces_sample_rate=1.0, + sample_rate=SENTRY_SAMPLE_RATE, + traces_sample_rate=SENTRY_TRACES_SAMPLE_RATE, send_default_pii=True, http_proxy=HTTP_PROXIES.get('http') if HTTP_PROXIES else None, https_proxy=HTTP_PROXIES.get('https') if HTTP_PROXIES else None ) + # Assign any configured tags for k, v in SENTRY_TAGS.items(): sentry_sdk.set_tag(k, v) # If using the default DSN, append a unique deployment ID tag for error correlation if SENTRY_DSN == DEFAULT_SENTRY_DSN: - sentry_sdk.set_tag( - 'netbox.deployment_id', - hashlib.sha256(SECRET_KEY.encode('utf-8')).hexdigest()[:16] - ) + sentry_sdk.set_tag('netbox.deployment_id', DEPLOYMENT_ID) # From c4c93ee34649140e9793fc4869ceea9ad7a47010 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Thu, 12 May 2022 10:17:29 -0400 Subject: [PATCH 07/12] Closes #9343: Add Ubiquiti SmartPower power outlet type --- docs/release-notes/version-3.2.md | 1 + netbox/dcim/choices.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/docs/release-notes/version-3.2.md b/docs/release-notes/version-3.2.md index bfd432741..d3010d215 100644 --- a/docs/release-notes/version-3.2.md +++ b/docs/release-notes/version-3.2.md @@ -12,6 +12,7 @@ * [#9280](https://github.com/netbox-community/netbox/issues/9280) - Allow adopting existing components when installing a module * [#9314](https://github.com/netbox-community/netbox/issues/9314) - Add device and VM filters for FHRP group assignments * [#9340](https://github.com/netbox-community/netbox/issues/9340) - Introduce support for error reporting via Sentry +* [#9343](https://github.com/netbox-community/netbox/issues/9343) - Add Ubiquiti SmartPower power outlet type ### Bug Fixes diff --git a/netbox/dcim/choices.py b/netbox/dcim/choices.py index e369201b4..5bc53bf88 100644 --- a/netbox/dcim/choices.py +++ b/netbox/dcim/choices.py @@ -575,6 +575,7 @@ class PowerOutletTypeChoices(ChoiceSet): TYPE_NEUTRIK_POWERCON_32A = 'neutrik-powercon-32a' TYPE_NEUTRIK_POWERCON_TRUE1 = 'neutrik-powercon-true1' TYPE_NEUTRIK_POWERCON_TRUE1_TOP = 'neutrik-powercon-true1-top' + TYPE_UBIQUITI_SMARTPOWER = 'ubiquiti-smartpower' # Other TYPE_HARDWIRED = 'hardwired' @@ -683,6 +684,7 @@ class PowerOutletTypeChoices(ChoiceSet): (TYPE_NEUTRIK_POWERCON_32A, 'Neutrik powerCON (32A)'), (TYPE_NEUTRIK_POWERCON_TRUE1, 'Neutrik powerCON TRUE1'), (TYPE_NEUTRIK_POWERCON_TRUE1_TOP, 'Neutrik powerCON TRUE1 TOP'), + (TYPE_UBIQUITI_SMARTPOWER, 'Ubiquiti SmartPower'), )), ('Other', ( (TYPE_HARDWIRED, 'Hardwired'), From 37903776fd7e2af4f3029ba43760e76d76c25939 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Thu, 12 May 2022 10:41:29 -0400 Subject: [PATCH 08/12] Fixes #9296: Improve Markdown link sanitization --- docs/release-notes/version-3.2.md | 1 + netbox/utilities/templatetags/builtins/filters.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/release-notes/version-3.2.md b/docs/release-notes/version-3.2.md index d3010d215..cc5c41f9c 100644 --- a/docs/release-notes/version-3.2.md +++ b/docs/release-notes/version-3.2.md @@ -18,6 +18,7 @@ * [#9190](https://github.com/netbox-community/netbox/issues/9190) - Prevent exception when attempting to instantiate module components which already exist on the parent device * [#9267](https://github.com/netbox-community/netbox/issues/9267) - Remove invalid entry in IP address role choices +* [#9296](https://github.com/netbox-community/netbox/issues/9296) - Improve Markdown link sanitization * [#9306](https://github.com/netbox-community/netbox/issues/9306) - Include VC master interfaces when selecting a LAG/bridge for a VC member interface * [#9311](https://github.com/netbox-community/netbox/issues/9311) - Permit creating contact assignment without a priority via the REST API * [#9313](https://github.com/netbox-community/netbox/issues/9313) - Remove HTML code from CSV output of many-to-many relationships diff --git a/netbox/utilities/templatetags/builtins/filters.py b/netbox/utilities/templatetags/builtins/filters.py index 4a3db0a3c..1c1258d5c 100644 --- a/netbox/utilities/templatetags/builtins/filters.py +++ b/netbox/utilities/templatetags/builtins/filters.py @@ -150,11 +150,11 @@ def render_markdown(value): value = strip_tags(value) # Sanitize Markdown links - pattern = fr'\[([^\]]+)\]\((?!({schemes})).*:(.+)\)' + pattern = fr'\[([^\]]+)\]\(\s*(?!({schemes})).*:(.+)\)' value = re.sub(pattern, '[\\1](\\3)', value, flags=re.IGNORECASE) # Sanitize Markdown reference links - pattern = fr'\[(.+)\]:\s*(?!({schemes}))\w*:(.+)' + pattern = fr'\[([^\]]+)\]:\s*(?!({schemes}))\w*:(.+)' value = re.sub(pattern, '[\\1]: \\3', value, flags=re.IGNORECASE) # Render Markdown From ad12ad4a773f1aca74b14f75f9ce5d870db42d13 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Thu, 12 May 2022 11:05:34 -0400 Subject: [PATCH 09/12] Closes #9221: Add definition list support for Markdown --- docs/release-notes/version-3.2.md | 1 + netbox/utilities/templatetags/builtins/filters.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-3.2.md b/docs/release-notes/version-3.2.md index cc5c41f9c..8297ab1e0 100644 --- a/docs/release-notes/version-3.2.md +++ b/docs/release-notes/version-3.2.md @@ -7,6 +7,7 @@ * [#8894](https://github.com/netbox-community/netbox/issues/8894) - Include full names when listing users * [#8998](https://github.com/netbox-community/netbox/issues/8998) - Enable filtering racks & reservations by site group * [#9122](https://github.com/netbox-community/netbox/issues/9122) - Introduce `clearcache` management command & clear cache during upgrade +* [#9221](https://github.com/netbox-community/netbox/issues/9221) - Add definition list support for Markdown * [#9260](https://github.com/netbox-community/netbox/issues/9260) - Apply user preferences to tables under object detail views * [#9278](https://github.com/netbox-community/netbox/issues/9278) - Linkify device types count under manufacturers list * [#9280](https://github.com/netbox-community/netbox/issues/9280) - Allow adopting existing components when installing a module diff --git a/netbox/utilities/templatetags/builtins/filters.py b/netbox/utilities/templatetags/builtins/filters.py index 1c1258d5c..44ad5ac47 100644 --- a/netbox/utilities/templatetags/builtins/filters.py +++ b/netbox/utilities/templatetags/builtins/filters.py @@ -158,7 +158,7 @@ def render_markdown(value): value = re.sub(pattern, '[\\1]: \\3', value, flags=re.IGNORECASE) # Render Markdown - html = markdown(value, extensions=['fenced_code', 'tables', StrikethroughExtension()]) + html = markdown(value, extensions=['def_list', 'fenced_code', 'tables', StrikethroughExtension()]) # If the string is not empty wrap it in rendered-markdown to style tables if html: From 5f3695d2d06f2bc04e1404a2bab8b8bea386c889 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Thu, 12 May 2022 12:18:58 -0400 Subject: [PATCH 10/12] Closes #8805: Add "mixed" option for device airflow indication --- docs/release-notes/version-3.2.md | 1 + netbox/dcim/choices.py | 2 ++ 2 files changed, 3 insertions(+) diff --git a/docs/release-notes/version-3.2.md b/docs/release-notes/version-3.2.md index 8297ab1e0..17918601a 100644 --- a/docs/release-notes/version-3.2.md +++ b/docs/release-notes/version-3.2.md @@ -4,6 +4,7 @@ ### Enhancements +* [#8805](https://github.com/netbox-community/netbox/issues/8805) - Add "mixed" option for device airflow indication * [#8894](https://github.com/netbox-community/netbox/issues/8894) - Include full names when listing users * [#8998](https://github.com/netbox-community/netbox/issues/8998) - Enable filtering racks & reservations by site group * [#9122](https://github.com/netbox-community/netbox/issues/9122) - Introduce `clearcache` management command & clear cache during upgrade diff --git a/netbox/dcim/choices.py b/netbox/dcim/choices.py index 5bc53bf88..a89960457 100644 --- a/netbox/dcim/choices.py +++ b/netbox/dcim/choices.py @@ -159,6 +159,7 @@ class DeviceAirflowChoices(ChoiceSet): AIRFLOW_RIGHT_TO_LEFT = 'right-to-left' AIRFLOW_SIDE_TO_REAR = 'side-to-rear' AIRFLOW_PASSIVE = 'passive' + AIRFLOW_MIXED = 'mixed' CHOICES = ( (AIRFLOW_FRONT_TO_REAR, 'Front to rear'), @@ -167,6 +168,7 @@ class DeviceAirflowChoices(ChoiceSet): (AIRFLOW_RIGHT_TO_LEFT, 'Right to left'), (AIRFLOW_SIDE_TO_REAR, 'Side to rear'), (AIRFLOW_PASSIVE, 'Passive'), + (AIRFLOW_MIXED, 'Mixed'), ) From a6aec9ebac82478c630c170af90b1838112b36a4 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Thu, 12 May 2022 13:53:26 -0400 Subject: [PATCH 11/12] Release v3.2.3 --- .github/ISSUE_TEMPLATE/bug_report.yaml | 2 +- .github/ISSUE_TEMPLATE/feature_request.yaml | 2 +- docs/release-notes/version-3.2.md | 2 +- netbox/netbox/settings.py | 2 +- requirements.txt | 6 +++--- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 2d6ca5700..df5ac6e81 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -14,7 +14,7 @@ body: attributes: label: NetBox version description: What version of NetBox are you currently running? - placeholder: v3.2.2 + placeholder: v3.2.3 validations: required: true - type: dropdown diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml index 13b162741..422b87f52 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yaml +++ b/.github/ISSUE_TEMPLATE/feature_request.yaml @@ -14,7 +14,7 @@ body: attributes: label: NetBox version description: What version of NetBox are you currently running? - placeholder: v3.2.2 + placeholder: v3.2.3 validations: required: true - type: dropdown diff --git a/docs/release-notes/version-3.2.md b/docs/release-notes/version-3.2.md index 17918601a..0c56c92f7 100644 --- a/docs/release-notes/version-3.2.md +++ b/docs/release-notes/version-3.2.md @@ -1,6 +1,6 @@ # NetBox v3.2 -## v3.2.3 (FUTURE) +## v3.2.3 (2022-05-12) ### Enhancements diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index fafcf35a1..999e39479 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -29,7 +29,7 @@ django.utils.encoding.force_text = force_str # Environment setup # -VERSION = '3.2.3-dev' +VERSION = '3.2.3' # Hostname HOSTNAME = platform.node() diff --git a/requirements.txt b/requirements.txt index 1e40f0b3f..0a15fcf20 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ Django==4.0.4 -django-cors-headers==3.11.0 +django-cors-headers==3.12.0 django-debug-toolbar==3.2.4 django-filter==21.1 django-graphiql-debug-toolbar==0.2.0 @@ -16,9 +16,9 @@ drf-yasg[validation]==1.20.0 graphene-django==2.15.0 gunicorn==20.1.0 Jinja2==3.1.2 -Markdown==3.3.6 +Markdown==3.3.7 markdown-include==0.6.0 -mkdocs-material==8.2.11 +mkdocs-material==8.2.14 mkdocstrings[python-legacy]==0.18.1 netaddr==0.8.0 Pillow==9.1.0 From 3c7c8c8776e35d82706420bab9f1a93f1c528913 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Thu, 12 May 2022 14:14:40 -0400 Subject: [PATCH 12/12] PRVB --- docs/release-notes/version-3.2.md | 4 ++++ netbox/netbox/settings.py | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/release-notes/version-3.2.md b/docs/release-notes/version-3.2.md index 0c56c92f7..408d572c7 100644 --- a/docs/release-notes/version-3.2.md +++ b/docs/release-notes/version-3.2.md @@ -1,5 +1,9 @@ # NetBox v3.2 +## v3.2.4 (FUTURE) + +--- + ## v3.2.3 (2022-05-12) ### Enhancements diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 999e39479..59306b8fa 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -29,7 +29,7 @@ django.utils.encoding.force_text = force_str # Environment setup # -VERSION = '3.2.3' +VERSION = '3.2.4-dev' # Hostname HOSTNAME = platform.node()