Updating an Existing Module¶
The main reason for updating an existing module is to either deprecate an option or add new options. We'll discuss the different methods for these options.
New Option - Doesn't correlate to different Nautobot models¶
There are times when you need to add a new option to a module that doesn't require resolving to other models within Nautobot. An example is adding a new interface type to device_interface
module and only requires a documentation and argument spec update.
Another example is adding a dns_name
field that is just a text field. The only updates that need to be made are to the DOCUMENTATION
, EXAMPLES
and argument_spec
within the module.
Steps:
- Update module
DOCUMENTATION
string with new option and type - Update module
EXAMPLES
to include the new option - Update module
argument_spec
to include new option and type - Update integration tests to have the new option within tests
New Option - Must be resolved to a different model¶
When we add a new option that may point to a different model then we must make a few additional changes to both the module and the utils
. Let's stick with our previous example in Contributing a New Module for route-targets.
It turns out that this was implemented as a separate model, but has a relationship to VRFs to track both import and export targets. This means we will need to add those additional options to the vrf module.
Here is a refresher for what we're looking to implement.
Let's start by updating the vrf module to specify both import_targets and export_targets as lists of strings.
We'll update the DOCUMENTATION
first.
...
import_targets:
description:
- Import targets tied to VRF
required: false
type: list
elements: str
version_added: "1.0.0"
export_targets:
description:
- Export targets tied to VRF
required: false
type: list
elements: str
version_added: "1.0.0"
...
Now that the DOCUMENTATION
is updated, let's move onto updating the EXAMPLES
.
- name: Create vrf with all information
vrf:
url: http://nautobot.local
token: thisIsMyToken
data:
name: Test VRF
rd: "65000:1"
tenant: Test Tenant
enforce_unique: true
import_targets:
- "65000:65001"
export_targets:
- "65000:65001"
description: VRF description
tags:
- Schnozzberry
state: present
The final update we have to make to the module is updating the argument_spec
.
def main():
...
argument_spec.update(
dict(
data=dict(
type="dict",
required=True,
options=dict(
...
import_targets=dict(required=False, type="list", elements="str"),
export_targets=dict(required=False, type="list", elements="str"),
...
...
Now that we have that taken care of, let's move onto the utils
.
# Used to normalize data for the respective query types used to find endpoints
QUERY_TYPES = dict(
...
export_targets="name",
group="name",
installed_device="name",
import_targets="name",
...
...
# Specifies keys within data that need to be converted to ID and the endpoint to be used when queried
CONVERT_TO_ID = {
...
"export_targets": "route_targets",
"group": "tenant_groups",
"import_targets": "route_targets",
...
Overall the changes are minimal as you just want to make sure to add it to CONVERT_TO_ID
to flag the values to be converted to an ID by resolving to the route-targets model. This variable is just telling the collection what endpoint to use to search. The QUERY_TYPE
then specifies the query type to use when attempting to resolve the ID.
Now we need to make sure we test these new options within the integration tests. Since these require resolving to an existing model, we need to update our nautobot-deploy.py
script that bootstraps Nautobot and make sure we add route targets we will use within our integration testing.
Edit tests/integration/nautobot-deploy.py
.
...
route_targets = [
{"name": "4000:4000"},
{"name": "5000:5000"},
{"name": "6000:6000"},
]
created_route_targets = make_calls(nb.ipam.route_targets, route_targets)
if ERRORS:
sys.exit(
"Errors have occurred when creating objects, and should have been printed out. Check previous output."
)
Next we'll update vrf.yml
for the latest integration target.
❯ tree tests/integration/targets
tests/integration/targets
├── latest
│ └── tasks
│ ├── main.yml
│ ├── ...
│ ├── vm_interface.yml
│ └── vrf.yml
12 directories, 143 files
- name: "VRF 4: ASSERT - Update"
networktocode.nautobot.vrf:
url: http://localhost:32768
token: 0123456789abcdef0123456789abcdef01234567
data:
name: "Test VRF One"
rd: "65001:1"
enforce_unique: False
tenant: "Test Tenant"
description: Updated description
import_targets:
- "4000:4000"
export_targets:
- "5000:5000"
tags:
- "Schnozzberry"
state: present
register: test_four
- name: "VRF 4: ASSERT - Updated"
assert:
that:
- test_four is changed
- test_four['diff']['after']['rd'] == "65001:1"
- test_four['diff']['after']['enforce_unique'] == false
- test_four['diff']['after']['description'] == "Updated description"
- test_four['diff']['after']['tags'][0] == 4
- test_four['diff']['after']['import_targets'] | length == 1
- test_four['diff']['after']['export_targets'] | length == 1
- test_four['vrf']['name'] == "Test VRF One"
- test_four['vrf']['tenant'] == 1
- test_four['vrf']['rd'] == "65001:1"
- test_four['vrf']['enforce_unique'] == false
- test_four['vrf']['description'] == "Updated description"
- test_four['vrf']['tags'][0] == 4
- test_four['vrf']['import_targets'] | length == 1
- test_four['vrf']['export_targets'] | length == 1
- test_four['msg'] == "vrf Test VRF One updated"
We added the import_targets and export_targets when updating the VRF and then asserting that the length of both the after and vrf object are both one.
Let's generate our new documents. From the root of the collection, run the following commands.
❯ poetry shell && poetry install
❯ ./hacking/make-docs.sh
rm: tests/output: No such file or directory
rm: .pytest_cache: No such file or directory
Using /Users/myohman/cloned-repos/nautobot-ansible/ansible.cfg as config file
Created collection for networktocode.nautobot at /Users/myohman/cloned-repos/nautobot-ansible/networktocode.nautobot-1.1.0.tar.gz
Starting galaxy collection install process
[WARNING]: The specified collections path '/Users/myohman/cloned-repos/nautobot-ansible' is not part of the configured Ansible collections paths
'/Users/myohman/.ansible/collections:/usr/share/ansible/collections'. The installed collection won't be picked up in an Ansible run.
Process install dependency map
Starting collection install process
Installing 'networktocode.nautobot:1.1.0' to '/Users/myohman/cloned-repos/nautobot-ansible/ansible_collections/networktocode.nautobot'
networktocode.nautobot (1.1.0) was installed successfully
Installing 'ansible.netcommon:1.4.1' to '/Users/myohman/cloned-repos/nautobot-ansible/ansible_collections/ansible/netcommon'
Downloading https://galaxy.ansible.com/download/ansible-netcommon-1.4.1.tar.gz to /Users/myohman/.ansible/tmp/ansible-local-4390k59zwzli/tmp5871aum5
ansible.netcommon (1.4.1) was installed successfully
Installing 'community.general:1.3.4' to '/Users/myohman/cloned-repos/nautobot-ansible/ansible_collections/community/general'
Downloading https://galaxy.ansible.com/download/community-general-1.3.4.tar.gz to /Users/myohman/.ansible/tmp/ansible-local-4390k59zwzli/tmp5871aum5
community.general (1.3.4) was installed successfully
Installing 'google.cloud:1.0.1' to '/Users/myohman/cloned-repos/nautobot-ansible/ansible_collections/google/cloud'
Downloading https://galaxy.ansible.com/download/google-cloud-1.0.1.tar.gz to /Users/myohman/.ansible/tmp/ansible-local-4390k59zwzli/tmp5871aum5
google.cloud (1.0.1) was installed successfully
Installing 'community.kubernetes:1.1.1' to '/Users/myohman/cloned-repos/nautobot-ansible/ansible_collections/community/kubernetes'
Downloading https://galaxy.ansible.com/download/community-kubernetes-1.1.1.tar.gz to /Users/myohman/.ansible/tmp/ansible-local-4390k59zwzli/tmp5871aum5
community.kubernetes (1.1.1) was installed successfully
ERROR:antsibull:error=Cannot find plugin:func=get_ansible_plugin_info:mod=antsibull.docs_parsing.ansible_internal:plugin_name=networktocode.nautobot.interface:plugin_type=module|Error while extracting documentation. Will not document this plugin.
We'll push these up and let the CI/CD run and then these tests should pass and then we're good to submit a PR.