Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v3.6.8 #14616

Merged
merged 23 commits into from
Dec 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
ec245b9
PRVB
jeremystretch Dec 15, 2023
12beac4
fix the result of script jobs #14549
kprince28 Dec 20, 2023
3f4a65c
added ! to safe characters
Azmodeszer Dec 21, 2023
c1cf037
Print NetBox version in upgrade.sh (#14547)
markkuleinio Dec 21, 2023
8dfec7e
Closes #14538 - Add available_at_site filter (#14541)
DanSheps Dec 21, 2023
f0b9008
Fixes #14575: Fix display of the tags column under VDC table
jeremystretch Dec 21, 2023
e5c565c
Closes #14119: Remove redundant check for to_objectchange()
jeremystretch Dec 21, 2023
1692070
Update search to add note
DanSheps Dec 21, 2023
c289dda
Changelog for #14507, #14538, #14549, #14560, #14575
jeremystretch Dec 21, 2023
0d08205
Fixes #14532: Device/VM change record should accurately reflect when …
jeremystretch Dec 21, 2023
99467e8
Fixes #12731: Support custom validation for many-to-many fields (#14516)
jeremystretch Dec 22, 2023
43909ee
Fixes #13649: Permit zero-length cables
jeremystretch Dec 22, 2023
031b754
Fixes #13741: Update docs to correctly reflect inventory item uniquen…
jeremystretch Dec 26, 2023
634681a
Fixes #13606: Fix filtering by null for multiselect custom fields
jeremystretch Dec 26, 2023
a67236f
Fixes #13812: Record data source sync failure when run via syncdataso…
jeremystretch Dec 26, 2023
e6642b5
Fixes #11816: Detach group/site validation error from group field
jeremystretch Dec 27, 2023
d6c8d15
Closes #11039: List parent prefixes under IP range view
jeremystretch Dec 27, 2023
b955751
Fixes #14517: Ensure reservations tab is always displayed under rack …
jeremystretch Dec 27, 2023
cc0fc03
Changelog for #11039, #11816, #12731, #13606, #13649, #13812, #14532
jeremystretch Dec 27, 2023
8a23756
Closes #14596: Match against description field when searching for dev…
jeremystretch Dec 27, 2023
113c60a
Fixes #13909: Ignore empty choices when populating dynamic choice fie…
jeremystretch Dec 27, 2023
0613e8e
Fixes #14613: Fix display of current configuration parameters
jeremystretch Dec 27, 2023
07da3f6
Release v3.6.8
jeremystretch Dec 27, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ body:
attributes:
label: NetBox Version
description: What version of NetBox are you currently running?
placeholder: v3.6.7
placeholder: v3.6.8
validations:
required: true
- type: dropdown
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/feature_request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ body:
attributes:
label: NetBox version
description: What version of NetBox are you currently running?
placeholder: v3.6.7
placeholder: v3.6.8
validations:
required: true
- type: dropdown
Expand Down
3 changes: 3 additions & 0 deletions docs/features/search.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ When entering a search query, the user can choose a specific lookup type: exact

Custom fields defined by NetBox administrators are also included in search results if configured with a search weight. Additionally, NetBox plugins can register their own custom models for inclusion alongside core models.

!!! note
NetBox does not index any static choice field's (including custom fields of type "Selection" or "Multiple selection").

## Saved Filters

Each type of object in NetBox is accompanied by an extensive set of filters, each tied to a specific attribute, which enable the creation of complex queries. Often you'll find that certain queries are used routinely to apply some set of prescribed conditions to a query. Once a set of filters has been applied, NetBox offers the option to save it for future use.
Expand Down
2 changes: 1 addition & 1 deletion docs/models/dcim/inventoryitem.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ The parent inventory item to which this item is assigned (optional).

### Name

The inventory item's name. Must be unique to the parent device.
The inventory item's name. If the inventory item is assigned to a parent item, its name must be unique among its siblings (all items belonging to the same parent item).

### Label

Expand Down
26 changes: 26 additions & 0 deletions docs/release-notes/version-3.6.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,31 @@
# NetBox v3.6

## v3.6.8 (2023-12-27)

### Enhancements

* [#11039](https://github.com/netbox-community/netbox/issues/11039) - List parent prefixes under IP range view
* [#14507](https://github.com/netbox-community/netbox/issues/14507) - Print new NetBox version when running upgrade script
* [#14538](https://github.com/netbox-community/netbox/issues/14538) - Add the `available_at_site` filter for VLANs
* [#14596](https://github.com/netbox-community/netbox/issues/14596) - Match against description field when searching for devices

### Bug Fixes

* [#11816](https://github.com/netbox-community/netbox/issues/11816) - Correct display of error message when attempting invalid VLAN site & group assignment
* [#12731](https://github.com/netbox-community/netbox/issues/12731) - Fix custom validation for many-to-many fields
* [#13606](https://github.com/netbox-community/netbox/issues/13606) - Fix filtering custom multi-choice fields by null
* [#13649](https://github.com/netbox-community/netbox/issues/13649) - Correct calculation of absolute lengths for zero-length cables
* [#13812](https://github.com/netbox-community/netbox/issues/13812) - Update status of remote data source when syncing fails via `syncdatasource` management command
* [#13909](https://github.com/netbox-community/netbox/issues/13909) - Fix cloning of objects which have a multi-choice custom field
* [#14517](https://github.com/netbox-community/netbox/issues/14517) - Ensure reservations tab is always displayed under rack view
* [#14532](https://github.com/netbox-community/netbox/issues/14532) - Device/VM change record should accurately reflect when primary/OOB IP is deleted
* [#14549](https://github.com/netbox-community/netbox/issues/14549) - Fix association of job results when executing scripts via `runscript` management command
* [#14560](https://github.com/netbox-community/netbox/issues/14560) - Do not escape exclamation marks in custom link URLs
* [#14575](https://github.com/netbox-community/netbox/issues/14575) - Fix display of the tags column under VDC table
* [#14613](https://github.com/netbox-community/netbox/issues/14613) - Fix display of current configuration parameters in UI

---

## v3.6.7 (2023-12-15)

### Enhancements
Expand Down
11 changes: 8 additions & 3 deletions netbox/core/management/commands/syncdatasource.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django.core.management.base import BaseCommand, CommandError

from core.choices import DataSourceStatusChoices
from core.models import DataSource


Expand Down Expand Up @@ -33,9 +34,13 @@ def handle(self, *args, **options):
for i, datasource in enumerate(datasources, start=1):
self.stdout.write(f"[{i}] Syncing {datasource}... ", ending='')
self.stdout.flush()
datasource.sync()
self.stdout.write(datasource.get_status_display())
self.stdout.flush()
try:
datasource.sync()
self.stdout.write(datasource.get_status_display())
self.stdout.flush()
except Exception as e:
DataSource.objects.filter(pk=datasource.pk).update(status=DataSourceStatusChoices.FAILED)
raise e

if len(options['name']) > 1:
self.stdout.write(f"Finished.")
15 changes: 9 additions & 6 deletions netbox/core/views.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.contrib import messages
from django.core.cache import cache
from django.shortcuts import get_object_or_404, redirect

from extras.models import ConfigRevision
Expand Down Expand Up @@ -153,9 +154,11 @@ class ConfigView(generic.ObjectView):
queryset = ConfigRevision.objects.all()

def get_object(self, **kwargs):
if config := self.queryset.first():
return config
# Instantiate a dummy default config if none has been created yet
return ConfigRevision(
data=get_config().defaults
)
revision_id = cache.get('config_version')
try:
return ConfigRevision.objects.get(pk=revision_id)
except ConfigRevision.DoesNotExist:
# Fall back to using the active config data if no record is found
return ConfigRevision(
data=get_config()
)
1 change: 1 addition & 0 deletions netbox/dcim/filtersets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1018,6 +1018,7 @@ def search(self, queryset, name, value):
Q(serial__icontains=value.strip()) |
Q(inventoryitems__serial__icontains=value.strip()) |
Q(asset_tag__icontains=value.strip()) |
Q(description_icontains=value.strip()) |
Q(comments__icontains=value) |
Q(primary_ip4__address__startswith=value) |
Q(primary_ip6__address__startswith=value)
Expand Down
22 changes: 22 additions & 0 deletions netbox/dcim/migrations/0182_zero_length_cable_fix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from django.db import migrations


def update_cable_lengths(apps, schema_editor):
Cable = apps.get_model('dcim', 'Cable')

# Set the absolute length for any zero-length Cables
Cable.objects.filter(length=0).update(_abs_length=0)


class Migration(migrations.Migration):

dependencies = [
('dcim', '0181_rename_device_role_device_role'),
]

operations = [
migrations.RunPython(
code=update_cable_lengths,
reverse_code=migrations.RunPython.noop
),
]
2 changes: 1 addition & 1 deletion netbox/dcim/models/cables.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ def save(self, *args, **kwargs):
_created = self.pk is None

# Store the given length (if any) in meters for use in database ordering
if self.length and self.length_unit:
if self.length is not None and self.length_unit:
self._abs_length = to_meters(self.length, self.length_unit)
else:
self._abs_length = None
Expand Down
4 changes: 2 additions & 2 deletions netbox/dcim/svg/cables.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,7 @@ def draw_cable(self, cable, terminations, cable_count=0):
if cable.type:
# Include the cable type in the tooltip
description.append(cable.get_type_display())
if cable.length and cable.length_unit:
if cable.length is not None and cable.length_unit:
# Include the cable length in the tooltip
description.append(f'{cable.length} {cable.get_length_unit_display()}')
else:
Expand All @@ -285,7 +285,7 @@ def draw_cable(self, cable, terminations, cable_count=0):
description = []
if cable.type:
labels.append(cable.get_type_display())
if cable.length and cable.length_unit:
if cable.length is not None and cable.length_unit:
# Include the cable length in the tooltip
labels.append(f'{cable.length} {cable.get_length_unit_display()}')

Expand Down
2 changes: 1 addition & 1 deletion netbox/dcim/tables/devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -1078,7 +1078,7 @@ class VirtualDeviceContextTable(TenancyColumnsMixin, NetBoxTable):
comments = columns.MarkdownColumn()

tags = columns.TagColumn(
url_name='dcim:vdc_list'
url_name='dcim:virtualdevicecontext_list'
)

class Meta(NetBoxTable.Meta):
Expand Down
3 changes: 1 addition & 2 deletions netbox/dcim/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -695,8 +695,7 @@ class RackRackReservationsView(generic.ObjectChildrenView):
label=_('Reservations'),
badge=lambda obj: obj.reservations.count(),
permission='dcim.view_rackreservation',
weight=510,
hide_if_empty=True
weight=510
)

def get_children(self, request, parent):
Expand Down
2 changes: 1 addition & 1 deletion netbox/extras/management/commands/runscript.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def _run_script():
# Create the job
job = Job.objects.create(
object=module,
name=script.name,
name=script.class_name,
user=User.objects.filter(is_superuser=True).order_by('pk')[0],
job_id=uuid.uuid4()
)
Expand Down
4 changes: 1 addition & 3 deletions netbox/extras/models/customfields.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from django.core.validators import RegexValidator, ValidationError
from django.db import models
from django.urls import reverse
from django.utils.html import escape
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _

Expand Down Expand Up @@ -571,8 +570,7 @@ def to_filter(self, lookup_expr=None):

# Multiselect
elif self.type == CustomFieldTypeChoices.TYPE_MULTISELECT:
filter_class = filters.MultiValueCharFilter
kwargs['lookup_expr'] = 'has_key'
filter_class = filters.MultiValueArrayFilter

# Object
elif self.type == CustomFieldTypeChoices.TYPE_OBJECT:
Expand Down
2 changes: 1 addition & 1 deletion netbox/extras/models/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ def render(self, context):
text = clean_html(text, allowed_schemes)

# Sanitize link
link = urllib.parse.quote(link, safe='/:?&=%+[]@#,;')
link = urllib.parse.quote(link, safe='/:?&=%+[]@#,;!')

# Verify link scheme is allowed
result = urllib.parse.urlparse(link)
Expand Down
29 changes: 14 additions & 15 deletions netbox/extras/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,21 +62,20 @@ def handle_changed_object(sender, instance, **kwargs):
else:
return

# Record an ObjectChange if applicable
if hasattr(instance, 'to_objectchange'):
if m2m_changed:
ObjectChange.objects.filter(
changed_object_type=ContentType.objects.get_for_model(instance),
changed_object_id=instance.pk,
request_id=request.id
).update(
postchange_data=instance.to_objectchange(action).postchange_data
)
else:
objectchange = instance.to_objectchange(action)
objectchange.user = request.user
objectchange.request_id = request.id
objectchange.save()
# Record an ObjectChange
if m2m_changed:
ObjectChange.objects.filter(
changed_object_type=ContentType.objects.get_for_model(instance),
changed_object_id=instance.pk,
request_id=request.id
).update(
postchange_data=instance.to_objectchange(action).postchange_data
)
else:
objectchange = instance.to_objectchange(action)
objectchange.user = request.user
objectchange.request_id = request.id
objectchange.save()

# If this is an M2M change, update the previously queued webhook (from post_save)
queue = webhooks_queue.get()
Expand Down
Loading