diff options
author | Sam Doran <sdoran@redhat.com> | 2020-04-15 15:26:45 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-15 15:26:45 -0400 |
commit | cdb24e0078d738f87fc20e67c2b7bcbf45f8e248 (patch) | |
tree | f40a7b7c07aee659d6095ada194a736f8c1d4371 | |
parent | d3d301e776e636e8791f7a66ed91984ea6ca471b (diff) | |
download | ansible-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.yml | 6 | ||||
-rw-r--r-- | lib/ansible/cli/galaxy.py | 13 | ||||
-rw-r--r-- | lib/ansible/galaxy/role.py | 34 | ||||
-rwxr-xr-x | test/integration/targets/ansible-galaxy/runme.sh | 65 |
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 |