summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Doran <sdoran@redhat.com>2020-04-15 15:26:45 -0400
committerGitHub <noreply@github.com>2020-04-15 15:26:45 -0400
commitcdb24e0078d738f87fc20e67c2b7bcbf45f8e248 (patch)
treef40a7b7c07aee659d6095ada194a736f8c1d4371
parentd3d301e776e636e8791f7a66ed91984ea6ca471b (diff)
downloadansible-cdb24e0078d738f87fc20e67c2b7bcbf45f8e248.tar.gz
ansible-galaxy - fix listing specific role and role description (#67409)
* ansible-galaxy - fix listing specific role If the role was not in the first search path, it was reported as not found * Properly display role description Default to description to top level description, falling back to the description from within galaxy_info * Display proper message when a role does not exist * Add integration tests * Use context manager * BSD and macOS ruining all the fun
-rw-r--r--changelogs/fragments/ansible-galaxy-role-list-specific-fix.yml6
-rw-r--r--lib/ansible/cli/galaxy.py13
-rw-r--r--lib/ansible/galaxy/role.py34
-rwxr-xr-xtest/integration/targets/ansible-galaxy/runme.sh65
4 files changed, 99 insertions, 19 deletions
diff --git a/changelogs/fragments/ansible-galaxy-role-list-specific-fix.yml b/changelogs/fragments/ansible-galaxy-role-list-specific-fix.yml
new file mode 100644
index 0000000000..eaef1d5952
--- /dev/null
+++ b/changelogs/fragments/ansible-galaxy-role-list-specific-fix.yml
@@ -0,0 +1,6 @@
+bugfixes:
+ - >
+ ansible-galaxy - fix a bug where listing a specific role if it was not in the first
+ path failed to find the role
+
+ - ansible-galaxy - properly show the role description when running offline (https://github.com/ansible/ansible/issues/60167)
diff --git a/lib/ansible/cli/galaxy.py b/lib/ansible/cli/galaxy.py
index 89a9dcc547..7b7f24b4ee 100644
--- a/lib/ansible/cli/galaxy.py
+++ b/lib/ansible/cli/galaxy.py
@@ -603,7 +603,11 @@ class GalaxyCLI(CLI):
def _display_role_info(role_info):
text = [u"", u"Role: %s" % to_text(role_info['name'])]
- text.append(u"\tdescription: %s" % role_info.get('description', ''))
+
+ # Get the top-level 'description' first, falling back to galaxy_info['galaxy_info']['description'].
+ galaxy_info = role_info.get('galaxy_info', {})
+ description = role_info.get('description', galaxy_info.get('description', ''))
+ text.append(u"\tdescription: %s" % description)
for k in sorted(role_info.keys()):
@@ -899,6 +903,9 @@ class GalaxyCLI(CLI):
role_info = {'path': roles_path}
gr = GalaxyRole(self.galaxy, self.api, role)
+ if not gr._exists:
+ data = u"- the role %s was not found" % role
+ break
install_info = gr.install_info
if install_info:
@@ -923,10 +930,6 @@ class GalaxyCLI(CLI):
role_info.update(role_spec)
data = self._display_role_info(role_info)
- # FIXME: This is broken in both 1.9 and 2.0 as
- # _display_role_info() always returns something
- if not data:
- data = u"\n- the role %s was not found" % role
self.pager(data)
diff --git a/lib/ansible/galaxy/role.py b/lib/ansible/galaxy/role.py
index 8e1ca72fd4..ba12d1d4c2 100644
--- a/lib/ansible/galaxy/role.py
+++ b/lib/ansible/galaxy/role.py
@@ -64,6 +64,7 @@ class GalaxyRole(object):
self.version = version
self.src = src or name
self.scm = scm
+ self.paths = [os.path.join(x, self.name) for x in galaxy.roles_paths]
if path is not None:
if not path.endswith(os.path.join(os.path.sep, self.name)):
@@ -82,9 +83,6 @@ class GalaxyRole(object):
else:
# use the first path by default
self.path = os.path.join(galaxy.roles_paths[0], self.name)
- # create list of possible paths
- self.paths = [x for x in galaxy.roles_paths]
- self.paths = [os.path.join(x, self.name) for x in self.paths]
def __repr__(self):
"""
@@ -105,17 +103,17 @@ class GalaxyRole(object):
Returns role metadata
"""
if self._metadata is None:
- for meta_main in self.META_MAIN:
- meta_path = os.path.join(self.path, meta_main)
- if os.path.isfile(meta_path):
- try:
- f = open(meta_path, 'r')
- self._metadata = yaml.safe_load(f)
- except Exception:
- display.vvvvv("Unable to load metadata for %s" % self.name)
- return False
- finally:
- f.close()
+ for path in self.paths:
+ for meta_main in self.META_MAIN:
+ meta_path = os.path.join(path, meta_main)
+ if os.path.isfile(meta_path):
+ try:
+ with open(meta_path, 'r') as f:
+ self._metadata = yaml.safe_load(f)
+ except Exception:
+ display.vvvvv("Unable to load metadata for %s" % self.name)
+ return False
+ break
return self._metadata
@@ -138,6 +136,14 @@ class GalaxyRole(object):
f.close()
return self._install_info
+ @property
+ def _exists(self):
+ for path in self.paths:
+ if os.path.isdir(path):
+ return True
+
+ return False
+
def _write_galaxy_install_info(self):
"""
Writes a YAML-formatted file to the role's meta/ directory
diff --git a/test/integration/targets/ansible-galaxy/runme.sh b/test/integration/targets/ansible-galaxy/runme.sh
index 3409352b8b..e33dc02de6 100755
--- a/test/integration/targets/ansible-galaxy/runme.sh
+++ b/test/integration/targets/ansible-galaxy/runme.sh
@@ -120,6 +120,71 @@ f_ansible_galaxy_status \
[[ $(grep -c '^- test-role' out.txt ) -eq 2 ]]
+# Galaxy role test case
+#
+# Test listing a specific role that is not in the first path in ANSIBLE_ROLES_PATH.
+# https://github.com/ansible/ansible/issues/60167#issuecomment-585460706
+
+f_ansible_galaxy_status \
+ "list specific role not in the first path in ANSIBLE_ROLES_PATHS"
+
+role_testdir=$(mktemp -d)
+pushd "${role_testdir}"
+
+ mkdir testroles
+ ansible-galaxy role init --init-path ./local-roles quark
+ ANSIBLE_ROLES_PATH=./local-roles:${HOME}/.ansible/roles ansible-galaxy role list quark | tee out.txt
+
+ [[ $(grep -c 'not found' out.txt) -eq 0 ]]
+
+ ANSIBLE_ROLES_PATH=${HOME}/.ansible/roles:./local-roles ansible-galaxy role list quark | tee out.txt
+
+ [[ $(grep -c 'not found' out.txt) -eq 0 ]]
+
+popd # ${role_testdir}
+rm -fr "${role_testdir}"
+
+
+# Galaxy role info tests
+
+f_ansible_galaxy_status \
+ "role info non-existant role"
+
+role_testdir=$(mktemp -d)
+pushd "${role_testdir}"
+
+ ansible-galaxy role info notaroll | tee out.txt
+
+ grep -- '- the role notaroll was not found' out.txt
+
+f_ansible_galaxy_status \
+ "role info description offline"
+
+ mkdir testroles
+ ansible-galaxy role init testdesc --init-path ./testroles
+
+ # Only galaxy_info['description'] exists in file
+ sed -i -e 's#[[:space:]]\{1,\}description:.*$# description: Description in galaxy_info#' ./testroles/testdesc/meta/main.yml
+ ansible-galaxy role info -p ./testroles --offline testdesc | tee out.txt
+ grep 'description: Description in galaxy_info' out.txt
+
+ # Both top level 'description' and galaxy_info['description'] exist in file
+ # Use shell-fu instead of sed to prepend a line to a file because BSD
+ # and macOS sed don't work the same as GNU sed.
+ echo 'description: Top level' | \
+ cat - ./testroles/testdesc/meta/main.yml > tmp.yml && \
+ mv tmp.yml ./testroles/testdesc/meta/main.yml
+ ansible-galaxy role info -p ./testroles --offline testdesc | tee out.txt
+ grep 'description: Top level' out.txt
+
+ # Only top level 'description' exists in file
+ sed -i.bak '/^[[:space:]]\{1,\}description: Description in galaxy_info/d' ./testroles/testdesc/meta/main.yml
+ ansible-galaxy role info -p ./testroles --offline testdesc | tee out.txt
+ grep 'description: Top level' out.txt
+
+popd # ${role_testdir}
+rm -fr "${role_testdir}"
+
# Properly list roles when the role name is a subset of the path, or the role
# name is the same name as the parent directory of the role. Issue #67365