Skip to content
Permalink
Browse files
validate meta/main.yml dependencies and meta/requirements.yml are bot…
…h lists before concatenating them together (#77821)
  • Loading branch information
s-hertel committed May 19, 2022
1 parent e85e8ee commit 400475acc033ea146c8dc4929e347166ee85c0e6
Showing 5 changed files with 95 additions and 3 deletions.
@@ -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 @@ def _execute_install_role(self, requirements):
# install dependencies, if we want them
if not no_deps and installed:
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)
else:
role_dependencies = (role.metadata.get('dependencies') or []) + role.requirements
role_dependencies = role.metadata_dependencies + role.requirements
for dep in role_dependencies:
display.debug('Installing dep %s' % dep)
dep_req = RoleRequirement()
@@ -27,14 +27,16 @@
import os
import tarfile
import tempfile
from ansible.module_utils.compat.version import LooseVersion

from collections.abc import MutableSequence
from shutil import rmtree

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.module_utils._text import to_native, to_text
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.playbook.role.requirement import RoleRequirement
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):

self._metadata = None
self._metadata_dependencies = None
self._requirements = None
self._install_info = None
self._validate_certs = not context.CLIARGS['ignore_certs']
@@ -120,6 +123,24 @@ def metadata(self):

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
def install_info(self):
"""
@@ -405,4 +426,7 @@ def requirements(self):

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
@@ -72,6 +72,7 @@ def _load_dependencies(self, attr, ds):
raise AnsibleParserError("Expected role dependencies to be a list.", obj=self._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:
roles.append(role_def)
continue
@@ -194,6 +194,70 @@ popd # ${galaxy_testdir}
rm -fr "${galaxy_testdir}"
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
#
# Ensure that if both a role_file and role_path is provided, they are both

0 comments on commit 400475a

Please sign in to comment.