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

Add inventory cache to the netbox plugin #57644

Merged
merged 2 commits into from Oct 17, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions changelogs/fragments/netbox-add-cache.yaml
@@ -0,0 +1,2 @@
minor_changes:
- netbox - use inventory cache if configured
57 changes: 45 additions & 12 deletions lib/ansible/plugins/inventory/netbox.py
Expand Up @@ -12,11 +12,13 @@
- Remy Leone (@sieben)
- Anthony Ruhier (@Anthony25)
- Nikhil Singh Baliyan (@nikkytub)
- Sander Steffann (@steffann)
short_description: NetBox inventory source
description:
- Get inventory hosts from NetBox
extends_documentation_fragment:
- constructed
- inventory_cache
options:
plugin:
description: token that ensures this is a source file for the 'netbox' plugin.
Expand Down Expand Up @@ -118,12 +120,12 @@
from threading import Thread
from itertools import chain

from ansible.plugins.inventory import BaseInventoryPlugin, Constructable
from ansible.plugins.inventory import BaseInventoryPlugin, Constructable, Cacheable
from ansible.module_utils.ansible_release import __version__ as ansible_version
from ansible.errors import AnsibleError
from ansible.module_utils._text import to_text
from ansible.module_utils.urls import open_url
from ansible.module_utils.six.moves.urllib.parse import urljoin, urlencode
from ansible.module_utils.six.moves.urllib.parse import urlencode
from ansible.module_utils.compat.ipaddress import ip_interface

ALLOWED_DEVICE_QUERY_PARAMETERS = (
Expand Down Expand Up @@ -158,21 +160,51 @@
)


class InventoryModule(BaseInventoryPlugin, Constructable):
class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
NAME = 'netbox'

def _fetch_information(self, url):
response = open_url(url, headers=self.headers, timeout=self.timeout, validate_certs=self.validate_certs)
results = None
cache_key = self.get_cache_key(url)

# get the user's cache option to see if we should save the cache if it is changing
user_cache_setting = self.get_option('cache')

# read if the user has caching enabled and the cache isn't being refreshed
attempt_to_read_cache = user_cache_setting and self.use_cache

# attempt to read the cache if inventory isn't being refreshed and the user has caching enabled
if attempt_to_read_cache:
try:
results = self._cache[cache_key]
need_to_fetch = False
except KeyError:
# occurs if the cache_key is not in the cache or if the cache_key expired
# we need to fetch the URL now
need_to_fetch = True
else:
# not reading from cache so do fetch
need_to_fetch = True

try:
raw_data = to_text(response.read(), errors='surrogate_or_strict')
except UnicodeError:
raise AnsibleError("Incorrect encoding of fetched payload from NetBox API.")
if need_to_fetch:
self.display.v("Fetching: " + url)
response = open_url(url, headers=self.headers, timeout=self.timeout, validate_certs=self.validate_certs)

try:
return json.loads(raw_data)
except ValueError:
raise AnsibleError("Incorrect JSON payload: %s" % raw_data)
try:
raw_data = to_text(response.read(), errors='surrogate_or_strict')
except UnicodeError:
raise AnsibleError("Incorrect encoding of fetched payload from NetBox API.")

try:
results = json.loads(raw_data)
except ValueError:
raise AnsibleError("Incorrect JSON payload: %s" % raw_data)

# put result in cache if enabled
if user_cache_setting:
self._cache[cache_key] = results

return results

def get_resource_list(self, api_url):
"""Retrieves resource list from netbox API.
Expand Down Expand Up @@ -446,6 +478,7 @@ def main(self):
def parse(self, inventory, loader, path, cache=True):
super(InventoryModule, self).parse(inventory, loader, path)
self._read_config_data(path=path)
self.use_cache = cache

# Netbox access
token = self.get_option("token")
Expand Down