Skip to content

Commit

Permalink
Actually activate inventory caching (#97)
Browse files Browse the repository at this point in the history
The inventory plugin advertises support for caching, but the
implementation was missing the required pieces to make it work
properly.

This commit split the inventory construction into two stages. The
first stage is responsible for fetching remote data (interacting with
the DigitalOcean's API). The second stage extracts the relevant data
from the API responses and populated the inventory.

Caching support then came almost for free. All we had to do is only
fetch data if:

 1. User does not want to use cache at all.
 2. User does use cache and wants data refreshed.
 3. User does use cache but the cache is empty.

There is some additional logic that makes sure we write the data to
cache if data refresh is requested, but nothing too complex.
  • Loading branch information
tadeboro authored Jun 1, 2021
1 parent e928762 commit 82b45a3
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 21 deletions.
3 changes: 3 additions & 0 deletions changelogs/fragments/97-wire-up-inventory-cache.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
bugfixes:
- digitalocean inventory plugin - wire up advertised caching functionality
(https://github.com/ansible-collections/community.digitalocean/pull/97).
30 changes: 16 additions & 14 deletions plugins/inventory/digitalocean.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,12 +170,12 @@ def _get_payload(self):

return payload

def _populate(self):
def _populate(self, records):
attributes = self.get_option('attributes')
var_prefix = self.get_option('var_prefix')
strict = self.get_option('strict')
host_filters = self.get_option('filters')
for record in self._get_payload():
for record in records:

host_name = record.get('name')
if not host_name:
Expand Down Expand Up @@ -220,22 +220,24 @@ def _passes_filters(self, filters, variables, host, strict=False):
def parse(self, inventory, loader, path, cache=True):
super(InventoryModule, self).parse(inventory, loader, path)

# cache settings
self._read_config_data(path)
self.cache_key = self.get_cache_key(path)

self.use_cache = self.get_option('cache') and cache
self.update_cache = self.get_option('cache') and not cache
# cache settings
cache_key = self.get_cache_key(path)
use_cache = self.get_option('cache') and cache
update_cache = self.get_option('cache') and not cache

results = []
if not self.update_cache:
records = None
if use_cache:
try:
results = self._cache[self.cache_key]['digitalocean']
records = self._cache[cache_key]
except KeyError:
pass
update_cache = True

if records is None:
records = self._get_payload()

if not results:
if self.cache_key not in self._cache:
self._cache[self.cache_key] = {'digitalocean': ''}
if update_cache:
self._cache[cache_key] = records

self._populate()
self._populate(records)
14 changes: 7 additions & 7 deletions tests/unit/plugins/inventory/test_digitalocean.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ def test_verify_file_bad_config(inventory):
assert inventory.verify_file('digitalocean_foobar.yml') is False


def get_payload():
@pytest.fixture()
def payload():
return [
{
"id": 3164444,
Expand Down Expand Up @@ -136,10 +137,10 @@ def get_option(option):
return options.get(option)


def test_populate_hostvars(inventory, mocker):
inventory._get_payload = mocker.MagicMock(side_effect=get_payload)
def test_populate_hostvars(inventory, payload, mocker):
inventory.get_option = mocker.MagicMock(side_effect=get_option)
inventory._populate()

inventory._populate(payload)

host_foo = inventory.inventory.get_host('foo')
host_bar = inventory.inventory.get_host('bar')
Expand Down Expand Up @@ -184,10 +185,9 @@ def get_option_with_filters(option):
return options.get(option)


def test_populate_hostvars_with_filters(inventory, mocker):
inventory._get_payload = mocker.MagicMock(side_effect=get_payload)
def test_populate_hostvars_with_filters(inventory, payload, mocker):
inventory.get_option = mocker.MagicMock(side_effect=get_option_with_filters)
inventory._populate()
inventory._populate(payload)

host_foo = inventory.inventory.get_host('foo')
host_bar = inventory.inventory.get_host('bar')
Expand Down

0 comments on commit 82b45a3

Please sign in to comment.