1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2024-09-14 20:13:21 +02:00

bitwarden_secrets_manager: implement rate limit retry with backoff (#8238)

* bitwarden_secrets_manager: implement rate limit retry with backoff (#8230)

* bitwarden_secrets_manager: add changelog fragment for 90cd2d61 (#8238)

* bitwarden_secrets_manager: clarify "Too many requests" is an error condition (#8238)

* bitwarden_secrets_manager: avoid an extra _run_with_retry execution after the last (very long) delay

* bitwarden_secrets_manager: changelog fragment key and reference issue url
This commit is contained in:
Matt Adams 2024-04-21 07:55:27 -05:00 committed by GitHub
parent be11d0d409
commit a05a5982a6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 22 additions and 1 deletions

View file

@ -0,0 +1,2 @@
bugfixes:
- "bitwarden_secrets_manager lookup plugin - implements retry with exponential backoff to avoid lookup errors when Bitwardn's API rate limiting is encountered (https://github.com/ansible-collections/community.general/issues/8230, https://github.com/ansible-collections/community.general/pull/8238)."

View file

@ -70,6 +70,7 @@ RETURN = """
""" """
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
from time import sleep
from ansible.errors import AnsibleLookupError from ansible.errors import AnsibleLookupError
from ansible.module_utils.common.text.converters import to_text from ansible.module_utils.common.text.converters import to_text
@ -84,11 +85,29 @@ class BitwardenSecretsManagerException(AnsibleLookupError):
class BitwardenSecretsManager(object): class BitwardenSecretsManager(object):
def __init__(self, path='bws'): def __init__(self, path='bws'):
self._cli_path = path self._cli_path = path
self._max_retries = 3
self._retry_delay = 1
@property @property
def cli_path(self): def cli_path(self):
return self._cli_path return self._cli_path
def _run_with_retry(self, args, stdin=None, retries=0):
out, err, rc = self._run(args, stdin)
if rc != 0:
if retries >= self._max_retries:
raise BitwardenSecretsManagerException("Max retries exceeded. Unable to retrieve secret.")
if "Too many requests" in err:
delay = self._retry_delay * (2 ** retries)
sleep(delay)
return self._run_with_retry(args, stdin, retries + 1)
else:
raise BitwardenSecretsManagerException(f"Command failed with return code {rc}: {err}")
return out, err, rc
def _run(self, args, stdin=None): def _run(self, args, stdin=None):
p = Popen([self.cli_path] + args, stdout=PIPE, stderr=PIPE, stdin=PIPE) p = Popen([self.cli_path] + args, stdout=PIPE, stderr=PIPE, stdin=PIPE)
out, err = p.communicate(stdin) out, err = p.communicate(stdin)
@ -107,7 +126,7 @@ class BitwardenSecretsManager(object):
'get', 'secret', secret_id 'get', 'secret', secret_id
] ]
out, err, rc = self._run(params) out, err, rc = self._run_with_retry(params)
if rc != 0: if rc != 0:
raise BitwardenSecretsManagerException(to_text(err)) raise BitwardenSecretsManagerException(to_text(err))