Refreshed "additional features" docs

This commit is contained in:
Jeremy Stretch
2020-08-03 10:53:44 -04:00
parent eacbec9c68
commit 2644330452
7 changed files with 88 additions and 89 deletions

View File

@@ -6,22 +6,24 @@ Custom scripting was introduced to provide a way for users to execute custom log
* Create a range of new reserved prefixes or IP addresses
* Fetch data from an external source and import it to NetBox
Custom scripts are Python code and exist outside of the official NetBox code base, so they can be updated and changed without interfering with the core NetBox installation. And because they're written from scratch, a custom script can be used to accomplish just about anything.
Custom scripts are Python code and exist outside of the official NetBox code base, so they can be updated and changed without interfering with the core NetBox installation. And because they're completely custom, there is no inherent limitation on what a script can accomplish.
## Writing Custom Scripts
All custom scripts must inherit from the `extras.scripts.Script` base class. This class provides the functionality necessary to generate forms and log activity.
```
```python
from extras.scripts import Script
class MyScript(Script):
..
...
```
Scripts comprise two core components: variables and a `run()` method. Variables allow your script to accept user input via the NetBox UI. The `run()` method is where your script's execution logic lives. (Note that your script can have as many methods as needed: this is merely the point of invocation for NetBox.)
Scripts comprise two core components: a set of variables and a `run()` method. Variables allow your script to accept user input via the NetBox UI, but they are optional: If your script does not require any user input, there is no need to define any variables.
```
The `run()` method is where your script's execution logic lives. (Note that your script can have as many methods as needed: this is merely the point of invocation for NetBox.)
```python
class MyScript(Script):
var1 = StringVar(...)
var2 = IntegerVar(...)
@@ -37,9 +39,7 @@ The `run()` method should accept two arguments:
* `commit` - A boolean indicating whether database changes will be committed.
!!! note
The `commit` argument was introduced in NetBox v2.7.8. Backward compatibility is maintained for scripts which accept only the `data` argument, however moving forward scripts should accept both arguments.
Defining variables is optional: You may create a script with only a `run()` method if no user input is needed.
The `commit` argument was introduced in NetBox v2.7.8. Backward compatibility is maintained for scripts which accept only the `data` argument, however moving forward scripts should accept both arguments. This backward compatibility will be removed in v2.10.
Returning output from your script is optional. Any raw output generated by the script will be displayed under the "output" tab in the UI.
@@ -47,7 +47,7 @@ Returning output from your script is optional. Any raw output generated by the s
### `name`
You can define `name` within a script module (the Python file which contains one or more scripts) to set the module name. If `name` is not defined, the filename will be used.
You can define `name` within a script module (the Python file which contains one or more scripts) to set the module name. If `name` is not defined, the module's file name will be used.
## Script Attributes
@@ -61,19 +61,11 @@ This is the human-friendly names of your script. If omitted, the class name will
A human-friendly description of what your script does.
### `field_order`
A list of field names indicating the order in which the form fields should appear. This is optional, and should not be required on Python 3.6 and above. For example:
```
field_order = ['var1', 'var2', 'var3']
```
### `commit_default`
The checkbox to commit database changes when executing a script is checked by default. Set `commit_default` to False under the script's Meta class to leave this option unchecked by default.
```
```python
commit_default = False
```
@@ -83,8 +75,9 @@ Details of the current HTTP request (the one being made to execute the script) a
```python
username = self.request.user.username
ip_address = self.request.META.get('HTTP_X_FORWARDED_FOR') or self.request.META.get('REMOTE_ADDR')
self.log_info("Running as user {} (IP: {})...".format(username, ip_address))
ip_address = self.request.META.get('HTTP_X_FORWARDED_FOR') or \
self.request.META.get('REMOTE_ADDR')
self.log_info(f"Running as user {username} (IP: {ip_address})...")
```
For a complete list of available request parameters, please see the [Django documentation](https://docs.djangoproject.com/en/stable/ref/request-response/).
@@ -112,30 +105,40 @@ Log messages are returned to the user upon execution of the script. Markdown ren
## Variable Reference
### Default Options
All custom script variables support the following default options:
* `default` - The field's default value
* `description` - A brief user-friendly description of the field
* `label` - The field name to be displayed in the rendered form
* `required` - Indicates whether the field is mandatory (all fields are required by default)
* `widget` - The class of form widget to use (see the [Django documentation](https://docs.djangoproject.com/en/stable/ref/forms/widgets/))
### StringVar
Stores a string of characters (i.e. a line of text). Options include:
Stores a string of characters (i.e. text). Options include:
* `min_length` - Minimum number of characters
* `max_length` - Maximum number of characters
* `regex` - A regular expression against which the provided value must match
Note: `min_length` and `max_length` can be set to the same number to effect a fixed-length field.
Note that `min_length` and `max_length` can be set to the same number to effect a fixed-length field.
### TextVar
Arbitrary text of any length. Renders as multi-line text input field.
Arbitrary text of any length. Renders as a multi-line text input field.
### IntegerVar
Stored a numeric integer. Options include:
Stores a numeric integer. Options include:
* `min_value` - Minimum value
* `max_value` - Maximum value
### BooleanVar
A true/false flag. This field has no options beyond the defaults.
A true/false flag. This field has no options beyond the defaults listed above.
### ChoiceVar
@@ -154,19 +157,24 @@ CHOICES = (
direction = ChoiceVar(choices=CHOICES)
```
In the example above, selecting the choice labeled "North" will submit the value `n`.
### ObjectVar
A NetBox object of a particular type, identified by the associated queryset. Most models will utilize the REST API to retrieve available options: Note that any filtering on the queryset in this case has no effect.
A NetBox object of a particular type, identified by the associated queryset.
* `queryset` - The base [Django queryset](https://docs.djangoproject.com/en/stable/topics/db/queries/) for the model
!!! warning
Because the available options for this field are populated using the REST API, any filtering or exclusions performed on the specified queryset will not have any effect. While it is possible to influence the manner in which field options are populated using NetBox's `APISelect` widget, please note that this component is not officially supported and is planned to be replaced in a future release.
### MultiObjectVar
Similar to `ObjectVar`, but allows for the selection of multiple objects.
### FileVar
An uploaded file. Note that uploaded files are present in memory only for the duration of the script's execution: They will not be save for future use.
An uploaded file. Note that uploaded files are present in memory only for the duration of the script's execution: They will not be automatically saved for future use. The script is responsible for writing file contents to disk where necessary.
### IPAddressVar
@@ -180,18 +188,8 @@ An IPv4 or IPv6 address with a mask. Returns a `netaddr.IPNetwork` object which
An IPv4 or IPv6 network with a mask. Returns a `netaddr.IPNetwork` object. Two attributes are available to validate the provided mask:
* `min_prefix_length` - Minimum length of the mask (default: none)
* `max_prefix_length` - Maximum length of the mask (default: none)
### Default Options
All variables support the following default options:
* `default` - The field's default value
* `description` - A brief description of the field
* `label` - The name of the form field
* `required` - Indicates whether the field is mandatory (default: true)
* `widget` - The class of form widget to use (see the [Django documentation](https://docs.djangoproject.com/en/stable/ref/forms/widgets/))
* `min_prefix_length` - Minimum length of the mask
* `max_prefix_length` - Maximum length of the mask
## Example
@@ -203,12 +201,13 @@ Below is an example script that creates new objects for a planned site. The user
These variables are presented as a web form to be completed by the user. Once submitted, the script's `run()` method is called to create the appropriate objects.
```
```python
from django.utils.text import slugify
from dcim.choices import DeviceStatusChoices, SiteStatusChoices
from dcim.models import Device, DeviceRole, DeviceType, Site
from extras.scripts import *
from utilities.forms import APISelect
class NewBranchScript(Script):
@@ -226,7 +225,10 @@ class NewBranchScript(Script):
)
switch_model = ObjectVar(
description="Access switch model",
queryset = DeviceType.objects.all()
queryset=DeviceType.objects.all(),
widget=APISelect(
display_field='model'
)
)
def run(self, data, commit):
@@ -238,20 +240,20 @@ class NewBranchScript(Script):
status=SiteStatusChoices.STATUS_PLANNED
)
site.save()
self.log_success("Created new site: {}".format(site))
self.log_success(f"Created new site: {site}")
# Create access switches
switch_role = DeviceRole.objects.get(name='Access Switch')
for i in range(1, data['switch_count'] + 1):
switch = Device(
device_type=data['switch_model'],
name='{}-switch{}'.format(site.slug, i),
name=f'{site.slug}-switch{i}',
site=site,
status=DeviceStatusChoices.STATUS_PLANNED,
device_role=switch_role
)
switch.save()
self.log_success("Created new switch: {}".format(switch))
self.log_success(f"Created new switch: {switch}")
# Generate a CSV table of new devices
output = [