validate meta/main.yml dependencies and meta/requirements.yml are both lists before concatenating them together (#77821)

pull/77871/head
Sloane Hertel 4 years ago committed by GitHub
parent e85e8ee00a
commit 400475acc0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,2 @@
bugfixes:
- ansible-galaxy - Fix unhandled traceback if a role's dependencies in meta/main.yml or meta/requirements.yml are not lists.

@ -1376,9 +1376,10 @@ class GalaxyCLI(CLI):
# install dependencies, if we want them # install dependencies, if we want them
if not no_deps and installed: if not no_deps and installed:
if not role.metadata: if not role.metadata:
# NOTE: the meta file is also required for installing the role, not just dependencies
display.warning("Meta file %s is empty. Skipping dependencies." % role.path) display.warning("Meta file %s is empty. Skipping dependencies." % role.path)
else: else:
role_dependencies = (role.metadata.get('dependencies') or []) + role.requirements role_dependencies = role.metadata_dependencies + role.requirements
for dep in role_dependencies: for dep in role_dependencies:
display.debug('Installing dep %s' % dep) display.debug('Installing dep %s' % dep)
dep_req = RoleRequirement() dep_req = RoleRequirement()

@ -27,14 +27,16 @@ import datetime
import os import os
import tarfile import tarfile
import tempfile import tempfile
from ansible.module_utils.compat.version import LooseVersion
from collections.abc import MutableSequence
from shutil import rmtree from shutil import rmtree
from ansible import context from ansible import context
from ansible.errors import AnsibleError from ansible.errors import AnsibleError, AnsibleParserError
from ansible.galaxy.user_agent import user_agent from ansible.galaxy.user_agent import user_agent
from ansible.module_utils._text import to_native, to_text from ansible.module_utils._text import to_native, to_text
from ansible.module_utils.common.yaml import yaml_dump, yaml_load from ansible.module_utils.common.yaml import yaml_dump, yaml_load
from ansible.module_utils.compat.version import LooseVersion
from ansible.module_utils.urls import open_url from ansible.module_utils.urls import open_url
from ansible.playbook.role.requirement import RoleRequirement from ansible.playbook.role.requirement import RoleRequirement
from ansible.utils.display import Display from ansible.utils.display import Display
@ -53,6 +55,7 @@ class GalaxyRole(object):
def __init__(self, galaxy, api, name, src=None, version=None, scm=None, path=None): def __init__(self, galaxy, api, name, src=None, version=None, scm=None, path=None):
self._metadata = None self._metadata = None
self._metadata_dependencies = None
self._requirements = None self._requirements = None
self._install_info = None self._install_info = None
self._validate_certs = not context.CLIARGS['ignore_certs'] self._validate_certs = not context.CLIARGS['ignore_certs']
@ -120,6 +123,24 @@ class GalaxyRole(object):
return self._metadata return self._metadata
@property
def metadata_dependencies(self):
"""
Returns a list of dependencies from role metadata
"""
if self._metadata_dependencies is None:
self._metadata_dependencies = []
if self.metadata is not None:
self._metadata_dependencies = self.metadata.get('dependencies') or []
if not isinstance(self._metadata_dependencies, MutableSequence):
raise AnsibleParserError(
f"Expected role dependencies to be a list. Role {self} has meta/main.yml with dependencies {self._metadata_dependencies}"
)
return self._metadata_dependencies
@property @property
def install_info(self): def install_info(self):
""" """
@ -405,4 +426,7 @@ class GalaxyRole(object):
break break
if not isinstance(self._requirements, MutableSequence):
raise AnsibleParserError(f"Expected role dependencies to be a list. Role {self} has meta/requirements.yml {self._requirements}")
return self._requirements return self._requirements

@ -72,6 +72,7 @@ class RoleMetadata(Base, CollectionSearch):
raise AnsibleParserError("Expected role dependencies to be a list.", obj=self._ds) raise AnsibleParserError("Expected role dependencies to be a list.", obj=self._ds)
for role_def in ds: for role_def in ds:
# FIXME: consolidate with ansible-galaxy to keep this in sync
if isinstance(role_def, string_types) or 'role' in role_def or 'name' in role_def: if isinstance(role_def, string_types) or 'role' in role_def or 'name' in role_def:
roles.append(role_def) roles.append(role_def)
continue continue

@ -194,6 +194,70 @@ popd # ${galaxy_testdir}
rm -fr "${galaxy_testdir}" rm -fr "${galaxy_testdir}"
rm -fr "${HOME}/.ansible/roles/${galaxy_local_test_role}" rm -fr "${HOME}/.ansible/roles/${galaxy_local_test_role}"
# Galaxy install test case (expected failure)
#
# Install role with a meta/requirements.yml that is not a list of roles
mkdir -p "${role_testdir}"
pushd "${role_testdir}"
ansible-galaxy role init --init-path . unsupported_requirements_format
cat <<EOF > ./unsupported_requirements_format/meta/requirements.yml
roles:
- src: git+file:///${galaxy_local_test_role_git_repo}
EOF
tar czvf unsupported_requirements_format.tar.gz unsupported_requirements_format
set +e
ansible-galaxy role install -p ./roles unsupported_requirements_format.tar.gz 2>&1 | tee out.txt
rc="$?"
set -e
# Test that installing the role was an error
[[ ! "$rc" == 0 ]]
grep out.txt -qe 'Expected role dependencies to be a list.'
# Test that the role was not installed to the expected directory
[[ ! -d "${HOME}/.ansible/roles/unsupported_requirements_format" ]]
popd # ${role_testdir}
rm -rf "${role_testdir}"
# Galaxy install test case (expected failure)
#
# Install role with meta/main.yml dependencies that is not a list of roles
mkdir -p "${role_testdir}"
pushd "${role_testdir}"
ansible-galaxy role init --init-path . unsupported_requirements_format
cat <<EOF > ./unsupported_requirements_format/meta/main.yml
galaxy_info:
author: Ansible
description: test unknown dependency format (expected failure)
company: your company (optional)
license: license (GPL-2.0-or-later, MIT, etc)
min_ansible_version: 2.1
galaxy_tags: []
dependencies:
roles:
- src: git+file:///${galaxy_local_test_role_git_repo}
EOF
tar czvf unsupported_requirements_format.tar.gz unsupported_requirements_format
set +e
ansible-galaxy role install -p ./roles unsupported_requirements_format.tar.gz 2>&1 | tee out.txt
rc="$?"
set -e
# Test that installing the role was an error
[[ ! "$rc" == 0 ]]
grep out.txt -qe 'Expected role dependencies to be a list.'
# Test that the role was not installed to the expected directory
[[ ! -d "${HOME}/.ansible/roles/unsupported_requirements_format" ]]
popd # ${role_testdir}
rm -rf "${role_testdir}"
# Galaxy install test case # Galaxy install test case
# #
# Ensure that if both a role_file and role_path is provided, they are both # Ensure that if both a role_file and role_path is provided, they are both

Loading…
Cancel
Save