From df7fa041494eb3609fcdbe65517a58a6396e0a84 Mon Sep 17 00:00:00 2001 From: Jonas L Date: Fri, 24 Nov 2023 20:50:43 +0100 Subject: [PATCH] fix(inventory): always use fresh cache on new cached session (#404) ##### SUMMARY The class scoped `cache` dict was being shared across all `cached_session`, we now make sure that the cache is instance scoped. Fixes #403 ##### ISSUE TYPE - Bugfix Pull Request --- .ansible-lint | 1 + .../fragments/fix-inventory-fresh-cache.yaml | 2 ++ examples/use-refresh-inventory.yml | 35 +++++++++++++++++++ plugins/module_utils/client.py | 14 +++++--- 4 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 changelogs/fragments/fix-inventory-fresh-cache.yaml create mode 100644 examples/use-refresh-inventory.yml diff --git a/.ansible-lint b/.ansible-lint index 35f1c5a..d9e34b1 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -5,6 +5,7 @@ exclude_paths: - .git/ - .github/ - changelogs/ + - examples/ - tests/integration/targets/certificate - tests/integration/targets/firewall - tests/integration/targets/floating_ip diff --git a/changelogs/fragments/fix-inventory-fresh-cache.yaml b/changelogs/fragments/fix-inventory-fresh-cache.yaml new file mode 100644 index 0000000..2901ac8 --- /dev/null +++ b/changelogs/fragments/fix-inventory-fresh-cache.yaml @@ -0,0 +1,2 @@ +bugfixes: + - hcloud inventory - Ensure the API client use a new cache for every *cached session*. diff --git a/examples/use-refresh-inventory.yml b/examples/use-refresh-inventory.yml new file mode 100644 index 0000000..fd4c351 --- /dev/null +++ b/examples/use-refresh-inventory.yml @@ -0,0 +1,35 @@ +--- +- name: Demonstrate the usage of 'refresh_inventory' + hosts: localhost + connection: local + + tasks: + - name: Print hostvars + ansible.builtin.debug: + var: hostvars + + - name: Create new server + hetzner.hcloud.server: + name: my-server + server_type: cx11 + image: debian-12 + + - name: Refresh inventory + ansible.builtin.meta: refresh_inventory + + - name: Run tests + block: + - name: Print updated inventory + ansible.builtin.debug: + var: hostvars + + - name: Verify hostvars is not empty + ansible.builtin.assert: + that: + - hostvars != {} + + always: + - name: Cleanup server + hetzner.hcloud.server: + name: my-server + state: absent diff --git a/plugins/module_utils/client.py b/plugins/module_utils/client.py index 352ca58..d82a630 100644 --- a/plugins/module_utils/client.py +++ b/plugins/module_utils/client.py @@ -68,7 +68,11 @@ def client_get_by_name_or_id(client: Client, resource: str, param: str | int): if HAS_REQUESTS: class CachedSession(requests.Session): - cache: dict[str, requests.Response] = {} + cache: dict[str, requests.Response] + + def __init__(self) -> None: + super().__init__() + self.cache = {} def send(self, request: requests.PreparedRequest, **kwargs) -> requests.Response: # type: ignore[no-untyped-def] """ @@ -89,7 +93,7 @@ if HAS_REQUESTS: class Client(ClientBase): @contextmanager - def cached_session(self) -> None: + def cached_session(self): """ Swap the client session during the scope of the context. The session will cache all GET requests. @@ -98,5 +102,7 @@ class Client(ClientBase): for long living scopes. """ self._requests_session = CachedSession() - yield - self._requests_session = requests.Session() + try: + yield + finally: + self._requests_session = requests.Session()