Skip to content

Commit

Permalink
Use resource prefix when apiVersion is v1 (#371)
Browse files Browse the repository at this point in the history
Use resource prefix when apiVersion is v1

SUMMARY
When getting a resource from the core api group, the prefix was not
passed, leading the lookup to happen in all api groups. This broad
search is not really necessary and leads to problems in some corner
cases, for example, when an api is deleted after the api group list is
cached.
This fix uses the 'api' prefix when the apiVersion is 'v1', as this is
almost certainly what the user wants. As a fallback, to retain backwards
compatibility, the old behavior is used if the first lookup failed to
find a resource. Given that the module defaults to 'v1' for the
apiVersion, there are likely many cases where a resource, such as
StatefulSet, is used while failing to provide an apiVersion. While
technically incorrect, this has worked in most cases, so we probably
shouldn't break this behavior.
Fixes #351
ISSUE TYPE

Bugfix Pull Request

COMPONENT NAME
changelogs/fragments/364-use-resource-prefix.yaml
plugins/module_utils/common.py
  • Loading branch information
Akasurde authored Feb 10, 2022
1 parent e62a271 commit 791175d
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 10 deletions.
3 changes: 3 additions & 0 deletions changelogs/fragments/364-use-resource-prefix.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
bugfixes:
- use resource prefix when finding resource and apiVersion is v1 (https://github.com/ansible-collections/kubernetes.core/issues/351).
36 changes: 26 additions & 10 deletions plugins/module_utils/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -354,25 +354,41 @@ def __init__(self, module, pyyaml_required=True, *args, **kwargs):
if pyyaml_required and not HAS_YAML:
module.fail_json(msg=missing_required_lib("PyYAML"), exception=YAML_IMP_ERR)

def find_resource(self, kind, api_version, fail=False):
def _find_resource_with_prefix(self, prefix, kind, api_version):
for attribute in ["kind", "name", "singular_name"]:
try:
return self.client.resources.get(
**{"api_version": api_version, attribute: kind}
**{"prefix": prefix, "api_version": api_version, attribute: kind}
)
except (ResourceNotFoundError, ResourceNotUniqueError):
pass
return self.client.resources.get(
prefix=prefix, api_version=api_version, short_names=[kind]
)

def find_resource(self, kind, api_version, fail=False):
msg = "Failed to find exact match for {0}.{1} by [kind, name, singularName, shortNames]".format(
api_version, kind
)
try:
return self.client.resources.get(
api_version=api_version, short_names=[kind]
)
if api_version == "v1":
return self._find_resource_with_prefix("api", kind, api_version)
except ResourceNotUniqueError:
# No point trying again as we'll just get the same error
if fail:
self.fail(msg=msg)
else:
return None
except ResourceNotFoundError:
pass
# The second check without a prefix is maintained for backwards compatibility.
# If we are here, it's probably because the resource really doesn't exist or
# the wrong api_version has been specified, for example, v1.DaemonSet.
try:
return self._find_resource_with_prefix(None, kind, api_version)
except (ResourceNotFoundError, ResourceNotUniqueError):
if fail:
self.fail(
msg="Failed to find exact match for {0}.{1} by [kind, name, singularName, shortNames]".format(
api_version, kind
)
)
self.fail(msg=msg)

def kubernetes_facts(
self,
Expand Down

0 comments on commit 791175d

Please sign in to comment.