Skip to content

Release v3.0.1 #7130

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

Merged
merged 46 commits into from
Sep 1, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
deb53d7
Fixes #7070: Fix exception when filtering by prefix max length in UI
jeremystretch Aug 30, 2021
88b230f
Fixes #7071: Fix exception when removing a primary IP from a device/VM
jeremystretch Aug 30, 2021
bf05bc2
#7070: Fix filterset test
jeremystretch Aug 30, 2021
db29930
Fixes #7075: Wrap label selectors in quotes to ensure IDs with spaces…
thatmattlove Aug 31, 2021
4f36885
Fixes #7096: Home links should honor BASE_PATH configuration
jeremystretch Aug 31, 2021
3090981
Fixes #7084: Fix KeyError exception when editing access VLAN on an in…
jeremystretch Aug 31, 2021
65c9339
Fixes #7083: Correct labeling for VM memory attribute
jeremystretch Aug 31, 2021
8036d1e
Fixes #7078: Restore styling on server error page
jeremystretch Aug 31, 2021
7db2b9d
Fixes #7072: Fix table configuration under prefix child object views
jeremystretch Aug 31, 2021
415313a
Fixes #7082: Avoid exception when referencing invalid content type in…
jeremystretch Aug 31, 2021
7b7b01a
Changelog for #7075
jeremystretch Aug 31, 2021
86da6c6
Fixes #7089 - Adds Q filter to ContentTypeFilterSet
DanSheps Aug 31, 2021
c4c6fa6
Fix misplacement of method for #7089
DanSheps Aug 31, 2021
1c09ffd
Fixes #7101: Enforce MAX_PAGE_SIZE for table and REST API pagination
jeremystretch Aug 31, 2021
349733c
Redirect users on error to the GitHub discussion forum
candlerb Aug 31, 2021
a8cdb38
Fixes #7093: Multi-select custom field filters should employ exact match
jeremystretch Aug 31, 2021
840ea36
Merge pull request #7103 from candlerb/candlerb/7102
jeremystretch Aug 31, 2021
1909f0c
Fix #7090: Cable Bulk Edit, length field should be decimal
sdktr Aug 31, 2021
4618cc2
Merge branch 'develop' of github.com:netbox-community/netbox into 709…
sdktr Aug 31, 2021
f1e4273
Changelog for #7090
sdktr Aug 31, 2021
9c389d9
Changelog #7090 fix whitespace
sdktr Aug 31, 2021
515b6bf
Merge pull request #7105 from sdktr/7090-fix-cablebulkedit-length-field
jeremystretch Aug 31, 2021
679bbd3
Fixes #7091: Ensure API requests from the UI are aware of `BASE_PATH`
thatmattlove Aug 31, 2021
5b87232
#7081: Fix APISelect loading of paginated data
thatmattlove Aug 31, 2021
093a86b
Fixes #7081: Properly handle pre-selected values even when they're ou…
thatmattlove Aug 31, 2021
5235866
Changelog for #7081, #7091
thatmattlove Aug 31, 2021
b95e835
Fixes #7092: Fix missing object permissions on Prefix IP Addresses view
thatmattlove Aug 31, 2021
2b263b0
Fixes #7106: Fix incorrect "Map It" button URL on a site's Physical A…
thatmattlove Aug 31, 2021
d743dc1
Fixes #7080: Re-add missing image preview element
thatmattlove Sep 1, 2021
14d87a3
Fixes #7041: Properly format JSON config object returned from a NAPAL…
thatmattlove Sep 1, 2021
691c66d
Fixes #7107: Fix missing search button and search results in IP Addre…
thatmattlove Sep 1, 2021
a33e477
Remove legacy script tags from templates
thatmattlove Sep 1, 2021
20ef18f
Fixes #7113: Add permissions to IPRanges bulk actions within Prefix view
sdktr Sep 1, 2021
909d127
Fixes #7113: Correct links to IPRanges bulk actions within Prefix view
sdktr Sep 1, 2021
6f66b27
Changelog for #7113
sdktr Sep 1, 2021
f63dcb1
#7091: Simplify access to BASE_PATH variable
jeremystretch Sep 1, 2021
d2fe59a
Fixes #7109: Ensure human readability of exceptions raised during RES…
jeremystretch Sep 1, 2021
9772c57
Merge branch 'develop' into 7113-fix-prefix-iprange-bulkedit
jeremystretch Sep 1, 2021
29eb238
Merge pull request #7115 from sdktr/7113-fix-prefix-iprange-bulkedit
jeremystretch Sep 1, 2021
662c896
#7113: Add bulk actions under child prefixes view; general cleanup
jeremystretch Sep 1, 2021
528df76
#7082: Handle stale content types
jeremystretch Sep 1, 2021
707e51d
#7084: Catch ValueErrors when initializing dynamic form fields
jeremystretch Sep 1, 2021
6f94198
#7123: Remove "Global" placeholder for null VRF field
jeremystretch Sep 1, 2021
a2eb0d8
#7084: Fix issue where hidden VLAN form fields were incorrectly inclu…
thatmattlove Sep 1, 2021
7bdde47
Fixes #7124: Fix duplicate static query param values in API Select
thatmattlove Sep 1, 2021
b207f28
Release v3.0.1
jeremystretch Sep 1, 2021
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
Prev Previous commit
Next Next commit
Fixes #7041: Properly format JSON config object returned from a NAPAL…
…M device
  • Loading branch information
thatmattlove committed Sep 1, 2021
commit 14d87a3584c53b20ce0be38aeea92b2307f11355
1 change: 1 addition & 0 deletions docs/release-notes/version-3.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Bug Fixes

* [#7041](https://github.com/netbox-community/netbox/issues/7041) - Properly format JSON config object returned from a NAPALM device
* [#7070](https://github.com/netbox-community/netbox/issues/7070) - Fix exception when filtering by prefix max length in UI
* [#7071](https://github.com/netbox-community/netbox/issues/7071) - Fix exception when removing a primary IP from a device/VM
* [#7072](https://github.com/netbox-community/netbox/issues/7072) - Fix table configuration under prefix child object views
Expand Down
4 changes: 2 additions & 2 deletions netbox/dcim/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from netbox.api.exceptions import ServiceUnavailable
from netbox.api.metadata import ContentTypeMetadata
from utilities.api import get_serializer_for_model
from utilities.utils import count_related
from utilities.utils import count_related, decode_dict
from virtualization.models import VirtualMachine
from . import serializers
from .exceptions import MissingFilterException
Expand Down Expand Up @@ -498,7 +498,7 @@ def napalm(self, request, pk):
response[method] = {'error': 'Only get_* NAPALM methods are supported'}
continue
try:
response[method] = getattr(d, method)()
response[method] = decode_dict(getattr(d, method)())
except NotImplementedError:
response[method] = {'error': 'Method {} not implemented for NAPALM driver {}'.format(method, driver)}
except Exception as e:
Expand Down
4 changes: 2 additions & 2 deletions netbox/project-static/dist/config.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion netbox/project-static/dist/config.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion netbox/project-static/dist/jobs.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion netbox/project-static/dist/lldp.js.map

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions netbox/project-static/dist/netbox.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion netbox/project-static/dist/netbox.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions netbox/project-static/dist/status.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion netbox/project-static/dist/status.js.map

Large diffs are not rendered by default.

20 changes: 14 additions & 6 deletions netbox/project-static/src/device/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,26 @@ function initConfig(): void {
.then(data => {
if (hasError(data)) {
createToast('danger', 'Error Fetching Device Config', data.error).show();
console.error(data.error);
return;
} else if (hasError<Required<DeviceConfig['get_config']>>(data.get_config)) {
createToast('danger', 'Error Fetching Device Config', data.get_config.error).show();
console.error(data.get_config.error);
return;
} else {
const configTypes = [
'running',
'startup',
'candidate',
] as (keyof DeviceConfig['get_config'])[];
const configTypes = ['running', 'startup', 'candidate'] as DeviceConfigType[];

for (const configType of configTypes) {
const element = document.getElementById(`${configType}_config`);
if (element !== null) {
element.innerHTML = data.get_config[configType];
const config = data.get_config[configType];
if (typeof config === 'string') {
// If the returned config is a string, set the element innerHTML as-is.
element.innerHTML = config;
} else {
// If the returned config is an object (dict), convert it to JSON.
element.innerHTML = JSON.stringify(data.get_config[configType], null, 2);
}
}
}
}
Expand Down
9 changes: 6 additions & 3 deletions netbox/project-static/src/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,15 @@ type LLDPNeighborDetail = {

type DeviceConfig = {
get_config: {
candidate: string;
running: string;
startup: string;
candidate: string | Record<string, unknown>;
running: string | Record<string, unknown>;
startup: string | Record<string, unknown>;
error?: string;
};
};

type DeviceConfigType = Exclude<keyof DeviceConfig['get_config'], 'error'>;

type DeviceEnvironment = {
cpu?: {
[core: string]: { '%usage': number };
Expand Down
4 changes: 3 additions & 1 deletion netbox/project-static/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ export function isApiError(data: Record<string, unknown>): data is APIError {
return 'error' in data && 'exception' in data;
}

export function hasError(data: Record<string, unknown>): data is ErrorBase {
export function hasError<E extends ErrorBase = ErrorBase>(
data: Record<string, unknown>,
): data is E {
return 'error' in data;
}

Expand Down
41 changes: 41 additions & 0 deletions netbox/utilities/utils.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import datetime
import json
import urllib
from collections import OrderedDict
from itertools import count, groupby
from typing import Any, Dict, List, Tuple

from django.core.serializers import serialize
from django.db.models import Count, OuterRef, Subquery
Expand Down Expand Up @@ -286,6 +288,45 @@ def flatten_dict(d, prefix='', separator='.'):
return ret


def decode_dict(encoded_dict: Dict, *, decode_keys: bool = True) -> Dict:
"""
Recursively URL decode string keys and values of a dict.

For example, `{'1%2F1%2F1': {'1%2F1%2F2': ['1%2F1%2F3', '1%2F1%2F4']}}` would
become: `{'1/1/1': {'1/1/2': ['1/1/3', '1/1/4']}}`

:param encoded_dict: Dictionary to be decoded.
:param decode_keys: (Optional) Enable/disable decoding of dict keys.
"""

def decode_value(value: Any, _decode_keys: bool) -> Any:
"""
Handle URL decoding of any supported value type.
"""
# Decode string values.
if isinstance(value, str):
return urllib.parse.unquote(value)
# Recursively decode each list item.
elif isinstance(value, list):
return [decode_value(v, _decode_keys) for v in value]
# Recursively decode each tuple item.
elif isinstance(value, Tuple):
return tuple(decode_value(v, _decode_keys) for v in value)
# Recursively decode each dict key/value pair.
elif isinstance(value, dict):
# Don't decode keys, if `decode_keys` is false.
if not _decode_keys:
return {k: decode_value(v, _decode_keys) for k, v in value.items()}
return {urllib.parse.unquote(k): decode_value(v, _decode_keys) for k, v in value.items()}
return value

if not decode_keys:
# Don't decode keys, if `decode_keys` is false.
return {k: decode_value(v, decode_keys) for k, v in encoded_dict.items()}

return {urllib.parse.unquote(k): decode_value(v, decode_keys) for k, v in encoded_dict.items()}


# Taken from django.utils.functional (<3.0)
def curry(_curried_func, *args, **kwargs):
def _curried(*moreargs, **morekwargs):
Expand Down