mirror of
https://github.com/netbox-community/netbox.git
synced 2025-12-31 01:27:45 -06:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f845b2cf07 | ||
|
|
2ed4a2b005 | ||
|
|
5b9210dfa5 | ||
|
|
4a13664e0f | ||
|
|
a9f3c74b0c | ||
|
|
50b7f46fc0 | ||
|
|
07ad4c1321 | ||
|
|
4a1fea3504 | ||
|
|
993d8f1480 | ||
|
|
c3efa2149c | ||
|
|
a75fa53d4d | ||
|
|
e75d327f38 | ||
|
|
a79d869bd8 | ||
|
|
32422d1683 | ||
|
|
571f604ce8 | ||
|
|
b12c8c880f | ||
|
|
b11f179527 | ||
|
|
80e1fd02bb | ||
|
|
4090afbf24 |
15
.github/ISSUE_TEMPLATE/01-feature_request.yaml
vendored
15
.github/ISSUE_TEMPLATE/01-feature_request.yaml
vendored
@@ -14,7 +14,7 @@ body:
|
||||
attributes:
|
||||
label: NetBox version
|
||||
description: What version of NetBox are you currently running?
|
||||
placeholder: v4.2.1
|
||||
placeholder: v4.2.2
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
@@ -27,19 +27,6 @@ body:
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Triage priority
|
||||
description: >
|
||||
Issue triage may be prioritized in some cases. Select whichever of the following
|
||||
conditions applies, if any.
|
||||
options:
|
||||
- I volunteer to perform this work (if approved)
|
||||
- I'm a NetBox Labs customer
|
||||
- N/A
|
||||
default: 2
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Proposed functionality
|
||||
|
||||
15
.github/ISSUE_TEMPLATE/02-bug_report.yaml
vendored
15
.github/ISSUE_TEMPLATE/02-bug_report.yaml
vendored
@@ -22,24 +22,11 @@ body:
|
||||
- Self-hosted
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Triage priority
|
||||
description: >
|
||||
Issue triage may be prioritized in some cases. Select whichever of the following
|
||||
conditions applies, if any.
|
||||
options:
|
||||
- I volunteer to perform this work (if approved)
|
||||
- I'm a NetBox Labs customer
|
||||
- N/A
|
||||
default: 2
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: NetBox Version
|
||||
description: What version of NetBox are you currently running?
|
||||
placeholder: v4.2.1
|
||||
placeholder: v4.2.2
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
|
||||
@@ -8,8 +8,6 @@ django-cors-headers
|
||||
|
||||
# Runtime UI tool for debugging Django
|
||||
# https://github.com/jazzband/django-debug-toolbar/blob/main/docs/changes.rst
|
||||
# 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
|
||||
|
||||
# Library for writing reusable URL query filters
|
||||
|
||||
@@ -21,7 +21,7 @@ The following sections detail how to set up a new instance of NetBox:
|
||||
| Dependency | Supported Versions |
|
||||
|------------|--------------------|
|
||||
| Python | 3.10, 3.11, 3.12 |
|
||||
| PostgreSQL | 12+ |
|
||||
| PostgreSQL | 13+ |
|
||||
| Redis | 4.0+ |
|
||||
|
||||
Below is a simplified overview of the NetBox application stack for reference:
|
||||
|
||||
@@ -20,7 +20,7 @@ NetBox requires the following dependencies:
|
||||
| Dependency | Supported Versions |
|
||||
|------------|--------------------|
|
||||
| Python | 3.10, 3.11, 3.12 |
|
||||
| PostgreSQL | 12+ |
|
||||
| PostgreSQL | 13+ |
|
||||
| Redis | 4.0+ |
|
||||
|
||||
## 3. Install the Latest Release
|
||||
|
||||
@@ -1,5 +1,25 @@
|
||||
# NetBox v4.2
|
||||
|
||||
## v4.2.2 (2025-01-17)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* [#18336](https://github.com/netbox-community/netbox/issues/18336) - Validate new rack height against installed devices when changing a rack's type
|
||||
* [#18350](https://github.com/netbox-community/netbox/issues/18350) - Fix `FieldDoesNotExist` exception when global search results include a circuit termination
|
||||
* [#18353](https://github.com/netbox-community/netbox/issues/18353) - Disable fetching of plugin catalog data when `ISOLATED_DEPLOYMENT` is enabled
|
||||
* [#18362](https://github.com/netbox-community/netbox/issues/18362) - Avoid transmitting census data on every worker restart
|
||||
* [#18363](https://github.com/netbox-community/netbox/issues/18363) - Fix support for assigning a MAC address to an interface via the REST API
|
||||
* [#18368](https://github.com/netbox-community/netbox/issues/18368) - Restore missing attributes from REST API serializer for MAC addresses (`tags`, `created`, `last_updated`, and custom fields)
|
||||
* [#18369](https://github.com/netbox-community/netbox/issues/18369) - Fix `TypeError` exception when rendering the system configuration view with one or more custom classes defined under `PROTECTION_RULES`
|
||||
* [#18373](https://github.com/netbox-community/netbox/issues/18373) - Fix `AttributeError` exception when attempting to assign host devices to a cluster
|
||||
* [#18376](https://github.com/netbox-community/netbox/issues/18376) - Fix the display of tagged VLANs in interfaces list for Q-in-Q interfaces
|
||||
* [#18379](https://github.com/netbox-community/netbox/issues/18379) - Ensure RSS feed dashboard widget content is sanitized
|
||||
* [#18392](https://github.com/netbox-community/netbox/issues/18392) - Virtual machines should not inherit config contexts assigned to locations
|
||||
* [#18400](https://github.com/netbox-community/netbox/issues/18400) - Fix support for `STORAGE_BACKEND` configuration parameter
|
||||
* [#18406](https://github.com/netbox-community/netbox/issues/18406) - Scope column headers in object lists should not be orderable
|
||||
|
||||
---
|
||||
|
||||
## v4.2.1 (2025-01-08)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -34,7 +34,7 @@ class CircuitTerminationIndex(SearchIndex):
|
||||
('port_speed', 2000),
|
||||
('upstream_speed', 2000),
|
||||
)
|
||||
display_attrs = ('circuit', 'site', 'provider_network', 'description')
|
||||
display_attrs = ('circuit', 'termination', 'description')
|
||||
|
||||
|
||||
@register_search
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import logging
|
||||
import requests
|
||||
import sys
|
||||
|
||||
from netbox.jobs import JobRunner
|
||||
from django.conf import settings
|
||||
from netbox.jobs import JobRunner, system_job
|
||||
from netbox.search.backends import search_backend
|
||||
from .choices import DataSourceStatusChoices
|
||||
from .choices import DataSourceStatusChoices, JobIntervalChoices
|
||||
from .exceptions import SyncError
|
||||
from .models import DataSource
|
||||
|
||||
@@ -31,3 +34,44 @@ class SyncDataSourceJob(JobRunner):
|
||||
if type(e) is SyncError:
|
||||
logging.error(e)
|
||||
raise e
|
||||
|
||||
|
||||
@system_job(interval=JobIntervalChoices.INTERVAL_DAILY)
|
||||
class SystemHousekeepingJob(JobRunner):
|
||||
"""
|
||||
Perform daily system housekeeping functions.
|
||||
"""
|
||||
class Meta:
|
||||
name = "System Housekeeping"
|
||||
|
||||
def run(self, *args, **kwargs):
|
||||
# Skip if running in development or test mode
|
||||
if settings.DEBUG or 'test' in sys.argv:
|
||||
return
|
||||
|
||||
# TODO: Migrate other housekeeping functions from the `housekeeping` management command.
|
||||
self.send_census_report()
|
||||
|
||||
@staticmethod
|
||||
def send_census_report():
|
||||
"""
|
||||
Send a census report (if enabled).
|
||||
"""
|
||||
# Skip if census reporting is disabled
|
||||
if settings.ISOLATED_DEPLOYMENT or not settings.CENSUS_REPORTING_ENABLED:
|
||||
return
|
||||
|
||||
census_data = {
|
||||
'version': settings.RELEASE.full_version,
|
||||
'python_version': sys.version.split()[0],
|
||||
'deployment_id': settings.DEPLOYMENT_ID,
|
||||
}
|
||||
try:
|
||||
requests.get(
|
||||
url=settings.CENSUS_URL,
|
||||
params=census_data,
|
||||
timeout=3,
|
||||
proxies=settings.HTTP_PROXIES
|
||||
)
|
||||
except requests.exceptions.RequestException:
|
||||
pass
|
||||
|
||||
@@ -570,8 +570,9 @@ class SystemView(UserPassesTestMixin, View):
|
||||
return response
|
||||
|
||||
# Serialize any CustomValidator classes
|
||||
if hasattr(config, 'CUSTOM_VALIDATORS') and config.CUSTOM_VALIDATORS:
|
||||
config.CUSTOM_VALIDATORS = json.dumps(config.CUSTOM_VALIDATORS, cls=ConfigJSONEncoder, indent=4)
|
||||
for attr in ['CUSTOM_VALIDATORS', 'PROTECTION_RULES']:
|
||||
if hasattr(config, attr) and getattr(config, attr, None):
|
||||
setattr(config, attr, json.dumps(getattr(config, attr), cls=ConfigJSONEncoder, indent=4))
|
||||
|
||||
return render(request, 'core/system.html', {
|
||||
'stats': stats,
|
||||
@@ -594,7 +595,7 @@ class BasePluginView(UserPassesTestMixin, View):
|
||||
catalog_plugins_error = cache.get(self.CACHE_KEY_CATALOG_ERROR, default=False)
|
||||
if not catalog_plugins_error:
|
||||
catalog_plugins = get_catalog_plugins()
|
||||
if not catalog_plugins:
|
||||
if not catalog_plugins and not settings.ISOLATED_DEPLOYMENT:
|
||||
# Cache for 5 minutes to avoid spamming connection
|
||||
cache.set(self.CACHE_KEY_CATALOG_ERROR, True, 300)
|
||||
messages.warning(request, _("Plugins catalog could not be loaded"))
|
||||
|
||||
@@ -170,8 +170,8 @@ class MACAddressSerializer(NetBoxModelSerializer):
|
||||
class Meta:
|
||||
model = MACAddress
|
||||
fields = [
|
||||
'id', 'url', 'display_url', 'display', 'mac_address', 'assigned_object_type', 'assigned_object',
|
||||
'description', 'comments',
|
||||
'id', 'url', 'display_url', 'display', 'mac_address', 'assigned_object_type', 'assigned_object_id',
|
||||
'assigned_object', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated',
|
||||
]
|
||||
brief_fields = ('id', 'url', 'display', 'mac_address', 'description')
|
||||
|
||||
|
||||
@@ -374,22 +374,27 @@ class Rack(ContactsMixin, ImageAttachmentsMixin, RackBase):
|
||||
if not self._state.adding:
|
||||
mounted_devices = Device.objects.filter(rack=self).exclude(position__isnull=True).order_by('position')
|
||||
|
||||
effective_u_height = self.rack_type.u_height if self.rack_type else self.u_height
|
||||
effective_starting_unit = self.rack_type.starting_unit if self.rack_type else self.starting_unit
|
||||
|
||||
# Validate that Rack is tall enough to house the highest mounted Device
|
||||
if top_device := mounted_devices.last():
|
||||
min_height = top_device.position + top_device.device_type.u_height - self.starting_unit
|
||||
if self.u_height < min_height:
|
||||
min_height = top_device.position + top_device.device_type.u_height - effective_starting_unit
|
||||
if effective_u_height < min_height:
|
||||
field = 'rack_type' if self.rack_type else 'u_height'
|
||||
raise ValidationError({
|
||||
'u_height': _(
|
||||
field: _(
|
||||
"Rack must be at least {min_height}U tall to house currently installed devices."
|
||||
).format(min_height=min_height)
|
||||
})
|
||||
|
||||
# Validate that the Rack's starting unit is less than or equal to the position of the lowest mounted Device
|
||||
if last_device := mounted_devices.first():
|
||||
if self.starting_unit > last_device.position:
|
||||
if effective_starting_unit > last_device.position:
|
||||
field = 'rack_type' if self.rack_type else 'starting_unit'
|
||||
raise ValidationError({
|
||||
'starting_unit': _("Rack unit numbering must begin at {position} or less to house "
|
||||
"currently installed devices.").format(position=last_device.position)
|
||||
field: _("Rack unit numbering must begin at {position} or less to house "
|
||||
"currently installed devices.").format(position=last_device.position)
|
||||
})
|
||||
|
||||
# Validate that Rack was assigned a Location of its same site, if applicable
|
||||
|
||||
@@ -69,16 +69,18 @@ INTERFACE_FHRPGROUPS = """
|
||||
"""
|
||||
|
||||
INTERFACE_TAGGED_VLANS = """
|
||||
{% if record.mode == 'tagged' %}
|
||||
{% load i18n %}
|
||||
{% if record.mode == 'access' %}
|
||||
{% elif record.mode == 'tagged-all' %}
|
||||
{% trans "All" %}
|
||||
{% else %}
|
||||
{% if value.count > 3 %}
|
||||
<a href="{% url 'ipam:vlan_list' %}?{{ record|meta:"model_name" }}_id={{ record.pk }}">{{ value.count }} VLANs</a>
|
||||
{% else %}
|
||||
{% for vlan in value.all %}
|
||||
<a href="{{ vlan.get_absolute_url }}">{{ vlan }}</a><br />
|
||||
<a href="{{ vlan.get_absolute_url }}">{{ vlan }}</a><br />
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% elif record.mode == 'tagged-all' %}
|
||||
All
|
||||
{% endif %}
|
||||
"""
|
||||
|
||||
|
||||
@@ -2447,3 +2447,46 @@ class VirtualDeviceContextTest(APIViewTestCases.APIViewTestCase):
|
||||
# Omit identifier to test uniqueness constraint
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
class MACAddressTest(APIViewTestCases.APIViewTestCase):
|
||||
model = MACAddress
|
||||
brief_fields = ['description', 'display', 'id', 'mac_address', 'url']
|
||||
bulk_update_data = {
|
||||
'description': 'New description',
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
device = create_test_device(name='Device 1')
|
||||
interfaces = (
|
||||
Interface(device=device, name='Interface 1', type='1000base-t'),
|
||||
Interface(device=device, name='Interface 2', type='1000base-t'),
|
||||
Interface(device=device, name='Interface 3', type='1000base-t'),
|
||||
Interface(device=device, name='Interface 4', type='1000base-t'),
|
||||
Interface(device=device, name='Interface 5', type='1000base-t'),
|
||||
)
|
||||
Interface.objects.bulk_create(interfaces)
|
||||
|
||||
mac_addresses = (
|
||||
MACAddress(mac_address='00:00:00:00:00:01', assigned_object=interfaces[0]),
|
||||
MACAddress(mac_address='00:00:00:00:00:02', assigned_object=interfaces[1]),
|
||||
MACAddress(mac_address='00:00:00:00:00:03', assigned_object=interfaces[2]),
|
||||
)
|
||||
MACAddress.objects.bulk_create(mac_addresses)
|
||||
|
||||
cls.create_data = [
|
||||
{
|
||||
'mac_address': '00:00:00:00:00:04',
|
||||
'assigned_object_type': 'dcim.interface',
|
||||
'assigned_object_id': interfaces[3].pk,
|
||||
},
|
||||
{
|
||||
'mac_address': '00:00:00:00:00:05',
|
||||
'assigned_object_type': 'dcim.interface',
|
||||
'assigned_object_id': interfaces[4].pk,
|
||||
},
|
||||
{
|
||||
'mac_address': '00:00:00:00:00:06',
|
||||
},
|
||||
]
|
||||
|
||||
@@ -3470,3 +3470,54 @@ class VirtualDeviceContextTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
||||
cls.bulk_edit_data = {
|
||||
'status': VirtualDeviceContextStatusChoices.STATUS_OFFLINE,
|
||||
}
|
||||
|
||||
|
||||
class MACAddressTestCase(ViewTestCases.PrimaryObjectViewTestCase):
|
||||
model = MACAddress
|
||||
|
||||
@classmethod
|
||||
def setUpTestData(cls):
|
||||
device = create_test_device(name='Device 1')
|
||||
interfaces = (
|
||||
Interface(device=device, name='Interface 1', type='1000base-t'),
|
||||
Interface(device=device, name='Interface 2', type='1000base-t'),
|
||||
Interface(device=device, name='Interface 3', type='1000base-t'),
|
||||
Interface(device=device, name='Interface 4', type='1000base-t'),
|
||||
Interface(device=device, name='Interface 5', type='1000base-t'),
|
||||
Interface(device=device, name='Interface 6', type='1000base-t'),
|
||||
)
|
||||
Interface.objects.bulk_create(interfaces)
|
||||
|
||||
mac_addresses = (
|
||||
MACAddress(mac_address='00:00:00:00:00:01', assigned_object=interfaces[0]),
|
||||
MACAddress(mac_address='00:00:00:00:00:02', assigned_object=interfaces[1]),
|
||||
MACAddress(mac_address='00:00:00:00:00:03', assigned_object=interfaces[2]),
|
||||
)
|
||||
MACAddress.objects.bulk_create(mac_addresses)
|
||||
|
||||
tags = create_tags('Alpha', 'Bravo', 'Charlie')
|
||||
|
||||
cls.form_data = {
|
||||
'mac_address': EUI('00:00:00:00:00:04'),
|
||||
'description': 'New MAC address',
|
||||
'interface_id': interfaces[3].pk,
|
||||
'tags': [t.pk for t in tags],
|
||||
}
|
||||
|
||||
cls.csv_data = (
|
||||
"mac_address,device,interface",
|
||||
"00:00:00:00:00:04,Device 1,Interface 4",
|
||||
"00:00:00:00:00:05,Device 1,Interface 5",
|
||||
"00:00:00:00:00:06,Device 1,Interface 6",
|
||||
)
|
||||
|
||||
cls.csv_update_data = (
|
||||
"id,mac_address",
|
||||
f"{mac_addresses[0].pk},00:00:00:00:00:0a",
|
||||
f"{mac_addresses[1].pk},00:00:00:00:00:0b",
|
||||
f"{mac_addresses[2].pk},00:00:00:00:00:0c",
|
||||
)
|
||||
|
||||
cls.bulk_edit_data = {
|
||||
'description': 'New description',
|
||||
}
|
||||
|
||||
@@ -120,11 +120,12 @@ class ConfigContextModelQuerySet(RestrictedQuerySet):
|
||||
is_active=True,
|
||||
)
|
||||
|
||||
# Apply Location & DeviceType filters only for VirtualMachines
|
||||
if self.model._meta.model_name == 'device':
|
||||
base_query.add((Q(locations=OuterRef('location')) | Q(locations=None)), Q.AND)
|
||||
base_query.add((Q(device_types=OuterRef('device_type')) | Q(device_types=None)), Q.AND)
|
||||
|
||||
elif self.model._meta.model_name == 'virtualmachine':
|
||||
base_query.add(Q(locations=None), Q.AND)
|
||||
base_query.add(Q(device_types=None), Q.AND)
|
||||
|
||||
base_query.add((Q(roles=OuterRef('role')) | Q(roles=None)), Q.AND)
|
||||
|
||||
@@ -192,7 +192,8 @@ class PrefixTable(TenancyColumnsMixin, NetBoxTable):
|
||||
)
|
||||
scope = tables.Column(
|
||||
verbose_name=_('Scope'),
|
||||
linkify=True
|
||||
linkify=True,
|
||||
orderable=False
|
||||
)
|
||||
vlan_group = tables.Column(
|
||||
accessor='vlan__group',
|
||||
|
||||
@@ -5,9 +5,7 @@ import os
|
||||
import platform
|
||||
import sys
|
||||
import warnings
|
||||
from urllib.parse import urlencode
|
||||
|
||||
import requests
|
||||
from django.contrib.messages import constants as messages
|
||||
from django.core.exceptions import ImproperlyConfigured, ValidationError
|
||||
from django.core.validators import URLValidator
|
||||
@@ -224,8 +222,18 @@ DATABASES = {
|
||||
# Storage backend
|
||||
#
|
||||
|
||||
# Default STORAGES for Django
|
||||
STORAGES = {
|
||||
"default": {
|
||||
"BACKEND": "django.core.files.storage.FileSystemStorage",
|
||||
},
|
||||
"staticfiles": {
|
||||
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
|
||||
},
|
||||
}
|
||||
|
||||
if STORAGE_BACKEND is not None:
|
||||
DEFAULT_FILE_STORAGE = STORAGE_BACKEND
|
||||
STORAGES['default']['BACKEND'] = STORAGE_BACKEND
|
||||
|
||||
# django-storages
|
||||
if STORAGE_BACKEND.startswith('storages.'):
|
||||
@@ -583,17 +591,6 @@ if SENTRY_ENABLED:
|
||||
# Calculate a unique deployment ID from the secret key
|
||||
DEPLOYMENT_ID = hashlib.sha256(SECRET_KEY.encode('utf-8')).hexdigest()[:16]
|
||||
CENSUS_URL = 'https://census.netbox.oss.netboxlabs.com/api/v1/'
|
||||
CENSUS_PARAMS = {
|
||||
'version': RELEASE.full_version,
|
||||
'python_version': sys.version.split()[0],
|
||||
'deployment_id': DEPLOYMENT_ID,
|
||||
}
|
||||
if CENSUS_REPORTING_ENABLED and not ISOLATED_DEPLOYMENT and not DEBUG and 'test' not in sys.argv:
|
||||
try:
|
||||
# Report anonymous census data
|
||||
requests.get(f'{CENSUS_URL}?{urlencode(CENSUS_PARAMS)}', timeout=3, proxies=HTTP_PROXIES)
|
||||
except requests.exceptions.RequestException:
|
||||
pass
|
||||
|
||||
|
||||
#
|
||||
|
||||
10
netbox/project-static/dist/netbox.js
vendored
10
netbox/project-static/dist/netbox.js
vendored
File diff suppressed because one or more lines are too long
4
netbox/project-static/dist/netbox.js.map
vendored
4
netbox/project-static/dist/netbox.js.map
vendored
File diff suppressed because one or more lines are too long
@@ -27,10 +27,10 @@
|
||||
"bootstrap": "5.3.3",
|
||||
"clipboard": "2.0.11",
|
||||
"flatpickr": "4.6.13",
|
||||
"gridstack": "11.2.0",
|
||||
"gridstack": "11.3.0",
|
||||
"htmx.org": "1.9.12",
|
||||
"query-string": "9.1.1",
|
||||
"sass": "1.83.1",
|
||||
"sass": "1.83.4",
|
||||
"tom-select": "2.4.1",
|
||||
"typeface-inter": "3.18.1",
|
||||
"typeface-roboto-mono": "1.1.13"
|
||||
|
||||
@@ -1905,10 +1905,10 @@ graphql@16.10.0:
|
||||
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.10.0.tgz#24c01ae0af6b11ea87bf55694429198aaa8e220c"
|
||||
integrity sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ==
|
||||
|
||||
gridstack@11.2.0:
|
||||
version "11.2.0"
|
||||
resolved "https://registry.yarnpkg.com/gridstack/-/gridstack-11.2.0.tgz#8977a6632c521260f064ef171b92c7a8df4f58a9"
|
||||
integrity sha512-ajwUzd9spR8NXDxfJotHWq9WOYoDOV9o6UJR3ksevNz8cvXNxDtI9H/lC+RN6ijM2DexureLlsG0RpYjBZiOtg==
|
||||
gridstack@11.3.0:
|
||||
version "11.3.0"
|
||||
resolved "https://registry.yarnpkg.com/gridstack/-/gridstack-11.3.0.tgz#b110c66bafc64c920fc54933e2c9df4f7b2cfffe"
|
||||
integrity sha512-Z0eRovKcZTRTs3zetJwjO6CNwrgIy845WfOeZGk8ybpeMCE8fMA8tScyKU72Y2M6uGHkjgwnjflglvPiv+RcBQ==
|
||||
|
||||
has-bigints@^1.0.1, has-bigints@^1.0.2:
|
||||
version "1.0.2"
|
||||
@@ -2667,10 +2667,10 @@ safe-regex-test@^1.0.3:
|
||||
es-errors "^1.3.0"
|
||||
is-regex "^1.1.4"
|
||||
|
||||
sass@1.83.1:
|
||||
version "1.83.1"
|
||||
resolved "https://registry.yarnpkg.com/sass/-/sass-1.83.1.tgz#dee1ab94b47a6f9993d3195d36f556bcbda64846"
|
||||
integrity sha512-EVJbDaEs4Rr3F0glJzFSOvtg2/oy2V/YrGFPqPY24UqcLDWcI9ZY5sN+qyO3c/QCZwzgfirvhXvINiJCE/OLcA==
|
||||
sass@1.83.4:
|
||||
version "1.83.4"
|
||||
resolved "https://registry.yarnpkg.com/sass/-/sass-1.83.4.tgz#5ccf60f43eb61eeec300b780b8dcb85f16eec6d1"
|
||||
integrity sha512-B1bozCeNQiOgDcLd33e2Cs2U60wZwjUUXzh900ZyQF5qUasvMdDZYbQ566LJu7cqR+sAHlAfO6RMkaID5s6qpA==
|
||||
dependencies:
|
||||
chokidar "^4.0.0"
|
||||
immutable "^5.0.2"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version: "4.2.1"
|
||||
version: "4.2.2"
|
||||
edition: "Community"
|
||||
published: "2025-01-08"
|
||||
published: "2025-01-17"
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
<tr>
|
||||
<th scope="row" class="border-0 ps-3">{% trans "Protection rules" %}</th>
|
||||
{% if config.PROTECTION_RULES %}
|
||||
<td class="border-0"><pre>{{ config.PROTECTION_RULES|json }}</pre></td>
|
||||
<td class="border-0"><pre>{{ config.PROTECTION_RULES }}</pre></td>
|
||||
{% else %}
|
||||
<td class="border-0">{{ ''|placeholder }}</td>
|
||||
{% endif %}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<div class="list-group-item px-1 py-2">
|
||||
<a href="{{ entry.link }}" class="text-body">{{ entry.title }}</a>
|
||||
<div class="text-secondary">
|
||||
{{ entry.summary|safe }}
|
||||
{{ entry.summary }}
|
||||
</div>
|
||||
</div>
|
||||
{% empty %}
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-01-08 05:02+0000\n"
|
||||
"POT-Creation-Date: 2025-01-10 05:01+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"
|
||||
@@ -766,8 +766,8 @@ msgstr ""
|
||||
#: netbox/ipam/forms/filtersets.py:212 netbox/ipam/forms/filtersets.py:284
|
||||
#: netbox/ipam/forms/filtersets.py:358 netbox/ipam/forms/filtersets.py:542
|
||||
#: netbox/ipam/forms/model_forms.py:503 netbox/ipam/tables/ip.py:183
|
||||
#: netbox/ipam/tables/ip.py:262 netbox/ipam/tables/ip.py:313
|
||||
#: netbox/ipam/tables/ip.py:376 netbox/ipam/tables/ip.py:403
|
||||
#: netbox/ipam/tables/ip.py:263 netbox/ipam/tables/ip.py:314
|
||||
#: netbox/ipam/tables/ip.py:377 netbox/ipam/tables/ip.py:404
|
||||
#: netbox/ipam/tables/vlans.py:95 netbox/ipam/tables/vlans.py:208
|
||||
#: netbox/templates/circuits/circuit.html:34
|
||||
#: netbox/templates/circuits/virtualcircuit.html:43
|
||||
@@ -844,7 +844,7 @@ msgstr ""
|
||||
#: netbox/ipam/forms/filtersets.py:122 netbox/ipam/forms/filtersets.py:145
|
||||
#: netbox/ipam/forms/filtersets.py:176 netbox/ipam/forms/filtersets.py:270
|
||||
#: netbox/ipam/forms/filtersets.py:313 netbox/ipam/forms/filtersets.py:510
|
||||
#: netbox/ipam/tables/ip.py:406 netbox/ipam/tables/vlans.py:205
|
||||
#: netbox/ipam/tables/ip.py:407 netbox/ipam/tables/vlans.py:205
|
||||
#: netbox/templates/circuits/circuit.html:48
|
||||
#: netbox/templates/circuits/circuitgroup.html:36
|
||||
#: netbox/templates/circuits/virtualcircuit.html:47
|
||||
@@ -1078,8 +1078,8 @@ msgstr ""
|
||||
#: netbox/ipam/forms/filtersets.py:292 netbox/ipam/forms/filtersets.py:363
|
||||
#: netbox/ipam/forms/filtersets.py:550 netbox/ipam/forms/model_forms.py:194
|
||||
#: netbox/ipam/forms/model_forms.py:220 netbox/ipam/forms/model_forms.py:251
|
||||
#: netbox/ipam/forms/model_forms.py:678 netbox/ipam/tables/ip.py:207
|
||||
#: netbox/ipam/tables/ip.py:266 netbox/ipam/tables/ip.py:317
|
||||
#: netbox/ipam/forms/model_forms.py:678 netbox/ipam/tables/ip.py:208
|
||||
#: netbox/ipam/tables/ip.py:267 netbox/ipam/tables/ip.py:318
|
||||
#: netbox/ipam/tables/vlans.py:99 netbox/ipam/tables/vlans.py:211
|
||||
#: netbox/templates/circuits/virtualcircuittermination.html:42
|
||||
#: netbox/templates/dcim/device.html:182
|
||||
@@ -1191,7 +1191,7 @@ msgstr ""
|
||||
#: netbox/dcim/tables/connections.py:65 netbox/dcim/tables/devices.py:1140
|
||||
#: netbox/ipam/forms/bulk_import.py:317 netbox/ipam/forms/model_forms.py:282
|
||||
#: netbox/ipam/forms/model_forms.py:291 netbox/ipam/tables/fhrp.py:64
|
||||
#: netbox/ipam/tables/ip.py:322 netbox/ipam/tables/vlans.py:145
|
||||
#: netbox/ipam/tables/ip.py:323 netbox/ipam/tables/vlans.py:145
|
||||
#: netbox/templates/circuits/inc/circuit_termination_fields.html:52
|
||||
#: netbox/templates/circuits/virtualcircuittermination.html:53
|
||||
#: netbox/templates/circuits/virtualcircuittermination.html:60
|
||||
@@ -1831,8 +1831,8 @@ msgstr ""
|
||||
#: netbox/dcim/tables/racks.py:224 netbox/dcim/tables/sites.py:108
|
||||
#: netbox/extras/tables/tables.py:582 netbox/ipam/tables/asn.py:69
|
||||
#: netbox/ipam/tables/fhrp.py:34 netbox/ipam/tables/ip.py:82
|
||||
#: netbox/ipam/tables/ip.py:224 netbox/ipam/tables/ip.py:279
|
||||
#: netbox/ipam/tables/ip.py:347 netbox/ipam/tables/services.py:24
|
||||
#: netbox/ipam/tables/ip.py:225 netbox/ipam/tables/ip.py:280
|
||||
#: netbox/ipam/tables/ip.py:348 netbox/ipam/tables/services.py:24
|
||||
#: netbox/ipam/tables/services.py:54 netbox/ipam/tables/vlans.py:121
|
||||
#: netbox/ipam/tables/vrfs.py:47 netbox/ipam/tables/vrfs.py:72
|
||||
#: netbox/templates/dcim/htmx/cable_edit.html:89
|
||||
@@ -3009,7 +3009,7 @@ msgstr ""
|
||||
#: netbox/dcim/tables/devices.py:689 netbox/dcim/tables/devices.py:899
|
||||
#: netbox/dcim/tables/devices.py:986 netbox/dcim/tables/devices.py:1146
|
||||
#: netbox/extras/tables/tables.py:223 netbox/ipam/tables/fhrp.py:59
|
||||
#: netbox/ipam/tables/ip.py:328 netbox/ipam/tables/services.py:44
|
||||
#: netbox/ipam/tables/ip.py:329 netbox/ipam/tables/services.py:44
|
||||
#: netbox/templates/dcim/interface.html:108
|
||||
#: netbox/templates/dcim/interface.html:366
|
||||
#: netbox/templates/dcim/location.html:41 netbox/templates/dcim/region.html:37
|
||||
@@ -3688,8 +3688,8 @@ msgstr ""
|
||||
#: netbox/ipam/forms/model_forms.py:480 netbox/ipam/forms/model_forms.py:494
|
||||
#: netbox/ipam/models/ip.py:217 netbox/ipam/models/ip.py:498
|
||||
#: netbox/ipam/models/ip.py:719 netbox/ipam/models/vrfs.py:61
|
||||
#: netbox/ipam/tables/ip.py:188 netbox/ipam/tables/ip.py:259
|
||||
#: netbox/ipam/tables/ip.py:310 netbox/ipam/tables/ip.py:400
|
||||
#: netbox/ipam/tables/ip.py:188 netbox/ipam/tables/ip.py:260
|
||||
#: netbox/ipam/tables/ip.py:311 netbox/ipam/tables/ip.py:401
|
||||
#: netbox/templates/dcim/interface.html:152
|
||||
#: netbox/templates/ipam/ipaddress.html:18
|
||||
#: netbox/templates/ipam/iprange.html:40 netbox/templates/ipam/prefix.html:19
|
||||
@@ -6994,8 +6994,8 @@ msgstr ""
|
||||
|
||||
#: netbox/dcim/tables/devices.py:197 netbox/dcim/tables/devices.py:1099
|
||||
#: netbox/ipam/forms/bulk_import.py:562 netbox/ipam/forms/model_forms.py:308
|
||||
#: netbox/ipam/forms/model_forms.py:321 netbox/ipam/tables/ip.py:306
|
||||
#: netbox/ipam/tables/ip.py:373 netbox/ipam/tables/ip.py:396
|
||||
#: netbox/ipam/forms/model_forms.py:321 netbox/ipam/tables/ip.py:307
|
||||
#: netbox/ipam/tables/ip.py:374 netbox/ipam/tables/ip.py:397
|
||||
#: netbox/templates/ipam/ipaddress.html:11
|
||||
#: netbox/virtualization/tables/virtualmachines.py:65
|
||||
msgid "IP Address"
|
||||
@@ -9658,7 +9658,7 @@ msgstr ""
|
||||
|
||||
#: netbox/ipam/forms/bulk_edit.py:218 netbox/ipam/forms/bulk_import.py:181
|
||||
#: netbox/ipam/forms/filtersets.py:259 netbox/ipam/forms/model_forms.py:217
|
||||
#: netbox/ipam/models/vlans.py:272 netbox/ipam/tables/ip.py:204
|
||||
#: netbox/ipam/models/vlans.py:272 netbox/ipam/tables/ip.py:205
|
||||
#: netbox/templates/ipam/prefix.html:56 netbox/templates/ipam/vlan.html:12
|
||||
#: netbox/templates/ipam/vlan/base.html:6
|
||||
#: netbox/templates/ipam/vlan_edit.html:10
|
||||
@@ -10516,8 +10516,8 @@ msgstr ""
|
||||
msgid "Prefixes"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/ipam/tables/ip.py:77 netbox/ipam/tables/ip.py:219
|
||||
#: netbox/ipam/tables/ip.py:274 netbox/ipam/tables/vlans.py:55
|
||||
#: netbox/ipam/tables/ip.py:77 netbox/ipam/tables/ip.py:220
|
||||
#: netbox/ipam/tables/ip.py:275 netbox/ipam/tables/vlans.py:55
|
||||
#: netbox/templates/dcim/device.html:260
|
||||
#: netbox/templates/ipam/aggregate.html:24
|
||||
#: netbox/templates/ipam/iprange.html:29 netbox/templates/ipam/prefix.html:102
|
||||
@@ -10542,31 +10542,31 @@ msgstr ""
|
||||
msgid "Scope Type"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/ipam/tables/ip.py:211
|
||||
#: netbox/ipam/tables/ip.py:212
|
||||
msgid "Pool"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/ipam/tables/ip.py:215 netbox/ipam/tables/ip.py:270
|
||||
#: netbox/ipam/tables/ip.py:216 netbox/ipam/tables/ip.py:271
|
||||
msgid "Marked Utilized"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/ipam/tables/ip.py:254
|
||||
#: netbox/ipam/tables/ip.py:255
|
||||
msgid "Start address"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/ipam/tables/ip.py:333
|
||||
#: netbox/ipam/tables/ip.py:334
|
||||
msgid "NAT (Inside)"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/ipam/tables/ip.py:338
|
||||
#: netbox/ipam/tables/ip.py:339
|
||||
msgid "NAT (Outside)"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/ipam/tables/ip.py:343
|
||||
#: netbox/ipam/tables/ip.py:344
|
||||
msgid "Assigned"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/ipam/tables/ip.py:379 netbox/templates/vpn/l2vpntermination.html:16
|
||||
#: netbox/ipam/tables/ip.py:380 netbox/templates/vpn/l2vpntermination.html:16
|
||||
#: netbox/vpn/forms/filtersets.py:240
|
||||
msgid "Assigned Object"
|
||||
msgstr ""
|
||||
@@ -11582,63 +11582,63 @@ msgstr ""
|
||||
msgid "Cannot delete stores from registry"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:755
|
||||
#: netbox/netbox/settings.py:742
|
||||
msgid "Czech"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:756
|
||||
#: netbox/netbox/settings.py:743
|
||||
msgid "Danish"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:757
|
||||
#: netbox/netbox/settings.py:744
|
||||
msgid "German"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:758
|
||||
#: netbox/netbox/settings.py:745
|
||||
msgid "English"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:759
|
||||
#: netbox/netbox/settings.py:746
|
||||
msgid "Spanish"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:760
|
||||
#: netbox/netbox/settings.py:747
|
||||
msgid "French"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:761
|
||||
#: netbox/netbox/settings.py:748
|
||||
msgid "Italian"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:762
|
||||
#: netbox/netbox/settings.py:749
|
||||
msgid "Japanese"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:763
|
||||
#: netbox/netbox/settings.py:750
|
||||
msgid "Dutch"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:764
|
||||
#: netbox/netbox/settings.py:751
|
||||
msgid "Polish"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:765
|
||||
#: netbox/netbox/settings.py:752
|
||||
msgid "Portuguese"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:766
|
||||
#: netbox/netbox/settings.py:753
|
||||
msgid "Russian"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:767
|
||||
#: netbox/netbox/settings.py:754
|
||||
msgid "Turkish"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:768
|
||||
#: netbox/netbox/settings.py:755
|
||||
msgid "Ukrainian"
|
||||
msgstr ""
|
||||
|
||||
#: netbox/netbox/settings.py:769
|
||||
#: netbox/netbox/settings.py:756
|
||||
msgid "Chinese"
|
||||
msgstr ""
|
||||
|
||||
|
||||
Binary file not shown.
@@ -12,8 +12,8 @@
|
||||
# Alexander Ryazanov (alryaz) <alryaz@xavux.com>, 2024
|
||||
# Vladyslav V. Prodan, 2024
|
||||
# Jeremy Stretch, 2024
|
||||
# Michail Tatarinov, 2024
|
||||
# Artem Kotik, 2025
|
||||
# Michail Tatarinov, 2025
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
@@ -22,7 +22,7 @@ msgstr ""
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-01-04 05:02+0000\n"
|
||||
"PO-Revision-Date: 2023-10-30 17:48+0000\n"
|
||||
"Last-Translator: Artem Kotik, 2025\n"
|
||||
"Last-Translator: Michail Tatarinov, 2025\n"
|
||||
"Language-Team: Russian (https://app.transifex.com/netbox-community/teams/178115/ru/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -6334,7 +6334,7 @@ msgstr "распределительный щит"
|
||||
|
||||
#: netbox/dcim/models/power.py:56
|
||||
msgid "power panels"
|
||||
msgstr "распределительный щиты"
|
||||
msgstr "распределительные щиты"
|
||||
|
||||
#: netbox/dcim/models/power.py:70
|
||||
#, python-brace-format
|
||||
@@ -9256,7 +9256,7 @@ msgstr "SLAAC"
|
||||
|
||||
#: netbox/ipam/choices.py:89
|
||||
msgid "Loopback"
|
||||
msgstr "Обратная петля"
|
||||
msgstr "Loopback"
|
||||
|
||||
#: netbox/ipam/choices.py:91
|
||||
msgid "Anycast"
|
||||
@@ -11185,7 +11185,7 @@ msgstr "Сети провайдеров"
|
||||
|
||||
#: netbox/netbox/navigation/menu.py:298
|
||||
msgid "Power Panels"
|
||||
msgstr "Распределительный щиты"
|
||||
msgstr "Распределительные щиты"
|
||||
|
||||
#: netbox/netbox/navigation/menu.py:309
|
||||
msgid "Configurations"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from django import forms
|
||||
from django.apps import apps
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
@@ -143,19 +144,26 @@ class ClusterAddDevicesForm(forms.Form):
|
||||
def clean(self):
|
||||
super().clean()
|
||||
|
||||
# If the Cluster is assigned to a Site, all Devices must be assigned to that Site.
|
||||
if self.cluster.site is not None:
|
||||
# If the Cluster is assigned to a Site or Location, all Devices must be assigned to that same scope.
|
||||
if self.cluster.scope is not None:
|
||||
for device in self.cleaned_data.get('devices', []):
|
||||
if device.site != self.cluster.site:
|
||||
raise ValidationError({
|
||||
'devices': _(
|
||||
"{device} belongs to a different site ({device_site}) than the cluster ({cluster_site})"
|
||||
).format(
|
||||
device=device,
|
||||
device_site=device.site,
|
||||
cluster_site=self.cluster.site
|
||||
)
|
||||
})
|
||||
for scope_field in ['site', 'location']:
|
||||
device_scope = getattr(device, scope_field)
|
||||
if (
|
||||
self.cluster.scope_type.model_class() == apps.get_model('dcim', scope_field)
|
||||
and device_scope != self.cluster.scope
|
||||
):
|
||||
raise ValidationError({
|
||||
'devices': _(
|
||||
"{device} belongs to a different {scope_field} ({device_scope}) than the "
|
||||
"cluster ({cluster_scope})"
|
||||
).format(
|
||||
device=device,
|
||||
scope_field=scope_field,
|
||||
device_scope=device_scope,
|
||||
cluster_scope=self.cluster.scope
|
||||
)
|
||||
})
|
||||
|
||||
|
||||
class ClusterRemoveDevicesForm(ConfirmationForm):
|
||||
|
||||
@@ -78,7 +78,8 @@ class ClusterTable(TenancyColumnsMixin, ContactsColumnMixin, NetBoxTable):
|
||||
)
|
||||
scope = tables.Column(
|
||||
verbose_name=_('Scope'),
|
||||
linkify=True
|
||||
linkify=True,
|
||||
orderable=False
|
||||
)
|
||||
device_count = columns.LinkedCountColumn(
|
||||
viewname='dcim:device_list',
|
||||
|
||||
@@ -56,7 +56,8 @@ class WirelessLANTable(TenancyColumnsMixin, NetBoxTable):
|
||||
)
|
||||
scope = tables.Column(
|
||||
verbose_name=_('Scope'),
|
||||
linkify=True
|
||||
linkify=True,
|
||||
orderable=False
|
||||
)
|
||||
interface_count = tables.Column(
|
||||
verbose_name=_('Interfaces')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Django==5.1.4
|
||||
Django==5.1.5
|
||||
django-cors-headers==4.6.0
|
||||
django-debug-toolbar==4.4.6
|
||||
django-debug-toolbar==5.0.1
|
||||
django-filter==24.3
|
||||
django-htmx==1.21.0
|
||||
django-graphiql-debug-toolbar==0.2.0
|
||||
@@ -12,7 +12,7 @@ django-rich==1.13.0
|
||||
django-rq==3.0
|
||||
django-taggit==6.1.0
|
||||
django-tables2==2.7.5
|
||||
django-timezone-field==7.0
|
||||
django-timezone-field==7.1
|
||||
djangorestframework==3.15.2
|
||||
drf-spectacular==0.28.0
|
||||
drf-spectacular-sidecar==2024.12.1
|
||||
@@ -25,13 +25,13 @@ mkdocstrings[python-legacy]==0.27.0
|
||||
netaddr==1.3.0
|
||||
nh3==0.2.20
|
||||
Pillow==11.1.0
|
||||
psycopg[c,pool]==3.2.3
|
||||
psycopg[c,pool]==3.2.4
|
||||
PyYAML==6.0.2
|
||||
requests==2.32.3
|
||||
rq==2.1.0
|
||||
social-auth-app-django==5.4.2
|
||||
social-auth-core==4.5.4
|
||||
strawberry-graphql==0.256.1
|
||||
strawberry-graphql==0.258.0
|
||||
strawberry-graphql-django==0.52.0
|
||||
svgwrite==1.4.3
|
||||
tablib==3.7.0
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
#!/bin/sh
|
||||
# Create a link to this file at .git/hooks/pre-commit to
|
||||
# force PEP8 validation prior to committing
|
||||
#
|
||||
# Ignored violations:
|
||||
#
|
||||
# W504: Line break after binary operator
|
||||
# E501: Line too long
|
||||
# TODO: Remove this file in NetBox v4.3
|
||||
# This script has been maintained to ease transition to the pre-commit tool.
|
||||
|
||||
exec 1>&2
|
||||
|
||||
@@ -14,48 +9,8 @@ RED='\033[0;31m'
|
||||
YELLOW='\033[0;33m'
|
||||
NOCOLOR='\033[0m'
|
||||
|
||||
printf "${YELLOW}This script is obsolete and will be removed in a future release.\n"
|
||||
printf "Please use pre-commit instead:\n"
|
||||
printf "${YELLOW}The pre-commit hook script is obsolete. Please use pre-commit instead:${NOCOLOR}\n"
|
||||
printf " pip install pre-commit\n"
|
||||
printf " pre-commit install${NOCOLOR}\n"
|
||||
|
||||
if [ -d ./venv/ ]; then
|
||||
VENV="$PWD/venv"
|
||||
if [ -e $VENV/bin/python ]; then
|
||||
PATH=$VENV/bin:$PATH
|
||||
elif [ -e $VENV/Scripts/python.exe ]; then
|
||||
PATH=$VENV/Scripts:$PATH
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ${NOVALIDATE} ]; then
|
||||
echo "${YELLOW}Skipping validation checks${NOCOLOR}"
|
||||
exit $EXIT
|
||||
fi
|
||||
|
||||
echo "Linting with ruff..."
|
||||
ruff check netbox/
|
||||
if [ $? != 0 ]; then
|
||||
EXIT=1
|
||||
fi
|
||||
|
||||
echo "Checking for missing migrations..."
|
||||
python netbox/manage.py makemigrations --dry-run --check
|
||||
if [ $? != 0 ]; then
|
||||
EXIT=1
|
||||
fi
|
||||
|
||||
git diff --cached --name-only | if grep --quiet 'netbox/project-static/'
|
||||
then
|
||||
echo "Checking UI ESLint, TypeScript, and Prettier compliance..."
|
||||
yarn --cwd "$PWD/netbox/project-static" validate
|
||||
if [ $? != 0 ]; then
|
||||
EXIT=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ $EXIT != 0 ]; then
|
||||
printf "${RED}COMMIT FAILED${NOCOLOR}\n"
|
||||
fi
|
||||
|
||||
exit $EXIT
|
||||
exit 1
|
||||
|
||||
Reference in New Issue
Block a user