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 v4.0.1 #16072

Merged
merged 35 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
fbcec97
PRVB
jeremystretch May 6, 2024
d759274
Update supported Python versions for v4.0
jeremystretch May 6, 2024
b4486b4
Fix #15992: Removed integrations for sentry-sdk
tobiasge May 7, 2024
acc2add
Fixes #15977: Hide all admin menu items for non-authenticated users (…
jeremystretch May 7, 2024
9316f48
Fixes #15982: Restore the "assign IP" tab
jeremystretch May 7, 2024
ccf3224
Fixes #16003: Enable cache busting on upgrade for setmode.js
jeremystretch May 7, 2024
4d40699
Fixes #15995: Permit nullable fields referenced by unique constraints…
jeremystretch May 7, 2024
a9a012d
Fixes #16011: Fix site tenant assignment by PK via REST API
jeremystretch May 7, 2024
195dbae
Fixes #16017: Bump Django to 5.0.6
jeremystretch May 8, 2024
db82363
Fixes #16027: Correct typo in error message
grncbg May 8, 2024
b87d1ec
Fixes #16016: Correct typo
jeremystretch May 8, 2024
5c5c0e1
Fixes #16032: Specify the WSGI module to load in uwsgi.ini
markkuleinio May 8, 2024
ff8dabe
Fixes #16025: Fix execution of scripts via the runscript management c…
jeremystretch May 8, 2024
5c68fc9
Fixes #16020: Include Python version on system UI view
jeremystretch May 8, 2024
0df3787
16031 make script result message display markdown
arthanson May 8, 2024
313b6e6
Remove duplicate column definition from ReportResultsTable
jeremystretch May 8, 2024
d7f652b
Closes #16034: Disable uWSGI logging
markkuleinio May 8, 2024
d7d97b1
Return an empty dict if the module cannot be loaded
DanSheps May 8, 2024
6ff349d
Putting field labels above fields
altf4arnold May 7, 2024
6e658d4
#15999: Additional cleanup
jeremystretch May 8, 2024
56ea7b8
16014 Update incorrect django-graphene reference and add link to filt…
arthanson May 8, 2024
0cc2963
Closes #16043: Add 'die-on-term = true' to fix stopping uWSGI (#16045)
markkuleinio May 8, 2024
1a56e8e
15148 add copy button to config context (#15954)
arthanson May 9, 2024
f40fb6a
Fixes #16051: Wrap empty_text with gettext_lazy()
grncbg May 9, 2024
e055e0a
Fixes #15968: Avoid resizing quick search field to display clear button
jeremystretch May 8, 2024
9f94015
Closes #16010: Enable Prometheus middleware only if metrics are enabled
jeremystretch May 8, 2024
2a06e19
Closes #16056: Add binary-path configuration in uwsgi.ini
markkuleinio May 9, 2024
08923d7
adds vms tab on device object view #15328
abhi1693 May 9, 2024
a953ff2
15973 fix switch type on cable edit (#16049)
arthanson May 9, 2024
e438ddb
Adds 2.5 and 10g (#16068)
abhi1693 May 9, 2024
9d4932b
Fixes #16061: Omit hidden fields from event rule form
jeremystretch May 9, 2024
8d11f8a
14121 update plugin development docs for pyproject.toml (#15952)
arthanson May 9, 2024
d847f02
Correct link
jeremystretch May 9, 2024
9cd0a0d
Release v4.0.1
jeremystretch May 9, 2024
ab62f41
Merge branch 'master' into develop
jeremystretch May 9, 2024
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
5 changes: 2 additions & 3 deletions .github/ISSUE_TEMPLATE/bug_report.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,17 @@ body:
attributes:
label: NetBox Version
description: What version of NetBox are you currently running?
placeholder: v4.0.0
placeholder: v4.0.1
validations:
required: true
- type: dropdown
attributes:
label: Python Version
description: What version of Python are you currently running?
options:
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12"
validations:
required: true
- type: textarea
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: v4.0.0
placeholder: v4.0.1
validations:
required: true
- type: dropdown
Expand Down
2 changes: 2 additions & 0 deletions contrib/generated_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,8 @@
"800gbase-x-qsfpdd",
"800gbase-x-osfp",
"1000base-kx",
"2.5gbase-kx",
"5gbase-kr",
"10gbase-kr",
"10gbase-kx4",
"25gbase-kr",
Expand Down
16 changes: 16 additions & 0 deletions contrib/uwsgi.ini
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,24 @@ master = true
; clear environment on exit
vacuum = true

; make SIGTERM stop the app (instead of reload)
die-on-term = true

; exit if no app can be loaded
need-app = true

; do not use multiple interpreters
single-interpreter = true

; change to the project directory
chdir = netbox

; specify the WSGI module to load
module = netbox.wsgi

; workaround to make uWSGI reloads work with pyuwsgi (not to be used if using uwsgi package instead)
binary-path = venv/bin/python

; only log internal messages and errors (reverse proxy already logs the requests)
disable-logging = true
log-5xx = true
2 changes: 1 addition & 1 deletion docs/development/adding-models.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ Create the following for each model:

## 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`.
Create a GraphQL 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.

Expand Down
2 changes: 1 addition & 1 deletion docs/development/release-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ In cases where upgrading a dependency to its most recent release is breaking, it

### Update UI Dependencies

Check whether any UI dependencies (JavaScript packages, fonts, etc.) need to be updated by running `yarn outdated` from within the `project-static/` directory. [Upgrade these dependencies](http://0.0.0.0:9000/development/web-ui/#updating-dependencies) as necessary, then run `yarn bundle` to generate the necessary files for distribution.
Check whether any UI dependencies (JavaScript packages, fonts, etc.) need to be updated by running `yarn outdated` from within the `project-static/` directory. [Upgrade these dependencies](./web-ui.md#updating-dependencies) as necessary, then run `yarn bundle` to generate the necessary files for distribution.

### Rebuild the Device Type Definition Schema

Expand Down
2 changes: 1 addition & 1 deletion docs/installation/4b-uwsgi.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pip3 install pyuwsgi
Once installed, add the package to `local_requirements.txt` to ensure it is re-installed during future rebuilds of the virtual environment:

```no-highlight
sudo sh -c "echo 'pyuwgsi' >> /opt/netbox/local_requirements.txt"
sudo sh -c "echo 'pyuwsgi' >> /opt/netbox/local_requirements.txt"
```

## Configuration
Expand Down
4 changes: 2 additions & 2 deletions docs/integrations/graphql-api.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# GraphQL API Overview

NetBox provides a read-only [GraphQL](https://graphql.org/) API to complement its REST API. This API is powered by the [Graphene](https://graphene-python.org/) library and [Graphene-Django](https://docs.graphene-python.org/projects/django/en/latest/).
NetBox provides a read-only [GraphQL](https://graphql.org/) API to complement its REST API. This API is powered by [Strawberry Django](https://strawberry-graphql.github.io/strawberry-django/).

## Queries

Expand Down Expand Up @@ -47,7 +47,7 @@ NetBox provides both a singular and plural query field for each object type:

For example, query `device(id:123)` to fetch a specific device (identified by its unique ID), and query `device_list` (with an optional set of filters) to fetch all devices.

For more detail on constructing GraphQL queries, see the [Graphene documentation](https://docs.graphene-python.org/en/latest/) as well as the [GraphQL queries documentation](https://graphql.org/learn/queries/).
For more detail on constructing GraphQL queries, see the [GraphQL queries documentation](https://graphql.org/learn/queries/). For filtering and lookup syntax, please refer to the [Strawberry Django documentation](https://strawberry-graphql.github.io/strawberry-django/guide/filters/).

## Filtering

Expand Down
2 changes: 1 addition & 1 deletion docs/plugins/development/graphql-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Defining the Schema Class

A plugin can extend NetBox's GraphQL API by registering its own schema class. By default, NetBox will attempt to import `graphql.schema` from the plugin, if it exists. This path can be overridden by defining `graphql_schema` on the PluginConfig instance as the dotted path to the desired Python class. This class must be a subclass of `graphene.ObjectType`.
A plugin can extend NetBox's GraphQL API by registering its own schema class. By default, NetBox will attempt to import `graphql.schema` from the plugin, if it exists. This path can be overridden by defining `graphql_schema` on the PluginConfig instance as the dotted path to the desired Python class.

### Example

Expand Down
68 changes: 44 additions & 24 deletions docs/plugins/development/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,20 @@ project-name/
- template_content.py
- urls.py
- views.py
- pyproject.toml
- README.md
- setup.py
```

The top level is the project root, which can have any name that you like. Immediately within the root should exist several items:

* `setup.py` - This is a standard installation script used to install the plugin package within the Python environment.
* `pyproject.toml` - is a standard configuration file used to install the plugin package within the Python environment.
* `README.md` - A brief introduction to your plugin, how to install and configure it, where to find help, and any other pertinent information. It is recommended to write `README` files using a markup language such as Markdown to enable human-friendly display.
* The plugin source directory. This must be a valid Python package name, typically comprising only lowercase letters, numbers, and underscores.

The plugin source directory contains all the actual Python code and other resources used by your plugin. Its structure is left to the author's discretion, however it is recommended to follow best practices as outlined in the [Django documentation](https://docs.djangoproject.com/en/stable/intro/reusable-apps/). At a minimum, this directory **must** contain an `__init__.py` file containing an instance of NetBox's `PluginConfig` class, discussed below.

**Note:** The [Cookiecutter NetBox Plugin](https://github.com/netbox-community/cookiecutter-netbox-plugin) can be used to auto-generate all the needed directories and files for a new plugin.

## PluginConfig

The `PluginConfig` class is a NetBox-specific wrapper around Django's built-in [`AppConfig`](https://docs.djangoproject.com/en/stable/ref/applications/) class. It is used to declare NetBox plugin functionality within a Python package. Each plugin should provide its own subclass, defining its name, metadata, and default and required configuration parameters. An example is below:
Expand Down Expand Up @@ -136,31 +138,48 @@ Apps from this list are inserted *before* the plugin's `PluginConfig` in the ord

Any additional apps must be installed within the same Python environment as NetBox or `ImproperlyConfigured` exceptions will be raised when loading the plugin.

## Create setup.py
## Create pyproject.toml

`setup.py` is the [setup script](https://docs.python.org/3.10/distutils/setupscript.html) used to package and install our plugin once it's finished. The primary function of this script is to call the setuptools library's `setup()` function to create a Python distribution package. We can pass a number of keyword arguments to control the package creation as well as to provide metadata about the plugin. An example `setup.py` is below:
`pyproject.toml` is the [configuration file](https://packaging.python.org/en/latest/guides/writing-pyproject-toml/) used to package and install our plugin once it's finished. It is used by packaging tools, as well as other tools. The primary function of this file is to call the build system to create a Python distribution package. We can pass a number of keyword arguments to control the package creation as well as to provide metadata about the plugin. There are three possible TOML tables in this file:

* `[build-system]` allows you to declare which build backend you use and which other dependencies (if any) are needed to build your project.
* `[project]` is the format that most build backends use to specify your project’s basic metadata, such as the author's name, project URL, etc.
* `[tool]` has tool-specific subtables, e.g., `[tool.black]`, `[tool.mypy]`. Consult the particular tool’s documentation for reference.

An example `pyproject.toml` is below:

```python
from setuptools import find_packages, setup

setup(
name='my-example-plugin',
version='0.1',
description='An example NetBox plugin',
url='https://github.com/jeremystretch/my-example-plugin',
author='Jeremy Stretch',
license='Apache 2.0',
install_requires=[],
packages=find_packages(),
include_package_data=True,
zip_safe=False,
)
```
# See PEP 518 for the spec of this file
# https://www.python.org/dev/peps/pep-0518/

[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"

[project]
name = "my-example-plugin"
version = "0.1.0"
authors = [
{name = "John Doe", email = "test@netboxlabs.com"},
]
description = "An example NetBox plugin."
readme = "README.md"

classifiers=[
'Development Status :: 3 - Alpha',
'Intended Audience :: Developers',
'Natural Language :: English',
"Programming Language :: Python :: 3 :: Only",
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
]

Many of these are self-explanatory, but for more information, see the [setuptools documentation](https://setuptools.readthedocs.io/en/latest/setuptools.html).
requires-python = ">=3.10.0"

```

!!! info
`zip_safe=False` is **required** as the current plugin iteration is not zip safe due to upstream python issue [issue19699](https://bugs.python.org/issue19699)
Many of these are self-explanatory, but for more information, see the [pyproject.toml documentation](https://packaging.python.org/en/latest/specifications/pyproject-toml/).

## Create a Virtual Environment

Expand All @@ -178,11 +197,12 @@ echo /opt/netbox/netbox > $VENV/lib/python3.10/site-packages/netbox.pth

## Development Installation

To ease development, it is recommended to go ahead and install the plugin at this point using setuptools' `develop` mode. This will create symbolic links within your Python environment to the plugin development directory. Call `setup.py` from the plugin's root directory with the `develop` argument (instead of `install`):
To ease development, it is recommended to go ahead and install the plugin at this point using setuptools' `develop` mode. This will create symbolic links within your Python environment to the plugin development directory. Call `pip` from the plugin's root directory with the `-e` flag:

```no-highlight
$ python setup.py develop
$ pip install -e .
```
More information on editable builds can be found at [Editable installs for pyproject.toml ](https://peps.python.org/pep-0660/).

## Configure NetBox

Expand Down
29 changes: 29 additions & 0 deletions docs/release-notes/version-4.0.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,34 @@
# NetBox v4.0

## v4.0.1 (2024-05-09)

### Enhancements

* [#15148](https://github.com/netbox-community/netbox/issues/15148) - Add copy-to-clipboard button for config context data
* [#15328](https://github.com/netbox-community/netbox/issues/15328) - Add a virtual machines UI tab for host devices
* [#15451](https://github.com/netbox-community/netbox/issues/15451) - Add 2.5 and 5 Gbps backplane Ethernet interface types
* [#16010](https://github.com/netbox-community/netbox/issues/16010) - Enable Prometheus middleware only if metrics are enabled

### Bug Fixes

* [#15968](https://github.com/netbox-community/netbox/issues/15968) - Avoid resizing quick search field to display clear button
* [#15973](https://github.com/netbox-community/netbox/issues/15973) - Fix AttributeError exception when modifying cable termination type
* [#15977](https://github.com/netbox-community/netbox/issues/15977) - Hide all admin menu items for non-authenticated users
* [#15982](https://github.com/netbox-community/netbox/issues/15982) - Restore the "assign IP" tab for assigning existing IP addresses to interfaces
* [#15992](https://github.com/netbox-community/netbox/issues/15992) - Fix AttributeError exception when Sentry integration is enabled
* [#15995](https://github.com/netbox-community/netbox/issues/15995) - Permit nullable fields referenced by unique constraints to be omitted from REST API requests
* [#15999](https://github.com/netbox-community/netbox/issues/15999) - Fix layout of login form labels for certain languages
* [#16003](https://github.com/netbox-community/netbox/issues/16003) - Enable cache busting for `setmode.js` asset to avoid breaking dark mode support on upgrade
* [#16011](https://github.com/netbox-community/netbox/issues/16011) - Fix site tenant assignment by PK via REST API
* [#16020](https://github.com/netbox-community/netbox/issues/16020) - Include Python version in system UI view
* [#16022](https://github.com/netbox-community/netbox/issues/16022) - Fix database migration failure when encountering a script module which no longer exists on disk
* [#16025](https://github.com/netbox-community/netbox/issues/16025) - Fix execution of scripts via the `runscript` management command
* [#16031](https://github.com/netbox-community/netbox/issues/16031) - Render Markdown content in script log messages
* [#16051](https://github.com/netbox-community/netbox/issues/16051) - Translate "empty" text for object tables
* [#16061](https://github.com/netbox-community/netbox/issues/16061) - Omit hidden fields from display within event rule edit form

---

## v4.0.0 (2024-05-06)

!!! tip "Plugin Maintainers"
Expand Down
2 changes: 1 addition & 1 deletion netbox/circuits/api/serializers_/circuits.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class Meta:
class CircuitSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='circuits-api:circuit-detail')
provider = ProviderSerializer(nested=True)
provider_account = ProviderAccountSerializer(nested=True, required=False, allow_null=True)
provider_account = ProviderAccountSerializer(nested=True, required=False, allow_null=True, default=None)
status = ChoiceField(choices=CircuitStatusChoices, required=False)
type = CircuitTypeSerializer(nested=True)
tenant = TenantSerializer(nested=True, required=False, allow_null=True)
Expand Down
1 change: 1 addition & 0 deletions netbox/circuits/api/serializers_/providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class Meta:
class ProviderAccountSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='circuits-api:provideraccount-detail')
provider = ProviderSerializer(nested=True)
name = serializers.CharField(allow_blank=True, max_length=100, required=False, default='')

class Meta:
model = ProviderAccount
Expand Down
4 changes: 2 additions & 2 deletions netbox/circuits/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ def setUpTestData(cls):
{
'cid': 'Circuit 6',
'provider': providers[1].pk,
'provider_account': provider_accounts[1].pk,
# Omit provider account to test uniqueness constraint
'type': circuit_types[1].pk,
},
]
Expand Down Expand Up @@ -237,7 +237,7 @@ def setUpTestData(cls):
'account': '5678',
},
{
'name': 'Provider Account 6',
# Omit name to test uniqueness constraint
'provider': providers[0].pk,
'account': '6789',
},
Expand Down
1 change: 1 addition & 0 deletions netbox/dcim/api/serializers_/devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ def get_config_context(self, obj):
class VirtualDeviceContextSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:virtualdevicecontext-detail')
device = DeviceSerializer(nested=True)
identifier = serializers.IntegerField(allow_null=True, max_value=32767, min_value=0, required=False, default=None)
tenant = TenantSerializer(nested=True, required=False, allow_null=True, default=None)
primary_ip = IPAddressSerializer(nested=True, read_only=True, allow_null=True)
primary_ip4 = IPAddressSerializer(nested=True, required=False, allow_null=True)
Expand Down
4 changes: 2 additions & 2 deletions netbox/dcim/api/serializers_/sites.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class SiteSerializer(NetBoxModelSerializer):
status = ChoiceField(choices=SiteStatusChoices, required=False)
region = RegionSerializer(nested=True, required=False, allow_null=True)
group = SiteGroupSerializer(nested=True, required=False, allow_null=True)
tenant = TenantSerializer(required=False, allow_null=True)
tenant = TenantSerializer(nested=True, required=False, allow_null=True)
time_zone = TimeZoneSerializerField(required=False, allow_null=True)
asns = SerializedPKRelatedField(
queryset=ASN.objects.all(),
Expand Down Expand Up @@ -83,7 +83,7 @@ class Meta:
class LocationSerializer(NestedGroupModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:location-detail')
site = SiteSerializer(nested=True)
parent = NestedLocationSerializer(required=False, allow_null=True)
parent = NestedLocationSerializer(required=False, allow_null=True, default=None)
status = ChoiceField(choices=LocationStatusChoices, required=False)
tenant = TenantSerializer(nested=True, required=False, allow_null=True)
rack_count = serializers.IntegerField(read_only=True)
Expand Down
4 changes: 4 additions & 0 deletions netbox/dcim/choices.py
Original file line number Diff line number Diff line change
Expand Up @@ -848,6 +848,8 @@ class InterfaceTypeChoices(ChoiceSet):

# Ethernet Backplane
TYPE_1GE_KX = '1000base-kx'
TYPE_2GE_KX = '2.5gbase-kx'
TYPE_5GE_KR = '5gbase-kr'
TYPE_10GE_KR = '10gbase-kr'
TYPE_10GE_KX4 = '10gbase-kx4'
TYPE_25GE_KR = '25gbase-kr'
Expand Down Expand Up @@ -1008,6 +1010,8 @@ class InterfaceTypeChoices(ChoiceSet):
_('Ethernet (backplane)'),
(
(TYPE_1GE_KX, '1000BASE-KX (1GE)'),
(TYPE_2GE_KX, '2.5GBASE-KX (2.5GE)'),
(TYPE_5GE_KR, '5GBASE-KR (5GE)'),
(TYPE_10GE_KR, '10GBASE-KR (10GE)'),
(TYPE_10GE_KX4, '10GBASE-KX4 (10GE)'),
(TYPE_25GE_KR, '25GBASE-KR (25GE)'),
Expand Down
Loading
Loading