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.4.5 #11793

Merged
merged 38 commits into from
Feb 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
7ebfa4c
PRVB
jeremystretch Feb 2, 2023
5e1bb20
Display login message as success
jeremystretch Feb 7, 2023
edbd597
Update housekeeping command docs
jeremystretch Feb 7, 2023
3f28d6a
Add step for creating search index
jeremystretch Feb 7, 2023
56c7a23
Fixes #11683: Fix CSV header attribute detection when auto-detecting …
jeremystretch Feb 7, 2023
91705aa
Fixes #11032 - Replication fields broken in custom validation (#11698)
kkthxbye-code Feb 8, 2023
3c970c3
Fixes #11582: Fix missing VC form errors
Feb 8, 2023
f923728
Fixes #11601 - Add partial lookup to IPRangeFilterSet
Feb 8, 2023
b5da383
Changelog for #11032, #11582, #11601
jeremystretch Feb 8, 2023
df499ea
Fixes #11459 - Allow using null in conditions (#11722)
kkthxbye-code Feb 13, 2023
d748851
Fixes #11711 - Use CSVModelMultipleChoiceField when importing custom …
kkthxbye-code Feb 13, 2023
9f91b89
#11711: Use CSVModelChoiceField for custom object fields during CSV i…
jeremystretch Feb 13, 2023
3150c1f
Changelog for #11459, #11711
jeremystretch Feb 13, 2023
c78022a
Change the way we invalidate the module cache to support reloading co…
kkthxbye-code Feb 16, 2023
9594049
Fixes #11473 graphql invalid tag filter returns all devices/interfaces
aronminn Feb 14, 2023
eee1a0e
change empty list to qs.none()
Feb 16, 2023
2db181e
Closes #11592: Expose FILE_UPLOAD_MAX_MEMORY_SIZE as a setting (#11742)
aronbergurj99 Feb 16, 2023
3a4fee4
Changelog for #11226, #11335, #11473, #11592
jeremystretch Feb 17, 2023
c36e7a1
Update introduction doc
jeremystretch Feb 17, 2023
c031951
Closes #11110: Add start_address and end_address filters for IP ranges
jeremystretch Feb 17, 2023
126f9ba
Raise stale timers from 60/30 to 90/30
jeremystretch Feb 17, 2023
afc752b
Fixes #11723: Circuit terminations should link to their associated ci…
jeremystretch Feb 18, 2023
315371b
Fixes #11786: List only applicable object types in form widget when f…
jeremystretch Feb 19, 2023
ce166b1
Proof of concept for showing containing prefixes when searching for i…
Feb 6, 2023
a61e7e7
Fix typo in search query
kkthxbye-code Feb 6, 2023
eed1b8f
Create CachedValueField to contain search specific lookups
kkthxbye-code Feb 7, 2023
18ea7d1
pep8 fixes
kkthxbye-code Feb 7, 2023
fc7cb10
Address feedback
kkthxbye-code Feb 18, 2023
25278be
Change Prefix and Aggregate search index weights to better order sear…
kkthxbye-code Feb 18, 2023
9efc468
Changelog for #11685
jeremystretch Feb 19, 2023
e635e3e
Fixes #11658: Remove reindex command call from search migration
jeremystretch Feb 19, 2023
cd09501
#11685: Omit no-op migration
jeremystretch Feb 20, 2023
0855ff8
Skip clearing cache when handling new objects
jeremystretch Feb 18, 2023
3e946c7
#11685: Clear cached search records for relevant IPAM objects
jeremystretch Feb 20, 2023
5a4d8a7
Closes #11787: Rebuild any missing search cache entires after upgrade
jeremystretch Feb 20, 2023
972ba7b
#11685: Fix migration
jeremystretch Feb 20, 2023
3586cf7
Arrange parameters alphabetically
jeremystretch Feb 21, 2023
c280ca3
Release v3.4.5
jeremystretch Feb 21, 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 @@ -14,7 +14,7 @@ body:
attributes:
label: NetBox version
description: What version of NetBox are you currently running?
placeholder: v3.4.4
placeholder: v3.4.5
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.4.4
placeholder: v3.4.5
validations:
required: true
- type: dropdown
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/stale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
necessary.
close-pr-message: >
This PR has been automatically closed due to lack of activity.
days-before-stale: 60
days-before-stale: 90
days-before-close: 30
exempt-issue-labels: 'status: accepted,status: blocked,status: needs milestone'
operations-per-run: 100
Expand Down
1 change: 1 addition & 0 deletions docs/administration/housekeeping.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ NetBox includes a `housekeeping` management command that should be run nightly.
* Clearing expired authentication sessions from the database
* Deleting changelog records older than the configured [retention time](../configuration/miscellaneous.md#changelog_retention)
* Deleting job result records older than the configured [retention time](../configuration/miscellaneous.md#jobresult_retention)
* Check for new NetBox releases (if [`RELEASE_CHECK_URL`](../configuration/miscellaneous.md#release_check_url) is set)

This command can be invoked directly, or by using the shell script provided at `/opt/netbox/contrib/netbox-housekeeping.sh`. This script can be linked from your cron scheduler's daily jobs directory (e.g. `/etc/cron.daily`) or referenced directly within the cron configuration file.

Expand Down
8 changes: 8 additions & 0 deletions docs/configuration/miscellaneous.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ By default, NetBox will permit users to create duplicate prefixes and IP address

---

## `FILE_UPLOAD_MAX_MEMORY_SIZE`

Default: `2621440` (2.5 MB).

The maximum amount (in bytes) of uploaded data that will be held in memory before being written to the filesystem. Changing this setting can be useful for example to be able to upload files bigger than 2.5MB to custom scripts for processing.

---

## GRAPHQL_ENABLED

!!! tip "Dynamic Configuration Parameter"
Expand Down
16 changes: 10 additions & 6 deletions docs/development/adding-models.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,19 @@ Each model should have a corresponding FilterSet class defined. This is used to

Create a table class for the model in `tables.py` by subclassing `utilities.tables.BaseTable`. Under the table's `Meta` class, be sure to list both the fields and default columns.

## 9. Create the object template
## 9. Create a SearchIndex subclass

If this model will be included in global search results, create a subclass of `netbox.search.SearchIndex` for it and specify the fields to be indexed.

## 10. Create the object template

Create the HTML template for the object view. (The other views each typically employ a generic template.) This template should extend `generic/object.html`.

## 10. Add the model to the navigation menu
## 11. Add the model to the navigation menu

Add the relevant navigation menu items in `netbox/netbox/navigation/menu.py`.

## 11. REST API components
## 12. REST API components

Create the following for each model:

Expand All @@ -71,21 +75,21 @@ Create the following for each model:
* API view in `api/views.py`
* Endpoint route in `api/urls.py`

## 12. GraphQL API components
## 13. GraphQL API components

Create a Graphene object type for the model in `graphql/types.py` by subclassing the appropriate class from `netbox.graphql.types`.

Also extend the schema class defined in `graphql/schema.py` with the individual object and object list fields per the established convention.

## 13. Add tests
## 14. Add tests

Add tests for the following:

* UI views
* API views
* Filter sets

## 14. Documentation
## 15. Documentation

Create a new documentation page for the model in `docs/models/<app_label>/<model_name>.md`. Include this file under the "features" documentation where appropriate.

Expand Down
6 changes: 4 additions & 2 deletions docs/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

NetBox was originally developed by its lead maintainer, [Jeremy Stretch](https://github.com/jeremystretch), while he was working as a network engineer at [DigitalOcean](https://www.digitalocean.com/) in 2015 as part of an effort to automate their network provisioning. Recognizing the new tool's potential, DigitalOcean agreed to release it as an open source project in June 2016.

Since then, thousands of organizations around the world have embraced NetBox as their central network source of truth to empower both network operators and automation.
Since then, thousands of organizations around the world have embraced NetBox as their central network source of truth to empower both network operators and automation. Today, the open source project is stewarded by [NetBox Labs](https://netboxlabs.com/) and a team of volunteer maintainers. Beyond the core product, myriad [plugins](https://netbox.dev/plugins/) have been developed by the NetBox community to enhance and expand its feature set.

## Key Features

Expand All @@ -17,6 +17,7 @@ NetBox was built specifically to serve the needs of network engineers and operat
* AS number (ASN) management
* Rack elevations with SVG rendering
* Device modeling using pre-defined types
* Virtual chassis and device contexts
* Network, power, and console cabling with SVG traces
* Power distribution modeling
* Data circuit and provider tracking
Expand All @@ -29,12 +30,13 @@ NetBox was built specifically to serve the needs of network engineers and operat
* Tenant ownership assignment
* Device & VM configuration contexts for advanced configuration rendering
* Custom fields for data model extension
* Support for custom validation rules
* Custom validation rules
* Custom reports & scripts executable directly within the UI
* Extensive plugin framework for adding custom functionality
* Single sign-on (SSO) authentication
* Robust object-based permissions
* Detailed, automatic change logging
* Global search engine
* NAPALM integration

## What NetBox Is Not
Expand Down
6 changes: 3 additions & 3 deletions docs/reference/conditions.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ Multiple conditions can be combined into nested sets using AND or OR logic. This

### Examples

`status` is "active" and `primary_ip` is defined _or_ the "exempt" tag is applied.
`status` is "active" and `primary_ip4` is defined _or_ the "exempt" tag is applied.

```json
{
Expand All @@ -109,8 +109,8 @@ Multiple conditions can be combined into nested sets using AND or OR logic. This
"value": "active"
},
{
"attr": "primary_ip",
"value": "",
"attr": "primary_ip4",
"value": null,
"negate": true
}
]
Expand Down
25 changes: 25 additions & 0 deletions docs/release-notes/version-3.4.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,30 @@
# NetBox v3.4

## v3.4.5 (2023-02-21)

### Enhancements

* [#11110](https://github.com/netbox-community/netbox/issues/11110) - Add `start_address` and `end_address` filters for IP ranges
* [#11592](https://github.com/netbox-community/netbox/issues/11592) - Introduce `FILE_UPLOAD_MAX_MEMORY_SIZE` configuration parameter
* [#11685](https://github.com/netbox-community/netbox/issues/11685) - Match on containing prefixes and aggregates when querying for IP addresses using global search
* [#11787](https://github.com/netbox-community/netbox/issues/11787) - Upgrade script will automatically rebuild missing search cache

### Bug Fixes

* [#11032](https://github.com/netbox-community/netbox/issues/11032) - Fix false custom validation errors during component creation
* [#11226](https://github.com/netbox-community/netbox/issues/11226) - Ensure scripts and reports within submodules are automatically reloaded
* [#11459](https://github.com/netbox-community/netbox/issues/11459) - Enable evaluating null values in custom validation rules
* [#11473](https://github.com/netbox-community/netbox/issues/11473) - GraphQL requests specifying an invalid filter should return an empty queryset
* [#11582](https://github.com/netbox-community/netbox/issues/11582) - Ensure form validation errors are displayed when adding virtual chassis members
* [#11601](https://github.com/netbox-community/netbox/issues/11601) - Fix partial matching of start/end addresses for IP range search
* [#11683](https://github.com/netbox-community/netbox/issues/11683) - Fix CSV header attribute detection when auto-detecting import format
* [#11711](https://github.com/netbox-community/netbox/issues/11711) - Fix CSV import for multiple-object custom fields
* [#11723](https://github.com/netbox-community/netbox/issues/11723) - Circuit terminations should link to their associated circuits (rather than site or provider network)
* [#11775](https://github.com/netbox-community/netbox/issues/11775) - Skip checking for old search cache records when creating a new object
* [#11786](https://github.com/netbox-community/netbox/issues/11786) - List only applicable object types in form widget when filtering custom fields

---

## v3.4.4 (2023-02-02)

### Enhancements
Expand Down
6 changes: 2 additions & 4 deletions netbox/circuits/models/circuits.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,10 @@ class Meta:
)

def __str__(self):
return f'Termination {self.term_side}: {self.site or self.provider_network}'
return f'{self.circuit}: Termination {self.term_side}'

def get_absolute_url(self):
if self.site:
return self.site.get_absolute_url()
return self.provider_network.get_absolute_url()
return self.circuit.get_absolute_url()

def clean(self):
super().clean()
Expand Down
3 changes: 2 additions & 1 deletion netbox/extras/conditions.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ class Condition:
bool: (EQ, CONTAINS),
int: (EQ, GT, GTE, LT, LTE, CONTAINS),
float: (EQ, GT, GTE, LT, LTE, CONTAINS),
list: (EQ, IN, CONTAINS)
list: (EQ, IN, CONTAINS),
type(None): (EQ,)
}

def __init__(self, attr, value, op=EQ, negate=False):
Expand Down
8 changes: 8 additions & 0 deletions netbox/extras/fields.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from django.db.models import TextField


class CachedValueField(TextField):
"""
Currently a dummy field to prevent custom lookups being applied globally to TextField.
"""
pass
18 changes: 6 additions & 12 deletions netbox/extras/forms/filtersets.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,7 @@ class CustomFieldFilterForm(SavedFiltersMixin, FilterForm):
('Attributes', ('type', 'content_type_id', 'group_name', 'weight', 'required', 'ui_visibility')),
)
content_type_id = ContentTypeMultipleChoiceField(
queryset=ContentType.objects.all(),
limit_choices_to=FeatureQuery('custom_fields'),
queryset=ContentType.objects.filter(FeatureQuery('custom_fields').get_query()),
required=False,
label=_('Object type')
)
Expand Down Expand Up @@ -79,8 +78,7 @@ class JobResultFilterForm(SavedFiltersMixin, FilterForm):
)
obj_type = ContentTypeChoiceField(
label=_('Object Type'),
queryset=ContentType.objects.all(),
limit_choices_to=FeatureQuery('job_results'), # TODO: This doesn't actually work
queryset=ContentType.objects.filter(FeatureQuery('job_results').get_query()),
required=False,
)
status = MultipleChoiceField(
Expand Down Expand Up @@ -135,8 +133,7 @@ class CustomLinkFilterForm(SavedFiltersMixin, FilterForm):
('Attributes', ('content_types', 'enabled', 'new_window', 'weight')),
)
content_types = ContentTypeMultipleChoiceField(
queryset=ContentType.objects.all(),
limit_choices_to=FeatureQuery('custom_links'),
queryset=ContentType.objects.filter(FeatureQuery('custom_links').get_query()),
required=False
)
enabled = forms.NullBooleanField(
Expand All @@ -162,8 +159,7 @@ class ExportTemplateFilterForm(SavedFiltersMixin, FilterForm):
('Attributes', ('content_types', 'mime_type', 'file_extension', 'as_attachment')),
)
content_types = ContentTypeMultipleChoiceField(
queryset=ContentType.objects.all(),
limit_choices_to=FeatureQuery('export_templates'),
queryset=ContentType.objects.filter(FeatureQuery('export_templates').get_query()),
required=False
)
mime_type = forms.CharField(
Expand All @@ -187,8 +183,7 @@ class SavedFilterFilterForm(SavedFiltersMixin, FilterForm):
('Attributes', ('content_types', 'enabled', 'shared', 'weight')),
)
content_types = ContentTypeMultipleChoiceField(
queryset=ContentType.objects.all(),
limit_choices_to=FeatureQuery('export_templates'),
queryset=ContentType.objects.filter(FeatureQuery('export_templates').get_query()),
required=False
)
enabled = forms.NullBooleanField(
Expand All @@ -215,8 +210,7 @@ class WebhookFilterForm(SavedFiltersMixin, FilterForm):
('Events', ('type_create', 'type_update', 'type_delete')),
)
content_type_id = ContentTypeMultipleChoiceField(
queryset=ContentType.objects.all(),
limit_choices_to=FeatureQuery('webhooks'),
queryset=ContentType.objects.filter(FeatureQuery('webhooks').get_query()),
required=False,
label=_('Object type')
)
Expand Down
17 changes: 16 additions & 1 deletion netbox/extras/lookups.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django.db.models import CharField, Lookup
from django.db.models import CharField, TextField, Lookup
from .fields import CachedValueField


class Empty(Lookup):
Expand All @@ -14,4 +15,18 @@ def as_sql(self, qn, connection):
return 'CAST(LENGTH(%s) AS BOOLEAN) != %s' % (lhs, rhs), params


class NetContainsOrEquals(Lookup):
"""
This lookup has the same functionality as the one from the ipam app except lhs is cast to inet
"""
lookup_name = 'net_contains_or_equals'

def as_sql(self, qn, connection):
lhs, lhs_params = self.process_lhs(qn, connection)
rhs, rhs_params = self.process_rhs(qn, connection)
params = lhs_params + rhs_params
return 'CAST(%s AS INET) >>= %s' % (lhs, rhs), params


CharField.register_lookup(Empty)
CachedValueField.register_lookup(NetContainsOrEquals)
2 changes: 1 addition & 1 deletion netbox/extras/management/commands/housekeeping.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def handle(self, *args, **options):
f"clearing sessions; skipping."
)

# Delete expired ObjectRecords
# Delete expired ObjectChanges
if options['verbosity']:
self.stdout.write("[*] Checking for expired changelog records")
if config.CHANGELOG_RETENTION:
Expand Down
31 changes: 22 additions & 9 deletions netbox/extras/management/commands/reindex.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ def add_arguments(self, parser):
nargs='*',
help='One or more apps or models to reindex',
)
parser.add_argument(
'--lazy',
action='store_true',
help="For each model, reindex objects only if no cache entries already exist"
)

def _get_indexers(self, *model_names):
indexers = {}
Expand Down Expand Up @@ -60,14 +65,15 @@ def handle(self, *model_labels, **kwargs):
raise CommandError("No indexers found!")
self.stdout.write(f'Reindexing {len(indexers)} models.')

# Clear all cached values for the specified models
self.stdout.write('Clearing cached values... ', ending='')
self.stdout.flush()
content_types = [
ContentType.objects.get_for_model(model) for model in indexers.keys()
]
deleted_count = search_backend.clear(content_types)
self.stdout.write(f'{deleted_count} entries deleted.')
# Clear all cached values for the specified models (if not being lazy)
if not kwargs['lazy']:
self.stdout.write('Clearing cached values... ', ending='')
self.stdout.flush()
content_types = [
ContentType.objects.get_for_model(model) for model in indexers.keys()
]
deleted_count = search_backend.clear(content_types)
self.stdout.write(f'{deleted_count} entries deleted.')

# Index models
self.stdout.write('Indexing models')
Expand All @@ -76,11 +82,18 @@ def handle(self, *model_labels, **kwargs):
model_name = model._meta.model_name
self.stdout.write(f' {app_label}.{model_name}... ', ending='')
self.stdout.flush()

if kwargs['lazy']:
content_type = ContentType.objects.get_for_model(model)
if cached_count := search_backend.count(object_types=[content_type]):
self.stdout.write(f'Skipping (found {cached_count} existing).')
continue

i = search_backend.cache(model.objects.iterator(), remove_existing=False)
if i:
self.stdout.write(f'{i} entries cached.')
else:
self.stdout.write(f'None found.')
self.stdout.write(f'No objects found.')

msg = f'Completed.'
if total_count := search_backend.size:
Expand Down
Loading