ansible-galaxy - fall back to galaxy.yml when listing collections (#68925)

Fallback to galaxy.yml for listing collections that don't have a FILES.json or MANIFEST.json

Co-authored-by: Sam Doran <sdoran@redhat.com>
This commit is contained in:
Sloane Hertel 2020-05-14 12:28:08 -04:00 committed by GitHub
parent 343ffaa18b
commit 55e29a1464
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 32 additions and 10 deletions

View file

@ -114,7 +114,7 @@ collections on a host without access to a Galaxy or Automation Hub server.
Listing collections Listing collections
=================== ===================
To list installed collections, run ``ansible-galaxy collection list``. This shows all of the installed collections found in the configured collections search paths. The path where the collections are located are displayed as well as version information. If no version information is available, a ``*`` is displayed for the version number. To list installed collections, run ``ansible-galaxy collection list``. This shows all of the installed collections found in the configured collections search paths. It will also show collections under development which contain a galaxy.yml file instead of a MANIFEST.json. The path where the collections are located are displayed as well as version information. If no version information is available, a ``*`` is displayed for the version number.
.. code-block:: shell .. code-block:: shell

View file

@ -1235,7 +1235,7 @@ class GalaxyCLI(CLI):
continue continue
collection_found = True collection_found = True
collection = CollectionRequirement.from_path(b_collection_path, False) collection = CollectionRequirement.from_path(b_collection_path, False, fallback_metadata=True)
fqcn_width, version_width = _get_collection_widths(collection) fqcn_width, version_width = _get_collection_widths(collection)
_display_header(collection_path, 'Collection', 'Version', fqcn_width, version_width) _display_header(collection_path, 'Collection', 'Version', fqcn_width, version_width)
@ -1246,7 +1246,7 @@ class GalaxyCLI(CLI):
collection_path = validate_collection_path(path) collection_path = validate_collection_path(path)
if os.path.isdir(collection_path): if os.path.isdir(collection_path):
display.vvv("Searching {0} for collections".format(collection_path)) display.vvv("Searching {0} for collections".format(collection_path))
collections = find_existing_collections(collection_path) collections = find_existing_collections(collection_path, fallback_metadata=True)
else: else:
# There was no 'ansible_collections/' directory in the path, so there # There was no 'ansible_collections/' directory in the path, so there
# or no collections here. # or no collections here.

View file

@ -224,7 +224,7 @@ class CollectionRequirement:
_extract_tar_file(collection_tar, file_name, b_collection_path, b_temp_path, _extract_tar_file(collection_tar, file_name, b_collection_path, b_temp_path,
expected_hash=file_info['chksum_sha256']) expected_hash=file_info['chksum_sha256'])
else: else:
os.makedirs(os.path.join(b_collection_path, to_bytes(file_name, errors='surrogate_or_strict'))) os.makedirs(os.path.join(b_collection_path, to_bytes(file_name, errors='surrogate_or_strict')), mode=0o0755)
except Exception: except Exception:
# Ensure we don't leave the dir behind in case of a failure. # Ensure we don't leave the dir behind in case of a failure.
shutil.rmtree(b_collection_path) shutil.rmtree(b_collection_path)
@ -386,7 +386,7 @@ class CollectionRequirement:
metadata=meta, files=files, allow_pre_releases=allow_pre_release) metadata=meta, files=files, allow_pre_releases=allow_pre_release)
@staticmethod @staticmethod
def from_path(b_path, force, parent=None): def from_path(b_path, force, parent=None, fallback_metadata=False):
info = {} info = {}
for b_file_name, property_name in CollectionRequirement._FILE_MAPPING: for b_file_name, property_name in CollectionRequirement._FILE_MAPPING:
b_file_path = os.path.join(b_path, b_file_name) b_file_path = os.path.join(b_path, b_file_name)
@ -399,6 +399,13 @@ class CollectionRequirement:
except ValueError: except ValueError:
raise AnsibleError("Collection file at '%s' does not contain a valid json string." raise AnsibleError("Collection file at '%s' does not contain a valid json string."
% to_native(b_file_path)) % to_native(b_file_path))
if not info and fallback_metadata:
b_galaxy_path = os.path.join(b_path, b'galaxy.yml')
if os.path.exists(b_galaxy_path):
collection_meta = _get_galaxy_yml(b_galaxy_path)
info['files_file'] = _build_files_manifest(b_path, collection_meta['namespace'], collection_meta['name'],
collection_meta['build_ignore'])
info['manifest_file'] = _build_manifest(**collection_meta)
allow_pre_release = False allow_pre_release = False
if 'manifest_file' in info: if 'manifest_file' in info:
@ -419,8 +426,11 @@ class CollectionRequirement:
dependencies = manifest['dependencies'] dependencies = manifest['dependencies']
else: else:
display.warning("Collection at '%s' does not have a MANIFEST.json file, cannot detect version." if fallback_metadata:
% to_text(b_path)) warning = "Collection at '%s' does not have a galaxy.yml or a MANIFEST.json file, cannot detect version."
else:
warning = "Collection at '%s' does not have a MANIFEST.json file, cannot detect version."
display.warning(warning % to_text(b_path))
parent_dir, name = os.path.split(to_text(b_path, errors='surrogate_or_strict')) parent_dir, name = os.path.split(to_text(b_path, errors='surrogate_or_strict'))
namespace = os.path.split(parent_dir)[1] namespace = os.path.split(parent_dir)[1]
@ -998,7 +1008,7 @@ def _build_collection_tar(b_collection_path, b_tar_path, collection_manifest, fi
display.display('Created collection for %s at %s' % (collection_name, to_text(b_tar_path))) display.display('Created collection for %s at %s' % (collection_name, to_text(b_tar_path)))
def find_existing_collections(path): def find_existing_collections(path, fallback_metadata=False):
collections = [] collections = []
b_path = to_bytes(path, errors='surrogate_or_strict') b_path = to_bytes(path, errors='surrogate_or_strict')
@ -1010,7 +1020,7 @@ def find_existing_collections(path):
for b_collection in os.listdir(b_namespace_path): for b_collection in os.listdir(b_namespace_path):
b_collection_path = os.path.join(b_namespace_path, b_collection) b_collection_path = os.path.join(b_namespace_path, b_collection)
if os.path.isdir(b_collection_path): if os.path.isdir(b_collection_path):
req = CollectionRequirement.from_path(b_collection_path, False) req = CollectionRequirement.from_path(b_collection_path, False, fallback_metadata=fallback_metadata)
display.vvv("Found installed collection %s:%s at '%s'" % (to_text(req), req.latest_version, display.vvv("Found installed collection %s:%s at '%s'" % (to_text(req), req.latest_version,
to_text(b_collection_path))) to_text(b_collection_path)))
collections.append(req) collections.append(req)

View file

@ -336,6 +336,10 @@ sed -i -e 's#^version:.*#version: 2.5.0#' ansible_test/zoo/galaxy.yml
ansible-galaxy collection build ansible_test/zoo ansible-galaxy collection build ansible_test/zoo
ansible-galaxy collection install ansible_test-zoo-2.5.0.tar.gz -p ./local ansible-galaxy collection install ansible_test-zoo-2.5.0.tar.gz -p ./local
# Test listing a collection that contains a galaxy.yml
ansible-galaxy collection init "ansible_test.development"
mv ./ansible_test/development "${galaxy_testdir}/local/ansible_collections/ansible_test/"
export ANSIBLE_COLLECTIONS_PATHS=~/.ansible/collections:${galaxy_testdir}/local export ANSIBLE_COLLECTIONS_PATHS=~/.ansible/collections:${galaxy_testdir}/local
f_ansible_galaxy_status \ f_ansible_galaxy_status \
@ -343,7 +347,7 @@ f_ansible_galaxy_status \
ansible-galaxy collection list -p ./install | tee out.txt ansible-galaxy collection list -p ./install | tee out.txt
[[ $(grep -c ansible_test out.txt) -eq 4 ]] [[ $(grep -c ansible_test out.txt) -eq 5 ]]
f_ansible_galaxy_status \ f_ansible_galaxy_status \
"collection list specific collection" "collection list specific collection"
@ -352,6 +356,14 @@ f_ansible_galaxy_status \
[[ $(grep -c 'ansible_test\.airport' out.txt) -eq 1 ]] [[ $(grep -c 'ansible_test\.airport' out.txt) -eq 1 ]]
f_ansible_galaxy_status \
"collection list specific collection which contains galaxy.yml"
ansible-galaxy collection list -p ./install ansible_test.development 2>&1 | tee out.txt
[[ $(grep -c 'ansible_test\.development' out.txt) -eq 1 ]]
[[ $(grep -c 'WARNING' out.txt) -eq 0 ]]
f_ansible_galaxy_status \ f_ansible_galaxy_status \
"collection list specific collection found in multiple places" "collection list specific collection found in multiple places"