Skip to content

Commit

Permalink
Add support for Nautobot REST API versioning (#139)
Browse files Browse the repository at this point in the history
  • Loading branch information
timizuoebideri1 authored Aug 24, 2022
1 parent e794da3 commit 77608d0
Show file tree
Hide file tree
Showing 65 changed files with 581 additions and 327 deletions.
3 changes: 2 additions & 1 deletion plugins/action/query_graphql.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def nautobot_action_graphql(args):
raise AnsibleError("Missing URL of Nautobot")

token = args.get("token") or os.getenv("NAUTOBOT_TOKEN")
api_version = args.get("api_version")
ssl_verify = args.get("validate_certs", True)
Display().vv("Verify Certificates: %s" % ssl_verify)

Expand All @@ -52,7 +53,7 @@ def nautobot_action_graphql(args):
if not isinstance(update_hostvars, bool):
raise AnsibleError("update_hostvars must be a boolean")

nautobot_api = NautobotApiBase(token=token, url=url, ssl_verify=ssl_verify)
nautobot_api = NautobotApiBase(token=token, url=url, ssl_verify=ssl_verify, api_version=api_version)
query = args.get("query")
Display().v("Query String: %s" % query)

Expand Down
10 changes: 8 additions & 2 deletions plugins/inventory/inventory.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
required: True
env:
- name: NAUTOBOT_URL
api_version:
description: The version of the Nautobot REST API.
required: False
version_added: "4.1.0"
validate_certs:
description:
- Allows connection when SSL certificates are not valid. Set to C(false) when certificates are not trusted.
Expand Down Expand Up @@ -1073,8 +1077,6 @@ def wrapper():
def fetch_api_docs(self):
openapi = self._fetch_information(self.api_endpoint + "/api/docs/?format=openapi")

self.api_version = openapi["info"]["version"]

device_path = "/api/dcim/devices/" if "/api/dcim/devices/" in openapi["paths"] else "/dcim/devices/"
vm_path = (
"/api/virtualization/virtual-machines/" if "/api/virtualization/virtual-machines/" in openapi["paths"] else "/virtualization/virtual-machines/"
Expand Down Expand Up @@ -1357,6 +1359,9 @@ def main(self):
# Get info about the API - version, allowed query parameters
self.fetch_api_docs()

if self.api_version:
self.headers.update({"Accept": f"application/json; version={self.api_version}"})

self.fetch_hosts()

# Interface, and Service lookup will depend on hosts, if option fetch_all is false
Expand Down Expand Up @@ -1402,6 +1407,7 @@ def parse(self, inventory, loader, path, cache=True):
token = self.get_option("token")
# Handle extra "/" from api_endpoint configuration and trim if necessary, see PR#49943
self.api_endpoint = self.get_option("api_endpoint").strip("/")
self.api_version = self.get_option("api_version")
self.timeout = self.get_option("timeout")
self.max_uri_length = self.get_option("max_uri_length")
self.validate_certs = self.get_option("validate_certs")
Expand Down
12 changes: 11 additions & 1 deletion plugins/lookup/lookup.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@
description:
- The api_filter to use.
required: False
api_version:
description:
- The Nautobot Rest API version to use.
required: False
version_added: "4.1.0"
plugin:
description:
- The Nautobot plugin to query
Expand Down Expand Up @@ -71,6 +76,7 @@
manufactured by {{ item.value.device_type.manufacturer.name }}"
loop: "{{ query('networktocode.nautobot.lookup', 'devices',
api_endpoint='http://localhost/',
api_version='1.3',
token='<redacted>') }}"
# This example uses an API Filter
Expand All @@ -83,7 +89,8 @@
manufactured by {{ item.value.device_type.manufacturer.name }}"
loop: "{{ query('networktocode.nautobot.lookup', 'devices',
api_endpoint='http://localhost/',
api_filter='role=management tag=Dell'),
api_version='1.3',
api_filter='role=management tag=Dell',
token='<redacted>') }}"
# Fetch bgp sessions for R1-device
Expand All @@ -93,6 +100,7 @@
msg: "{{ query('networktocode.nautobot.lookup', 'bgp_sessions',
api_filter='device=R1-Device',
api_endpoint='http://localhost/',
api_version='1.3',
token='<redacted>',
plugin='mycustomstuff') }}"
"""
Expand Down Expand Up @@ -299,6 +307,7 @@ def run(self, terms, variables=None, **kwargs):
api_filter = kwargs.get("api_filter")
raw_return = kwargs.get("raw_data")
plugin = kwargs.get("plugin")
api_version = kwargs.get("api_version")

if not isinstance(terms, list):
terms = [terms]
Expand All @@ -309,6 +318,7 @@ def run(self, terms, variables=None, **kwargs):
nautobot = pynautobot.api(
api_endpoint,
token=api_token if api_token else None,
api_version=api_version,
)
nautobot.http_session = session

Expand Down
8 changes: 7 additions & 1 deletion plugins/lookup/lookup_graphql.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
description:
- Queries Nautobot via its GraphQL API through pynautobot
options:
api_version:
description:
- The Nautobot Rest API Version to use
required: False
version_added: "4.1.0"
query:
description:
- The GraphQL formatted query string, see [pynautobot GraphQL documentation](https://pynautobot.readthedocs.io/en/latest/advanced/graphql.html).
Expand Down Expand Up @@ -147,12 +152,13 @@ def nautobot_lookup_graphql(**kwargs):

token = kwargs.get("token") or os.getenv("NAUTOBOT_TOKEN")
ssl_verify = kwargs.get("validate_certs", True)
api_version = kwargs.get("api_version")
Display().vv("Validate certs: %s" % ssl_verify)

if not isinstance(ssl_verify, bool):
raise AnsibleLookupError("validate_certs must be a boolean")

nautobot_api = NautobotApiBase(token=token, url=url, ssl_verify=ssl_verify)
nautobot_api = NautobotApiBase(token=token, url=url, ssl_verify=ssl_verify, api_version=api_version)
graph_variables = kwargs.get("graph_variables")
Display().v("Graph Variables: %s" % graph_variables)

Expand Down
21 changes: 16 additions & 5 deletions plugins/module_utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@
state=dict(required=False, default="present", choices=["present", "absent"]),
query_params=dict(required=False, type="list", elements="str"),
validate_certs=dict(type="raw", default=True),
api_version=dict(type="str", required=False),
)


Expand All @@ -446,10 +447,11 @@ def __init__(self, module, endpoint, client=None, remove_keys=None):
url = self.module.params["url"]
token = self.module.params["token"]
ssl_verify = self.module.params["validate_certs"]
api_version = self.module.params["api_version"]

# Attempt to initiate connection to Nautobot
if client is None:
self.nb = self._connect_api(url, token, ssl_verify)
self.nb = self._connect_api(url, token, ssl_verify, api_version)
else:
self.nb = client
self.version = self.nb.version
Expand Down Expand Up @@ -506,12 +508,17 @@ def _version_check_greater(self, greater, lesser, greater_or_equal=False):
elif g_major == l_major and g_minor > l_minor:
return True

def _connect_api(self, url, token, ssl_verify):
def _connect_api(self, url, token, ssl_verify, api_version):
try:
nb = pynautobot.api(url, token=token)
nb = pynautobot.api(url, token=token, api_version=api_version)
nb.http_session.verify = ssl_verify
try:
self.version = nb.version
except pynautobot.RequestError as e:
# Better error reporting
# An error might be: Invalid version in \"Accept\" header. Supported versions are 1.2, 1.3
# This way error returned is less verbose
self._handle_errors(msg=e.error)
except Exception:
self.module.fail_json(msg="Failed to establish connection to Nautobot API")
return nb
Expand Down Expand Up @@ -927,7 +934,10 @@ def _create_object(self, nb_endpoint, data):
nb_obj = data
else:
try:
nb_obj = nb_endpoint.create(data)
if isinstance(nb_endpoint, pynautobot.core.endpoint.DetailEndpoint):
nb_obj = nb_endpoint.create(data)
else:
nb_obj = nb_endpoint.create(**data)
except pynautobot.RequestError as e:
self._handle_errors(msg=e.error)

Expand Down Expand Up @@ -1033,9 +1043,10 @@ def __init__(self, **kwargs):
self.url = kwargs.get("url") or os.getenv("NAUTOBOT_URL")
self.token = kwargs.get("token") or os.getenv("NAUTOBOT_TOKEN")
self.ssl_verify = kwargs.get("ssl_verify", True)
self.api_version = kwargs.get("api_version")

# Setup the API client calls
self.api = pynautobot.api(url=self.url, token=self.token)
self.api = pynautobot.api(url=self.url, token=self.token, api_version=self.api_version)
self.api.http_session.verify = self.ssl_verify


Expand Down
6 changes: 6 additions & 0 deletions plugins/modules/aggregate.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
- pynautobot
version_added: "1.0.0"
options:
api_version:
description:
- API Version Nautobot REST API
required: false
type: str
version_added: "4.1.0"
url:
description:
- "URL of the Nautobot instance resolvable by Ansible control host"
Expand Down
6 changes: 6 additions & 0 deletions plugins/modules/cable.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
- pynautobot
version_added: "1.0.0"
options:
api_version:
description:
- API Version Nautobot REST API
required: false
type: str
version_added: "4.1.0"
url:
description:
- URL of the Nautobot instance resolvable by Ansible control host
Expand Down
6 changes: 6 additions & 0 deletions plugins/modules/circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
- pynautobot
version_added: "1.0.0"
options:
api_version:
description:
- API Version Nautobot REST API
required: false
type: str
version_added: "4.1.0"
url:
description:
- URL of the Nautobot instance resolvable by Ansible control host
Expand Down
6 changes: 6 additions & 0 deletions plugins/modules/circuit_termination.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
- pynautobot
version_added: "1.0.0"
options:
api_version:
description:
- API Version Nautobot REST API
required: false
type: str
version_added: "4.1.0"
url:
description:
- URL of the Nautobot instance resolvable by Ansible control host
Expand Down
6 changes: 6 additions & 0 deletions plugins/modules/circuit_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
- pynautobot
version_added: "1.0.0"
options:
api_version:
description:
- API Version Nautobot REST API
required: false
type: str
version_added: "4.1.0"
url:
description:
- URL of the Nautobot instance resolvable by Ansible control host
Expand Down
6 changes: 6 additions & 0 deletions plugins/modules/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
- pynautobot
version_added: "1.0.0"
options:
api_version:
description:
- API Version Nautobot REST API
required: false
type: str
version_added: "4.1.0"
url:
description:
- URL of the Nautobot instance resolvable by Ansible control host
Expand Down
6 changes: 6 additions & 0 deletions plugins/modules/cluster_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
- pynautobot
version_added: "1.0.0"
options:
api_version:
description:
- API Version Nautobot REST API
required: false
type: str
version_added: "4.1.0"
url:
description:
- URL of the Nautobot instance resolvable by Ansible control host
Expand Down
6 changes: 6 additions & 0 deletions plugins/modules/cluster_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
- pynautobot
version_added: "1.0.0"
options:
api_version:
description:
- API Version Nautobot REST API
required: false
type: str
version_added: "4.1.0"
url:
description:
- URL of the Nautobot instance resolvable by Ansible control host
Expand Down
6 changes: 6 additions & 0 deletions plugins/modules/console_port.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
- pynautobot
version_added: "1.0.0"
options:
api_version:
description:
- API Version Nautobot REST API
required: false
type: str
version_added: "4.1.0"
url:
description:
- URL of the Nautobot instance resolvable by Ansible control host
Expand Down
6 changes: 6 additions & 0 deletions plugins/modules/console_port_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
- pynautobot
version_added: "1.0.0"
options:
api_version:
description:
- API Version Nautobot REST API
required: false
type: str
version_added: "4.1.0"
url:
description:
- URL of the Nautobot instance resolvable by Ansible control host
Expand Down
6 changes: 6 additions & 0 deletions plugins/modules/console_server_port.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
- pynautobot
version_added: "1.0.0"
options:
api_version:
description:
- API Version Nautobot REST API
required: false
type: str
version_added: "4.1.0"
url:
description:
- URL of the Nautobot instance resolvable by Ansible control host
Expand Down
6 changes: 6 additions & 0 deletions plugins/modules/console_server_port_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
- pynautobot
version_added: "1.0.0"
options:
api_version:
description:
- API Version Nautobot REST API
required: false
type: str
version_added: "4.1.0"
url:
description:
- URL of the Nautobot instance resolvable by Ansible control host
Expand Down
6 changes: 6 additions & 0 deletions plugins/modules/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@
- pynautobot
version_added: "1.0.0"
options:
api_version:
description:
- API Version Nautobot REST API
required: false
type: str
version_added: "4.1.0"
url:
description:
- URL of the Nautobot instance resolvable by Ansible control host
Expand Down
6 changes: 6 additions & 0 deletions plugins/modules/device_bay.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@
- pynautobot
version_added: "1.0.0"
options:
api_version:
description:
- API Version Nautobot REST API
required: false
type: str
version_added: "4.1.0"
url:
description:
- URL of the Nautobot instance resolvable by Ansible control host
Expand Down
6 changes: 6 additions & 0 deletions plugins/modules/device_bay_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@
- pynautobot
version_added: "1.0.0"
options:
api_version:
description:
- API Version Nautobot REST API
required: false
type: str
version_added: "4.1.0"
url:
description:
- URL of the Nautobot instance resolvable by Ansible control host
Expand Down
Loading

0 comments on commit 77608d0

Please sign in to comment.