Merge v2.11.5

This commit is contained in:
jeremystretch 2021-06-04 09:47:14 -04:00
commit 0e23038e28
12 changed files with 26 additions and 31 deletions

View File

@ -17,7 +17,7 @@ body:
What version of NetBox are you currently running? (If you don't have access to the most What version of NetBox are you currently running? (If you don't have access to the most
recent NetBox release, consider testing on our [demo instance](https://demo.netbox.dev/) recent NetBox release, consider testing on our [demo instance](https://demo.netbox.dev/)
before opening a bug report to see if your issue has already been addressed.) before opening a bug report to see if your issue has already been addressed.)
placeholder: v2.11.4 placeholder: v2.11.5
validations: validations:
required: true required: true
- type: dropdown - type: dropdown

View File

@ -14,7 +14,7 @@ body:
attributes: attributes:
label: NetBox version label: NetBox version
description: What version of NetBox are you currently running? description: What version of NetBox are you currently running?
placeholder: v2.11.4 placeholder: v2.11.5
validations: validations:
required: true required: true
- type: dropdown - type: dropdown

View File

@ -80,7 +80,7 @@ class DeviceConnectionsReport(Report):
self.log_success(device) self.log_success(device)
``` ```
As you can see, reports are completely customizable. Validation logic can be as simple or as complex as needed. As you can see, reports are completely customizable. Validation logic can be as simple or as complex as needed. Also note that the `description` attribute support markdown syntax. It will be rendered in the report list page.
!!! warning !!! warning
Reports should never alter data: If you find yourself using the `create()`, `save()`, `update()`, or `delete()` methods on objects within reports, stop and re-evaluate what you're trying to accomplish. Note that there are no safeguards against the accidental alteration or destruction of data. Reports should never alter data: If you find yourself using the `create()`, `save()`, `update()`, or `delete()` methods on objects within reports, stop and re-evaluate what you're trying to accomplish. Note that there are no safeguards against the accidental alteration or destruction of data.
@ -93,7 +93,7 @@ The following methods are available to log results within a report:
* log_warning(object, message) * log_warning(object, message)
* log_failure(object, message) * log_failure(object, message)
The recording of one or more failure messages will automatically flag a report as failed. It is advised to log a success for each object that is evaluated so that the results will reflect how many objects are being reported on. (The inclusion of a log message is optional for successes.) Messages recorded with `log()` will appear in a report's results but are not associated with a particular object or status. The recording of one or more failure messages will automatically flag a report as failed. It is advised to log a success for each object that is evaluated so that the results will reflect how many objects are being reported on. (The inclusion of a log message is optional for successes.) Messages recorded with `log()` will appear in a report's results but are not associated with a particular object or status. Log messages also support using markdown syntax and will be rendered on the report result page.
To perform additional tasks, such as sending an email or calling a webhook, after a report has been run, extend the `post_run()` method. The status of the report is available as `self.failed` and the results object is `self.result`. To perform additional tasks, such as sending an email or calling a webhook, after a report has been run, extend the `post_run()` method. The status of the report is available as `self.failed` and the results object is `self.result`.

View File

@ -1,12 +1,16 @@
# NetBox v2.11 # NetBox v2.11
## v2.11.5 (FUTURE) ## v2.11.5 (2021-06-04)
**NOTE:** This release includes a database migration that calculates and annotates prefix depth. It may impose a noticeable delay on the upgrade process: Users should anticipate roughly one minute of delay per 100 thousand prefixes being updated.
### Enhancements ### Enhancements
* [#6087](https://github.com/netbox-community/netbox/issues/6087) - Improved prefix hierarchy rendering * [#6087](https://github.com/netbox-community/netbox/issues/6087) - Improved prefix hierarchy rendering
* [#6487](https://github.com/netbox-community/netbox/issues/6487) - Add location filter to cable connection form * [#6487](https://github.com/netbox-community/netbox/issues/6487) - Add location filter to cable connection form
* [#6501](https://github.com/netbox-community/netbox/issues/6501) - Expose prefix depth and children on REST API serializer * [#6501](https://github.com/netbox-community/netbox/issues/6501) - Expose prefix depth and children on REST API serializer
* [#6527](https://github.com/netbox-community/netbox/issues/6527) - Support Markdown for report descriptions
* [#6540](https://github.com/netbox-community/netbox/issues/6540) - Add a "flat" column to the prefix table
### Bug Fixes ### Bug Fixes

View File

@ -273,7 +273,7 @@ class IPAddressSerializer(PrimaryModelSerializer):
) )
assigned_object = serializers.SerializerMethodField(read_only=True) assigned_object = serializers.SerializerMethodField(read_only=True)
nat_inside = NestedIPAddressSerializer(required=False, allow_null=True) nat_inside = NestedIPAddressSerializer(required=False, allow_null=True)
nat_outside = NestedIPAddressSerializer(read_only=True) nat_outside = NestedIPAddressSerializer(required=False, read_only=True)
class Meta: class Meta:
model = IPAddress model = IPAddress
@ -282,7 +282,7 @@ class IPAddressSerializer(PrimaryModelSerializer):
'assigned_object_id', 'assigned_object', 'nat_inside', 'nat_outside', 'dns_name', 'description', 'tags', 'assigned_object_id', 'assigned_object', 'nat_inside', 'nat_outside', 'dns_name', 'description', 'tags',
'custom_fields', 'created', 'last_updated', 'custom_fields', 'created', 'last_updated',
] ]
read_only_fields = ['family'] read_only_fields = ['family', 'nat_outside']
@swagger_serializer_method(serializer_or_field=serializers.DictField) @swagger_serializer_method(serializer_or_field=serializers.DictField)
def get_assigned_object(self, obj): def get_assigned_object(self, obj):

View File

@ -4,17 +4,6 @@ from django.db import migrations
from ipam.utils import rebuild_prefixes from ipam.utils import rebuild_prefixes
def push_to_stack(stack, prefix):
# Increment child count on parent nodes
for n in stack:
n['children'] += 1
stack.append({
'pk': prefix['pk'],
'prefix': prefix['prefix'],
'children': 0,
})
def populate_prefix_hierarchy(apps, schema_editor): def populate_prefix_hierarchy(apps, schema_editor):
""" """
Populate _depth and _children attrs for all Prefixes. Populate _depth and _children attrs for all Prefixes.

View File

@ -277,6 +277,11 @@ class PrefixTable(BaseTable):
template_code=PREFIX_LINK, template_code=PREFIX_LINK,
attrs={'td': {'class': 'text-nowrap'}} attrs={'td': {'class': 'text-nowrap'}}
) )
prefix_flat = tables.Column(
accessor=Accessor('prefix'),
linkify=True,
verbose_name='Prefix (Flat)'
)
depth = tables.Column( depth = tables.Column(
accessor=Accessor('_depth'), accessor=Accessor('_depth'),
verbose_name='Depth' verbose_name='Depth'
@ -318,8 +323,8 @@ class PrefixTable(BaseTable):
class Meta(BaseTable.Meta): class Meta(BaseTable.Meta):
model = Prefix model = Prefix
fields = ( fields = (
'pk', 'prefix', 'status', 'depth', 'children', 'vrf', 'tenant', 'site', 'vlan', 'role', 'is_pool', 'pk', 'prefix', 'prefix_flat', 'status', 'depth', 'children', 'vrf', 'tenant', 'site', 'vlan', 'role',
'mark_utilized', 'description', 'is_pool', 'mark_utilized', 'description',
) )
default_columns = ('pk', 'prefix', 'status', 'vrf', 'tenant', 'site', 'vlan', 'role', 'description') default_columns = ('pk', 'prefix', 'status', 'vrf', 'tenant', 'site', 'vlan', 'role', 'description')
row_attrs = { row_attrs = {
@ -332,15 +337,14 @@ class PrefixDetailTable(PrefixTable):
accessor='get_utilization', accessor='get_utilization',
orderable=False orderable=False
) )
tenant = TenantColumn()
tags = TagColumn( tags = TagColumn(
url_name='ipam:prefix_list' url_name='ipam:prefix_list'
) )
class Meta(PrefixTable.Meta): class Meta(PrefixTable.Meta):
fields = ( fields = (
'pk', 'prefix', 'status', 'children', 'vrf', 'utilization', 'tenant', 'site', 'vlan', 'role', 'is_pool', 'pk', 'prefix', 'prefix_flat', 'status', 'children', 'vrf', 'utilization', 'tenant', 'site', 'vlan', 'role',
'mark_utilized', 'description', 'tags', 'is_pool', 'mark_utilized', 'description', 'tags',
) )
default_columns = ( default_columns = (
'pk', 'prefix', 'status', 'children', 'vrf', 'utilization', 'tenant', 'site', 'vlan', 'role', 'description', 'pk', 'prefix', 'status', 'children', 'vrf', 'utilization', 'tenant', 'site', 'vlan', 'role', 'description',

View File

@ -16,7 +16,7 @@ from django.core.validators import URLValidator
# Environment setup # Environment setup
# #
VERSION = '2.12-beta1' VERSION = '3.0-beta1'
# Hostname # Hostname
HOSTNAME = platform.node() HOSTNAME = platform.node()

View File

@ -774,9 +774,7 @@ class BulkEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
# If we are editing *all* objects in the queryset, replace the PK list with all matched objects. # If we are editing *all* objects in the queryset, replace the PK list with all matched objects.
if request.POST.get('_all') and self.filterset is not None: if request.POST.get('_all') and self.filterset is not None:
pk_list = [ pk_list = self.filterset(request.GET, self.queryset.values_list('pk', flat=True)).qs
obj.pk for obj in self.filterset(request.GET, self.queryset.only('pk')).qs
]
else: else:
pk_list = request.POST.getlist('pk') pk_list = request.POST.getlist('pk')

View File

@ -11,7 +11,7 @@
{% block content %} {% block content %}
{% if report.description %} {% if report.description %}
<p class="text-muted">{{ report.description }}</p> <p class="text-muted">{{ report.description|render_markdown }}</p>
{% endif %} {% endif %}
{% if perms.extras.run_report %} {% if perms.extras.run_report %}
<div class="float-end noprint"> <div class="float-end noprint">

View File

@ -9,7 +9,7 @@
{% if reports %} {% if reports %}
{% for module, module_reports in reports %} {% for module, module_reports in reports %}
<div class="card"> <div class="card">
<h5 class="card-header"><a name="module.{{ module }}"></a>{{ module|bettertitle }}</h3> <h5 class="card-header"><a name="module.{{ module }}"></a>{{ module|bettertitle }}</h5>
<div class="card-body"> <div class="card-body">
<table class="table table-hover table-headings reports"> <table class="table table-hover table-headings reports">
<thead> <thead>
@ -32,7 +32,7 @@
<td> <td>
{% include 'extras/inc/job_label.html' with result=report.result %} {% include 'extras/inc/job_label.html' with result=report.result %}
</td> </td>
<td>{{ report.description|placeholder }}</td> <td>{{ report.description|render_markdown|placeholder }}</td>
<td class="text-end"> <td class="text-end">
{% if report.result %} {% if report.result %}
<a href="{% url 'extras:report_result' job_result_pk=report.result.pk %}">{{ report.result.created }}</a> <a href="{% url 'extras:report_result' job_result_pk=report.result.pk %}">{{ report.result.created }}</a>

View File

@ -1,4 +1,4 @@
Django==3.2.3 Django==3.2.4
django-cacheops==6.0 django-cacheops==6.0
django-cors-headers==3.7.0 django-cors-headers==3.7.0
django-debug-toolbar==3.2.1 django-debug-toolbar==3.2.1