Update ansible-galaxy to handle role requirements (#68288)
* Update galaxy role object to handle requirements Co-Authored-By: Sandra McCann <samccann@redhat.com>
This commit is contained in:
parent
d42151e676
commit
91bb5af688
5 changed files with 155 additions and 33 deletions
|
@ -0,0 +1,2 @@
|
|||
minor_changes:
|
||||
- ansible-galaxy - allow role to define dependency requirements that will be only installed by defining them in ``meta/requirements.yml`` (https://github.com/ansible/proposals/issues/57)
|
|
@ -363,10 +363,30 @@ command line, as follows:
|
|||
Dependencies
|
||||
------------
|
||||
|
||||
Roles can also be dependent on other roles, and when you install a role that has dependencies, those dependencies will automatically be installed.
|
||||
Roles can also be dependent on other roles, and when you install a role that has dependencies, those dependencies will automatically be installed to the ``roles_path``.
|
||||
|
||||
You specify role dependencies in the ``meta/main.yml`` file by providing a list of roles. If the source of a role is Galaxy, you can simply specify the role in
|
||||
the format ``namespace.role_name``. You can also use the more complex format in ``requirements.yml``, allowing you to provide ``src``, ``scm``, ``version``, and ``name``.
|
||||
There are two ways to define the dependencies of a role:
|
||||
|
||||
* using ``meta/requirements.yml``
|
||||
* using ``meta/main.yml``
|
||||
|
||||
Using ``meta/requirements.yml``
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
`.. versionadded:: 2.10`
|
||||
|
||||
You can create the file ``meta/requirements.yml`` and define dependencies in the same format used for :file:`requirements.yml` described in the `Installing multiple roles from a file`_ section.
|
||||
|
||||
From there, you can import or include the specified roles in your tasks.
|
||||
|
||||
Using ``meta/main.yml``
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Alternatively, you can specify role dependencies in the ``meta/main.yml`` file by providing a list of roles under the ``dependencies`` section. If the source of a role is Galaxy, you can simply specify the role in
|
||||
the format ``namespace.role_name``. You can also use the more complex format in :file:`requirements.yml`, allowing you to provide ``src``, ``scm``, ``version``, and ``name``.
|
||||
|
||||
Dependencies installed that way, depending on other factors described below, will also be executed **before** this role is executed during play execution.
|
||||
To better understand how dependencies are handled during play execution, see :ref:`playbooks_reuse_roles`.
|
||||
|
||||
The following shows an example ``meta/main.yml`` file with dependent roles:
|
||||
|
||||
|
@ -425,8 +445,6 @@ Alternately, you can specify the role dependencies in the complex form used in
|
|||
src: git+https://github.com/geerlingguy/ansible-role-composer.git
|
||||
version: 775396299f2da1f519f0d8885022ca2d6ee80ee8
|
||||
|
||||
When dependencies are encountered by ``ansible-galaxy``, it will automatically install each dependency to the ``roles_path``. To understand how dependencies are handled during play execution, see :ref:`playbooks_reuse_roles`.
|
||||
|
||||
.. note::
|
||||
|
||||
Galaxy expects all role dependencies to exist in Galaxy, and therefore dependencies to be specified in the
|
||||
|
|
|
@ -1057,7 +1057,7 @@ class GalaxyCLI(CLI):
|
|||
if not role.metadata:
|
||||
display.warning("Meta file %s is empty. Skipping dependencies." % role.path)
|
||||
else:
|
||||
role_dependencies = role.metadata.get('dependencies') or []
|
||||
role_dependencies = (role.metadata.get('dependencies') or []) + role.requirements
|
||||
for dep in role_dependencies:
|
||||
display.debug('Installing dep %s' % dep)
|
||||
dep_req = RoleRequirement()
|
||||
|
|
|
@ -47,11 +47,13 @@ class GalaxyRole(object):
|
|||
SUPPORTED_SCMS = set(['git', 'hg'])
|
||||
META_MAIN = (os.path.join('meta', 'main.yml'), os.path.join('meta', 'main.yaml'))
|
||||
META_INSTALL = os.path.join('meta', '.galaxy_install_info')
|
||||
META_REQUIREMENTS = (os.path.join('meta', 'requirements.yml'), os.path.join('meta', 'requirements.yaml'))
|
||||
ROLE_DIRS = ('defaults', 'files', 'handlers', 'meta', 'tasks', 'templates', 'vars', 'tests')
|
||||
|
||||
def __init__(self, galaxy, api, name, src=None, version=None, scm=None, path=None):
|
||||
|
||||
self._metadata = None
|
||||
self._requirements = None
|
||||
self._install_info = None
|
||||
self._validate_certs = not context.CLIARGS['ignore_certs']
|
||||
|
||||
|
@ -371,3 +373,25 @@ class GalaxyRole(object):
|
|||
}
|
||||
"""
|
||||
return dict(scm=self.scm, src=self.src, version=self.version, name=self.name)
|
||||
|
||||
@property
|
||||
def requirements(self):
|
||||
"""
|
||||
Returns role requirements
|
||||
"""
|
||||
if self._requirements is None:
|
||||
self._requirements = []
|
||||
for meta_requirements in self.META_REQUIREMENTS:
|
||||
meta_path = os.path.join(self.path, meta_requirements)
|
||||
if os.path.isfile(meta_path):
|
||||
try:
|
||||
f = open(meta_path, 'r')
|
||||
self._requirements = yaml.safe_load(f)
|
||||
except Exception:
|
||||
display.vvvvv("Unable to load requirements for %s" % self.name)
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
break
|
||||
|
||||
return self._requirements
|
||||
|
|
|
@ -12,36 +12,72 @@ ansible-galaxy --version
|
|||
# Need a relative custom roles path for testing various scenarios of -p
|
||||
galaxy_relative_rolespath="my/custom/roles/path"
|
||||
|
||||
# Prep the local git repo with a role and make a tar archive so we can test
|
||||
# different things
|
||||
galaxy_local_test_role="test-role"
|
||||
galaxy_local_test_role_dir=$(mktemp -d)
|
||||
galaxy_local_test_role_git_repo="${galaxy_local_test_role_dir}/${galaxy_local_test_role}"
|
||||
galaxy_local_test_role_tar="${galaxy_local_test_role_dir}/${galaxy_local_test_role}.tar"
|
||||
pushd "${galaxy_local_test_role_dir}"
|
||||
ansible-galaxy init "${galaxy_local_test_role}"
|
||||
pushd "${galaxy_local_test_role}"
|
||||
git init .
|
||||
|
||||
# Prep git, becuase it doesn't work inside a docker container without it
|
||||
git config user.email "tester@ansible.com"
|
||||
git config user.name "Ansible Tester"
|
||||
|
||||
git add .
|
||||
git commit -m "local testing ansible galaxy role"
|
||||
git archive \
|
||||
--format=tar \
|
||||
--prefix="${galaxy_local_test_role}/" \
|
||||
master > "${galaxy_local_test_role_tar}"
|
||||
popd # "${galaxy_local_test_role}"
|
||||
popd # "${galaxy_local_test_role_dir}"
|
||||
|
||||
# Status message function (f_ to designate that it's a function)
|
||||
f_ansible_galaxy_status()
|
||||
{
|
||||
printf "\n\n\n### Testing ansible-galaxy: %s\n" "${@}"
|
||||
}
|
||||
|
||||
# Use to initialize a repository. Must call the post function too.
|
||||
f_ansible_galaxy_create_role_repo_pre()
|
||||
{
|
||||
repo_name=$1
|
||||
repo_dir=$2
|
||||
|
||||
pushd "${repo_dir}"
|
||||
ansible-galaxy init "${repo_name}"
|
||||
pushd "${repo_name}"
|
||||
git init .
|
||||
|
||||
# Prep git, because it doesn't work inside a docker container without it
|
||||
git config user.email "tester@ansible.com"
|
||||
git config user.name "Ansible Tester"
|
||||
|
||||
# f_ansible_galaxy_create_role_repo_post
|
||||
}
|
||||
|
||||
# Call after f_ansible_galaxy_create_repo_pre.
|
||||
f_ansible_galaxy_create_role_repo_post()
|
||||
{
|
||||
repo_name=$1
|
||||
repo_tar=$2
|
||||
|
||||
# f_ansible_galaxy_create_role_repo_pre
|
||||
|
||||
git add .
|
||||
git commit -m "local testing ansible galaxy role"
|
||||
|
||||
git archive \
|
||||
--format=tar \
|
||||
--prefix="${repo_name}/" \
|
||||
master > "${repo_tar}"
|
||||
popd # "${repo_name}"
|
||||
popd # "${repo_dir}"
|
||||
}
|
||||
|
||||
# Prep the local git repos with role and make a tar archive so we can test
|
||||
# different things
|
||||
galaxy_local_test_role="test-role"
|
||||
galaxy_local_test_role_dir=$(mktemp -d)
|
||||
galaxy_local_test_role_git_repo="${galaxy_local_test_role_dir}/${galaxy_local_test_role}"
|
||||
galaxy_local_test_role_tar="${galaxy_local_test_role_dir}/${galaxy_local_test_role}.tar"
|
||||
|
||||
f_ansible_galaxy_create_role_repo_pre "${galaxy_local_test_role}" "${galaxy_local_test_role_dir}"
|
||||
f_ansible_galaxy_create_role_repo_post "${galaxy_local_test_role}" "${galaxy_local_test_role_tar}"
|
||||
|
||||
galaxy_local_parent_role="parent-role"
|
||||
galaxy_local_parent_role_dir=$(mktemp -d)
|
||||
galaxy_local_parent_role_git_repo="${galaxy_local_parent_role_dir}/${galaxy_local_parent_role}"
|
||||
galaxy_local_parent_role_tar="${galaxy_local_parent_role_dir}/${galaxy_local_parent_role}.tar"
|
||||
|
||||
# Create parent-role repository
|
||||
f_ansible_galaxy_create_role_repo_pre "${galaxy_local_parent_role}" "${galaxy_local_parent_role_dir}"
|
||||
|
||||
cat <<EOF > meta/requirements.yml
|
||||
- src: git+file:///${galaxy_local_test_role_git_repo}
|
||||
EOF
|
||||
f_ansible_galaxy_create_role_repo_post "${galaxy_local_parent_role}" "${galaxy_local_parent_role_tar}"
|
||||
|
||||
# Galaxy install test case
|
||||
#
|
||||
# Install local git repo
|
||||
|
@ -55,6 +91,7 @@ pushd "${galaxy_testdir}"
|
|||
[[ -d "${HOME}/.ansible/roles/${galaxy_local_test_role}" ]]
|
||||
popd # ${galaxy_testdir}
|
||||
rm -fr "${galaxy_testdir}"
|
||||
rm -fr "${HOME}/.ansible/roles/${galaxy_local_test_role}"
|
||||
|
||||
# Galaxy install test case
|
||||
#
|
||||
|
@ -71,6 +108,45 @@ pushd "${galaxy_testdir}"
|
|||
popd # ${galaxy_testdir}
|
||||
rm -fr "${galaxy_testdir}"
|
||||
|
||||
# Galaxy install test case
|
||||
#
|
||||
# Install local git repo with a meta/requirements.yml
|
||||
f_ansible_galaxy_status "install of local git repo with meta/requirements.yml"
|
||||
galaxy_testdir=$(mktemp -d)
|
||||
pushd "${galaxy_testdir}"
|
||||
|
||||
ansible-galaxy install git+file:///"${galaxy_local_parent_role_git_repo}" "$@"
|
||||
|
||||
# Test that the role was installed to the expected directory
|
||||
[[ -d "${HOME}/.ansible/roles/${galaxy_local_parent_role}" ]]
|
||||
|
||||
# Test that the dependency was also installed
|
||||
[[ -d "${HOME}/.ansible/roles/${galaxy_local_test_role}" ]]
|
||||
|
||||
popd # ${galaxy_testdir}
|
||||
rm -fr "${galaxy_testdir}"
|
||||
rm -fr "${HOME}/.ansible/roles/${galaxy_local_parent_role}"
|
||||
rm -fr "${HOME}/.ansible/roles/${galaxy_local_test_role}"
|
||||
|
||||
# Galaxy install test case
|
||||
#
|
||||
# Install local git repo with a meta/requirements.yml + --no-deps argument
|
||||
f_ansible_galaxy_status "install of local git repo with meta/requirements.yml + --no-deps argument"
|
||||
galaxy_testdir=$(mktemp -d)
|
||||
pushd "${galaxy_testdir}"
|
||||
|
||||
ansible-galaxy install git+file:///"${galaxy_local_parent_role_git_repo}" --no-deps "$@"
|
||||
|
||||
# Test that the role was installed to the expected directory
|
||||
[[ -d "${HOME}/.ansible/roles/${galaxy_local_parent_role}" ]]
|
||||
|
||||
# Test that the dependency was not installed
|
||||
[[ ! -d "${HOME}/.ansible/roles/${galaxy_local_test_role}" ]]
|
||||
|
||||
popd # ${galaxy_testdir}
|
||||
rm -fr "${galaxy_testdir}"
|
||||
rm -fr "${HOME}/.ansible/roles/${galaxy_local_test_role}"
|
||||
|
||||
# Galaxy install test case
|
||||
#
|
||||
# Ensure that if both a role_file and role_path is provided, they are both
|
||||
|
@ -112,13 +188,16 @@ rm -fr "${galaxy_testdir}"
|
|||
#
|
||||
# Basic tests to ensure listing roles works
|
||||
|
||||
f_ansible_galaxy_status \
|
||||
"role list"
|
||||
f_ansible_galaxy_status "role list"
|
||||
galaxy_testdir=$(mktemp -d)
|
||||
pushd "${galaxy_testdir}"
|
||||
ansible-galaxy install git+file:///"${galaxy_local_test_role_git_repo}" "$@"
|
||||
|
||||
ansible-galaxy role list | tee out.txt
|
||||
ansible-galaxy role list test-role | tee -a out.txt
|
||||
|
||||
[[ $(grep -c '^- test-role' out.txt ) -eq 2 ]]
|
||||
popd # ${galaxy_testdir}
|
||||
|
||||
# Galaxy role test case
|
||||
#
|
||||
|
@ -185,7 +264,6 @@ f_ansible_galaxy_status \
|
|||
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
|
||||
#
|
||||
|
|
Loading…
Add table
Reference in a new issue