summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSloane Hertel <19572925+s-hertel@users.noreply.github.com>2022-10-26 17:05:17 -0400
committerGitHub <noreply@github.com>2022-10-26 16:05:17 -0500
commit65fd4e182ba1664deec04418af085db92cc6029b (patch)
tree5599f1e1a96ef55c3aaf2478bab19680e1797728 /lib
parenta5480c330db2645c213081955273610b98c67a6c (diff)
downloadansible-65fd4e182ba1664deec04418af085db92cc6029b.tar.gz
[2.13] ansible-galaxy - fix unnecessary api check when installing role (#79143)
* ansible-galaxy install - fix unnecessary api check when installing a role from git repo (#79090) * delay server api evaluation until a GalaxyRole needs to make an api call for info, list, and install (cherry picked from commit cb2e434dd2359a9fe1c00e75431f4abeff7381e8) * fix type for older python * Fix isinstance check (#79159) Use GalaxyAPI for isinstance check instead of RoleDistributionServer, since the latter is defined in __main__ sometimes (when running integration tests or ansible-galaxy from source) and importing from ansible.cli.galaxy won't reference the same object. (cherry picked from commit 89d682464b65af6d2f77a148fc6abb2c38b0e994)
Diffstat (limited to 'lib')
-rwxr-xr-xlib/ansible/cli/galaxy.py62
-rw-r--r--lib/ansible/galaxy/role.py9
2 files changed, 47 insertions, 24 deletions
diff --git a/lib/ansible/cli/galaxy.py b/lib/ansible/cli/galaxy.py
index 5acaa6e46a..c08d2ec60f 100755
--- a/lib/ansible/cli/galaxy.py
+++ b/lib/ansible/cli/galaxy.py
@@ -17,7 +17,9 @@ import shutil
import sys
import textwrap
import time
+import typing as t
+from dataclasses import dataclass
from yaml.error import YAMLError
import ansible.constants as C
@@ -156,6 +158,30 @@ def validate_signature_count(value):
return value
+@dataclass
+class RoleDistributionServer:
+ _api: t.Union[GalaxyAPI, None]
+ api_servers: t.List[GalaxyAPI]
+
+ @property
+ def api(self):
+ if self._api:
+ return self._api
+
+ for server in self.api_servers:
+ try:
+ if u'v1' in server.available_api_versions:
+ self._api = server
+ break
+ except Exception:
+ continue
+
+ if not self._api:
+ self._api = self.api_servers[0]
+
+ return self._api
+
+
class GalaxyCLI(CLI):
'''command to manage Ansible roles in shared repositories, the default of which is Ansible Galaxy *https://galaxy.ansible.com*.'''
@@ -186,7 +212,7 @@ class GalaxyCLI(CLI):
self.api_servers = []
self.galaxy = None
- self._api = None
+ self.lazy_role_api = None
super(GalaxyCLI, self).__init__(args)
def init_parser(self):
@@ -649,25 +675,15 @@ class GalaxyCLI(CLI):
**galaxy_options
))
+ # checks api versions once a GalaxyRole makes an api call
+ # self.api can be used to evaluate the best server immediately
+ self.lazy_role_api = RoleDistributionServer(None, self.api_servers)
+
return context.CLIARGS['func']()
@property
def api(self):
- if self._api:
- return self._api
-
- for server in self.api_servers:
- try:
- if u'v1' in server.available_api_versions:
- self._api = server
- break
- except Exception:
- continue
-
- if not self._api:
- self._api = self.api_servers[0]
-
- return self._api
+ return self.lazy_role_api.api
def _get_default_collection_path(self):
return C.COLLECTIONS_PATHS[0]
@@ -728,7 +744,7 @@ class GalaxyCLI(CLI):
display.vvv("found role %s in yaml file" % to_text(role))
if "name" not in role and "src" not in role:
raise AnsibleError("Must specify name or src for role")
- return [GalaxyRole(self.galaxy, self.api, **role)]
+ return [GalaxyRole(self.galaxy, self.lazy_role_api, **role)]
else:
b_include_path = to_bytes(requirement["include"], errors="surrogate_or_strict")
if not os.path.isfile(b_include_path):
@@ -737,7 +753,7 @@ class GalaxyCLI(CLI):
with open(b_include_path, 'rb') as f_include:
try:
- return [GalaxyRole(self.galaxy, self.api, **r) for r in
+ return [GalaxyRole(self.galaxy, self.lazy_role_api, **r) for r in
(RoleRequirement.role_yaml_parse(i) for i in yaml_load(f_include))]
except Exception as e:
raise AnsibleError("Unable to load data from include requirements file: %s %s"
@@ -1152,7 +1168,7 @@ class GalaxyCLI(CLI):
for role in context.CLIARGS['args']:
role_info = {'path': roles_path}
- gr = GalaxyRole(self.galaxy, self.api, role)
+ gr = GalaxyRole(self.galaxy, self.lazy_role_api, role)
install_info = gr.install_info
if install_info:
@@ -1294,7 +1310,7 @@ class GalaxyCLI(CLI):
# (and their dependencies, unless the user doesn't want us to).
for rname in context.CLIARGS['args']:
role = RoleRequirement.role_yaml_parse(rname.strip())
- role_requirements.append(GalaxyRole(self.galaxy, self.api, **role))
+ role_requirements.append(GalaxyRole(self.galaxy, self.lazy_role_api, **role))
if not role_requirements and not collection_requirements:
display.display("Skipping install, no requirements found")
@@ -1403,7 +1419,7 @@ class GalaxyCLI(CLI):
display.debug('Installing dep %s' % dep)
dep_req = RoleRequirement()
dep_info = dep_req.role_yaml_parse(dep)
- dep_role = GalaxyRole(self.galaxy, self.api, **dep_info)
+ dep_role = GalaxyRole(self.galaxy, self.lazy_role_api, **dep_info)
if '.' not in dep_role.name and '.' not in dep_role.src and dep_role.scm is None:
# we know we can skip this, as it's not going to
# be found on galaxy.ansible.com
@@ -1487,7 +1503,7 @@ class GalaxyCLI(CLI):
if role_name:
# show the requested role, if it exists
- gr = GalaxyRole(self.galaxy, self.api, role_name, path=os.path.join(role_path, role_name))
+ gr = GalaxyRole(self.galaxy, self.lazy_role_api, role_name, path=os.path.join(role_path, role_name))
if os.path.isdir(gr.path):
role_found = True
display.display('# %s' % os.path.dirname(gr.path))
@@ -1506,7 +1522,7 @@ class GalaxyCLI(CLI):
display.display('# %s' % role_path)
path_files = os.listdir(role_path)
for path_file in path_files:
- gr = GalaxyRole(self.galaxy, self.api, path_file, path=path)
+ gr = GalaxyRole(self.galaxy, self.lazy_role_api, path_file, path=path)
if gr.metadata:
_display_role(gr)
diff --git a/lib/ansible/galaxy/role.py b/lib/ansible/galaxy/role.py
index 058174c931..391394cfc9 100644
--- a/lib/ansible/galaxy/role.py
+++ b/lib/ansible/galaxy/role.py
@@ -32,6 +32,7 @@ from shutil import rmtree
from ansible import context
from ansible.errors import AnsibleError
+from ansible.galaxy.api import GalaxyAPI
from ansible.galaxy.user_agent import user_agent
from ansible.module_utils._text import to_native, to_text
from ansible.module_utils.common.yaml import yaml_dump, yaml_load
@@ -60,7 +61,7 @@ class GalaxyRole(object):
display.debug('Validate TLS certificates: %s' % self._validate_certs)
self.galaxy = galaxy
- self.api = api
+ self._api = api
self.name = name
self.version = version
@@ -101,6 +102,12 @@ class GalaxyRole(object):
return self.name == other.name
@property
+ def api(self):
+ if not isinstance(self._api, GalaxyAPI):
+ return self._api.api
+ return self._api
+
+ @property
def metadata(self):
"""
Returns role metadata