mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-09 00:58:16 -06:00
Merge branch 'develop' into 16423-inconsistency_swagger_schema_vs_api
This commit is contained in:
commit
70d0f96c14
2
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
2
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@ -26,7 +26,7 @@ body:
|
||||
attributes:
|
||||
label: NetBox Version
|
||||
description: What version of NetBox are you currently running?
|
||||
placeholder: v4.0.3
|
||||
placeholder: v4.0.5
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
|
2
.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
2
.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
@ -14,7 +14,7 @@ body:
|
||||
attributes:
|
||||
label: NetBox version
|
||||
description: What version of NetBox are you currently running?
|
||||
placeholder: v4.0.3
|
||||
placeholder: v4.0.5
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
|
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -5,10 +5,12 @@ on:
|
||||
paths-ignore:
|
||||
- 'contrib/**'
|
||||
- 'docs/**'
|
||||
- 'netbox/translations/**'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'contrib/**'
|
||||
- 'docs/**'
|
||||
- 'netbox/translations/**'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
@ -8,7 +8,9 @@ django-cors-headers
|
||||
|
||||
# Runtime UI tool for debugging Django
|
||||
# https://github.com/jazzband/django-debug-toolbar/blob/main/docs/changes.rst
|
||||
django-debug-toolbar
|
||||
# Pinned for DNS looukp bug; see https://github.com/netbox-community/netbox/issues/16454
|
||||
# and https://github.com/jazzband/django-debug-toolbar/issues/1927
|
||||
django-debug-toolbar==4.3.0
|
||||
|
||||
# Library for writing reusable URL query filters
|
||||
# https://github.com/carltongibson/django-filter/blob/main/CHANGES.rst
|
||||
|
@ -323,6 +323,7 @@
|
||||
"100base-tx",
|
||||
"100base-t1",
|
||||
"1000base-t",
|
||||
"1000base-tx",
|
||||
"2.5gbase-t",
|
||||
"5gbase-t",
|
||||
"10gbase-t",
|
||||
|
@ -1,18 +1,34 @@
|
||||
# NetBox v4.0
|
||||
|
||||
## v4.0.4 (FUTURE)
|
||||
## v4.0.6 (FUTURE)
|
||||
|
||||
---
|
||||
|
||||
## v4.0.5 (2024-06-06)
|
||||
|
||||
### Enhancements
|
||||
|
||||
* [#14810](https://github.com/netbox-community/netbox/issues/14810) - Enable contact assignment for services
|
||||
* [#15489](https://github.com/netbox-community/netbox/issues/15489) - Add 1000Base-TX interface type
|
||||
* [#15873](https://github.com/netbox-community/netbox/issues/15873) - Improve readability of allocates resource numbers for clusters
|
||||
* [#16290](https://github.com/netbox-community/netbox/issues/16290) - Capture entire object in changelog data (but continue to display only non-internal attributes)
|
||||
* [#16353](https://github.com/netbox-community/netbox/issues/16353) - Enable plugins to extend object change view with custom content
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* [#13422](https://github.com/netbox-community/netbox/issues/13422) - Rebuild MPTT trees for applicable models after merging staged changes
|
||||
* [#14567](https://github.com/netbox-community/netbox/issues/14567) - Apply active quicksearch value when exporting "current view" from object list
|
||||
* [#15194](https://github.com/netbox-community/netbox/issues/15194) - Avoid enqueuing duplicate event triggers for a modified object
|
||||
* [#16039](https://github.com/netbox-community/netbox/issues/16039) - Fix row highlighting for front & rear port connections under device view
|
||||
* [#16050](https://github.com/netbox-community/netbox/issues/16050) - Fix display of names & descriptions defined for custom scripts
|
||||
* [#16083](https://github.com/netbox-community/netbox/issues/16083) - Disable font ligatures to avoid peculiarities in rendered text
|
||||
* [#16202](https://github.com/netbox-community/netbox/issues/16202) - Fix site map button URL for certain localizations
|
||||
* [#16261](https://github.com/netbox-community/netbox/issues/16261) - Fix GraphQL filtering for certain multi-value filters
|
||||
* [#16286](https://github.com/netbox-community/netbox/issues/16286) - Fix global search support for provider accounts
|
||||
* [#16312](https://github.com/netbox-community/netbox/issues/16312) - Fix object list navigation for dashboard widgets
|
||||
* [#16315](https://github.com/netbox-community/netbox/issues/16315) - Fix filtering change log & journal entries by object type in UI
|
||||
* [#16376](https://github.com/netbox-community/netbox/issues/16376) - Update change log for the terminating object (e.g. interface) when attaching a cable
|
||||
* [#16400](https://github.com/netbox-community/netbox/issues/16400) - Fix AttributeError when attempting to restore a previous configuration revision after deleting the current one
|
||||
|
||||
---
|
||||
|
||||
|
@ -135,23 +135,23 @@ class ConditionSet:
|
||||
def __init__(self, ruleset):
|
||||
if type(ruleset) is not dict:
|
||||
raise ValueError(_("Ruleset must be a dictionary, not {ruleset}.").format(ruleset=type(ruleset)))
|
||||
if len(ruleset) != 1:
|
||||
raise ValueError(_("Ruleset must have exactly one logical operator (found {ruleset})").format(
|
||||
ruleset=len(ruleset)))
|
||||
|
||||
# Determine the logic type
|
||||
logic = list(ruleset.keys())[0]
|
||||
if type(logic) is not str or logic.lower() not in (AND, OR):
|
||||
raise ValueError(_("Invalid logic type: {logic} (must be '{op_and}' or '{op_or}')").format(
|
||||
logic=logic, op_and=AND, op_or=OR
|
||||
))
|
||||
self.logic = logic.lower()
|
||||
if len(ruleset) == 1:
|
||||
self.logic = (list(ruleset.keys())[0]).lower()
|
||||
if self.logic not in (AND, OR):
|
||||
raise ValueError(_("Invalid logic type: must be 'AND' or 'OR'. Please check documentation."))
|
||||
|
||||
# Compile the set of Conditions
|
||||
self.conditions = [
|
||||
ConditionSet(rule) if is_ruleset(rule) else Condition(**rule)
|
||||
for rule in ruleset[self.logic]
|
||||
]
|
||||
# Compile the set of Conditions
|
||||
self.conditions = [
|
||||
ConditionSet(rule) if is_ruleset(rule) else Condition(**rule)
|
||||
for rule in ruleset[self.logic]
|
||||
]
|
||||
else:
|
||||
try:
|
||||
self.logic = None
|
||||
self.conditions = [Condition(**ruleset)]
|
||||
except TypeError:
|
||||
raise ValueError(_("Incorrect key(s) informed. Please check documentation."))
|
||||
|
||||
def eval(self, data):
|
||||
"""
|
||||
|
@ -1,6 +1,12 @@
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.test import TestCase
|
||||
|
||||
from dcim.choices import SiteStatusChoices
|
||||
from dcim.models import Site
|
||||
from extras.conditions import Condition, ConditionSet
|
||||
from extras.events import serialize_for_event
|
||||
from extras.forms import EventRuleForm
|
||||
from extras.models import EventRule, Webhook
|
||||
|
||||
|
||||
class ConditionTestCase(TestCase):
|
||||
@ -217,3 +223,93 @@ class ConditionSetTest(TestCase):
|
||||
self.assertTrue(cs.eval({'a': 1, 'b': 2, 'c': 9}))
|
||||
self.assertFalse(cs.eval({'a': 9, 'b': 2, 'c': 9}))
|
||||
self.assertFalse(cs.eval({'a': 9, 'b': 9, 'c': 3}))
|
||||
|
||||
def test_event_rule_conditions_without_logic_operator(self):
|
||||
"""
|
||||
Test evaluation of EventRule conditions without logic operator.
|
||||
"""
|
||||
event_rule = EventRule(
|
||||
name='Event Rule 1',
|
||||
type_create=True,
|
||||
type_update=True,
|
||||
conditions={
|
||||
'attr': 'status.value',
|
||||
'value': 'active',
|
||||
}
|
||||
)
|
||||
|
||||
# Create a Site to evaluate - Status = active
|
||||
site = Site.objects.create(name='Site 1', slug='site-1', status=SiteStatusChoices.STATUS_ACTIVE)
|
||||
data = serialize_for_event(site)
|
||||
|
||||
# Evaluate the conditions (status='active')
|
||||
self.assertTrue(event_rule.eval_conditions(data))
|
||||
|
||||
def test_event_rule_conditions_with_logical_operation(self):
|
||||
"""
|
||||
Test evaluation of EventRule conditions without logic operator, but with logical operation (in).
|
||||
"""
|
||||
event_rule = EventRule(
|
||||
name='Event Rule 1',
|
||||
type_create=True,
|
||||
type_update=True,
|
||||
conditions={
|
||||
"attr": "status.value",
|
||||
"value": ["planned", "staging"],
|
||||
"op": "in",
|
||||
}
|
||||
)
|
||||
|
||||
# Create a Site to evaluate - Status = active
|
||||
site = Site.objects.create(name='Site 1', slug='site-1', status=SiteStatusChoices.STATUS_ACTIVE)
|
||||
data = serialize_for_event(site)
|
||||
|
||||
# Evaluate the conditions (status in ['planned, 'staging'])
|
||||
self.assertFalse(event_rule.eval_conditions(data))
|
||||
|
||||
def test_event_rule_conditions_with_logical_operation_and_negate(self):
|
||||
"""
|
||||
Test evaluation of EventRule with logical operation (in) and negate.
|
||||
"""
|
||||
event_rule = EventRule(
|
||||
name='Event Rule 1',
|
||||
type_create=True,
|
||||
type_update=True,
|
||||
conditions={
|
||||
"attr": "status.value",
|
||||
"value": ["planned", "staging"],
|
||||
"op": "in",
|
||||
"negate": True,
|
||||
}
|
||||
)
|
||||
|
||||
# Create a Site to evaluate - Status = active
|
||||
site = Site.objects.create(name='Site 1', slug='site-1', status=SiteStatusChoices.STATUS_ACTIVE)
|
||||
data = serialize_for_event(site)
|
||||
|
||||
# Evaluate the conditions (status NOT in ['planned, 'staging'])
|
||||
self.assertTrue(event_rule.eval_conditions(data))
|
||||
|
||||
def test_event_rule_conditions_with_incorrect_key_must_return_false(self):
|
||||
"""
|
||||
Test Event Rule with incorrect condition (key "foo" is wrong). Must return false.
|
||||
"""
|
||||
|
||||
ct = ContentType.objects.get(app_label='extras', model='webhook')
|
||||
site_ct = ContentType.objects.get_for_model(Site)
|
||||
webhook = Webhook.objects.create(name='Webhook 100', payload_url='http://example.com/?1', http_method='POST')
|
||||
form = EventRuleForm({
|
||||
"name": "Event Rule 1",
|
||||
"type_create": True,
|
||||
"type_update": True,
|
||||
"action_object_type": ct.pk,
|
||||
"action_type": "webhook",
|
||||
"action_choice": webhook.pk,
|
||||
"content_types": [site_ct.pk],
|
||||
"conditions": {
|
||||
"foo": "status.value",
|
||||
"value": "active"
|
||||
}
|
||||
})
|
||||
|
||||
self.assertFalse(form.is_valid())
|
||||
|
@ -25,7 +25,7 @@ from utilities.string import trailing_slash
|
||||
# Environment setup
|
||||
#
|
||||
|
||||
VERSION = '4.0.4-dev'
|
||||
VERSION = '4.0.6-dev'
|
||||
HOSTNAME = platform.node()
|
||||
# Set the base directory two levels up
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
@ -368,6 +368,8 @@ INSTALLED_APPS = [
|
||||
'drf_spectacular',
|
||||
'drf_spectacular_sidecar',
|
||||
]
|
||||
if not DEBUG:
|
||||
INSTALLED_APPS.remove('debug_toolbar')
|
||||
if not DJANGO_ADMIN_ENABLED:
|
||||
INSTALLED_APPS.remove('django.contrib.admin')
|
||||
|
||||
|
BIN
netbox/project-static/dist/netbox.js
vendored
BIN
netbox/project-static/dist/netbox.js
vendored
Binary file not shown.
BIN
netbox/project-static/dist/netbox.js.map
vendored
BIN
netbox/project-static/dist/netbox.js.map
vendored
Binary file not shown.
@ -27,10 +27,10 @@
|
||||
"bootstrap": "5.3.3",
|
||||
"clipboard": "2.0.11",
|
||||
"flatpickr": "4.6.13",
|
||||
"gridstack": "10.1.2",
|
||||
"gridstack": "10.2.0",
|
||||
"htmx.org": "1.9.12",
|
||||
"query-string": "9.0.0",
|
||||
"sass": "1.77.2",
|
||||
"sass": "1.77.4",
|
||||
"tom-select": "2.3.1",
|
||||
"typeface-inter": "3.18.1",
|
||||
"typeface-roboto-mono": "1.1.13"
|
||||
|
@ -1754,10 +1754,10 @@ graphql@16.8.1:
|
||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07"
|
||||
integrity sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==
|
||||
|
||||
gridstack@10.1.2:
|
||||
version "10.1.2"
|
||||
resolved "https://registry.yarnpkg.com/gridstack/-/gridstack-10.1.2.tgz#58b5ae0057a8aa5e4f6563041c4ca2def3aa4268"
|
||||
integrity sha512-Nn27XGQ68WtBC513cKQQ4t/dA2uuN/xnNUU50puXEJv6IFk5SzT0Dnsq68GpopO1n0tXUKZKm1Rw7uOUMDz1KQ==
|
||||
gridstack@10.2.0:
|
||||
version "10.2.0"
|
||||
resolved "https://registry.yarnpkg.com/gridstack/-/gridstack-10.2.0.tgz#4ba9c7ee69a730851721a9f5cb33dc55026ded1f"
|
||||
integrity sha512-svKAOq/dfinpvhe/nnxdyZOOEd9qynXiOPHvL96PALE0yWChWp/6lechnqKwud0tL/rRyAfMJ6Hh/z2fS13pBA==
|
||||
|
||||
has-bigints@^1.0.1, has-bigints@^1.0.2:
|
||||
version "1.0.2"
|
||||
@ -2482,10 +2482,10 @@ safe-regex-test@^1.0.3:
|
||||
es-errors "^1.3.0"
|
||||
is-regex "^1.1.4"
|
||||
|
||||
sass@1.77.2:
|
||||
version "1.77.2"
|
||||
resolved "https://registry.yarnpkg.com/sass/-/sass-1.77.2.tgz#18d4ed2eefc260cdc8099c5439ec1303fd5863aa"
|
||||
integrity sha512-eb4GZt1C3avsX3heBNlrc7I09nyT00IUuo4eFhAbeXWU2fvA7oXI53SxODVAA+zgZCk9aunAZgO+losjR3fAwA==
|
||||
sass@1.77.4:
|
||||
version "1.77.4"
|
||||
resolved "https://registry.yarnpkg.com/sass/-/sass-1.77.4.tgz#92059c7bfc56b827c56eb116778d157ec017a5cd"
|
||||
integrity sha512-vcF3Ckow6g939GMA4PeU7b2K/9FALXk2KF9J87txdHzXbUF9XRQRwSxcAs/fGaTnJeBFd7UoV22j3lzMLdM0Pw==
|
||||
dependencies:
|
||||
chokidar ">=3.0.0 <4.0.0"
|
||||
immutable "^4.0.0"
|
||||
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-06-05 05:02+0000\n"
|
||||
"POT-Creation-Date: 2024-06-08 05:02+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -6674,14 +6674,12 @@ msgstr ""
|
||||
msgid "Ruleset must be a dictionary, not {ruleset}."
|
||||
msgstr ""
|
||||
|
||||
#: netbox/extras/conditions.py:139
|
||||
#, python-brace-format
|
||||
msgid "Ruleset must have exactly one logical operator (found {ruleset})"
|
||||
#: netbox/extras/conditions.py:142
|
||||
msgid "Invalid logic type: must be 'AND' or 'OR'. Please check documentation."
|
||||
msgstr ""
|
||||
|
||||
#: netbox/extras/conditions.py:145
|
||||
#, python-brace-format
|
||||
msgid "Invalid logic type: {logic} (must be '{op_and}' or '{op_or}')"
|
||||
#: netbox/extras/conditions.py:154
|
||||
msgid "Incorrect key(s) informed. Please check documentation."
|
||||
msgstr ""
|
||||
|
||||
#: netbox/extras/dashboard/forms.py:38
|
||||
@ -10452,43 +10450,43 @@ msgstr ""
|
||||
msgid "Cannot delete stores from registry"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:722
|
||||
#: netbox/netbox/settings.py:724
|
||||
msgid "German"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:723
|
||||
#: netbox/netbox/settings.py:725
|
||||
msgid "English"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:724
|
||||
#: netbox/netbox/settings.py:726
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:725
|
||||
#: netbox/netbox/settings.py:727
|
||||
msgid "French"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:726
|
||||
#: netbox/netbox/settings.py:728
|
||||
msgid "Japanese"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:727
|
||||
#: netbox/netbox/settings.py:729
|
||||
msgid "Portuguese"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:728
|
||||
#: netbox/netbox/settings.py:730
|
||||
msgid "Russian"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:729
|
||||
#: netbox/netbox/settings.py:731
|
||||
msgid "Turkish"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:730
|
||||
#: netbox/netbox/settings.py:732
|
||||
msgid "Ukrainian"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:731
|
||||
#: netbox/netbox/settings.py:733
|
||||
msgid "Chinese"
|
||||
msgstr ""
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -15,23 +15,23 @@ django-tables2==2.7.0
|
||||
django-timezone-field==6.1.0
|
||||
djangorestframework==3.15.1
|
||||
drf-spectacular==0.27.2
|
||||
drf-spectacular-sidecar==2024.5.1
|
||||
drf-spectacular-sidecar==2024.6.1
|
||||
feedparser==6.0.11
|
||||
gunicorn==22.0.0
|
||||
Jinja2==3.1.4
|
||||
Markdown==3.6
|
||||
mkdocs-material==9.5.24
|
||||
mkdocs-material==9.5.26
|
||||
mkdocstrings[python-legacy]==0.25.1
|
||||
netaddr==1.2.1
|
||||
netaddr==1.3.0
|
||||
nh3==0.2.17
|
||||
Pillow==10.3.0
|
||||
psycopg[c,pool]==3.1.19
|
||||
PyYAML==6.0.1
|
||||
requests==2.32.2
|
||||
requests==2.32.3
|
||||
social-auth-app-django==5.4.1
|
||||
social-auth-core==4.5.4
|
||||
strawberry-graphql==0.230.0
|
||||
strawberry-graphql-django==0.40.0
|
||||
strawberry-graphql==0.234.0
|
||||
strawberry-graphql-django==0.42.0
|
||||
svgwrite==1.4.3
|
||||
tablib==3.6.1
|
||||
tzdata==2024.1
|
||||
|
Loading…
Reference in New Issue
Block a user