How to specify dependecies to Ansible Galaxy roles from other roles? - ansible

I've specified dependency for my role by declaring it inside meta/main.yml.
---
dependencies:
- role: angstwad.docker_ubuntu
src: https://github.com/angstwad/docker.ubuntu
scm: git
version: v2.3.0
However when I try to execute Ansible playbook I'm seeing error message:
ERROR! the role 'angstwad.docker_ubuntu' was not found in /home/.../ansible/roles:/etc/ansible/roles:/home/.../ansible/roles:/home/.../ansible
The error appears to have been in '/home/.../roles/docker-node/meta/main.yml': line 5, column 5, but may be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- role: angstwad.docker_ubuntu
^ here
From the error message I conclude that external role angstwad.docker_ubuntu hasn't be imported, even if it has been explicitly mentioned in docker-node/meta/main.yml.
Can I specify external dependencies from Ansible Galaxy even if my role itself has not been uploaded to Ansible Galaxy?
Or do I need to explicitly import them using ansible-galaxy?
From Ansible documentation:
Roles can also be dependent on other roles, and when you install a
role that has dependencies, those dependenices will automatically be
installed.
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 username.role_name. The more complex
format used in requirements.yml is also supported, allowing you to
provide src, scm, version and name.
By following suggestions from another SO question (How to automatically install Ansible Galaxy roles?) it sounds like downloading external dependencies needs to be done explicitly either manually or with workaround.

If the role that has this dependency is itself being installed via ansible-galaxy, then revise meta/main.yml to look like this:
---
dependencies:
- src: https://github.com/angstwad/docker.ubuntu.git
scm: git
version: v2.3.0
Thus, when installing the primary role the docker.ubuntu role will automatically be installed in ~/.ansible/roles/docker.ubuntu and it will run when the playbook is executed.
If the role that has this dependency will NOT be installed via ansible-galaxy, that is, if the dependency is the only thing being installed via the ansible-galaxy command, then docker.ubuntu will have to be installed separately, e.g.
ansible-galaxy install git+https://github.com/angstwad/docker.ubuntu.git
or
ansible-galaxy install git+https://github.com/angstwad/docker.ubuntu.git -p /path_to/my_playbook/roles
This will place the role in your search path (again, ~/.ansible/roles/docker.ubuntu if not specified via -p). In this scenario, revise meta/main.yml to this:
---
dependencies:
- role: docker.ubuntu
Note that when pulling your role from github, it lands as docker.ubuntu vs docker_ubuntu. See https://galaxy.ansible.com/docs/using/installing.html#dependencies for more. Hope this helps.

As per documentation you linked, you see:
When dependencies are encountered by ansible-galaxy, it will automatically install each dependency to the roles_path.
Downloading of dependencies is handled by ansible-galaxy only, the src meta information doesn't affect ansible-playbook, which just looks inside your role directory and if it don't see a corresponding folder - it fails. As in answer in question you linked, you can indeed create a first task, or include in you playbook to run ansible galaxy before each start.

Related

Can I create Ansible role in one project and then import it in diferent projects

I want to build Ansible role that then can be used by different Ansible project/s. I want to avoid coping code of role every time. Is there some better way? And I do not want to publicly publish code of the role.
Yes you can import a role directly from a Git repo.
# requirements.yml file
- src: <link to git repo>
Then execute the command:
ansible-galaxy install -r requirements.yml
Or even simpler:
ansible-galaxy install git+<link to .git version of repository>
These are of course only two of many ways. Check the link above for more details.

Unable to override role name with meta/main.yml role_name for molecule test

I created an example role project with this command:
molecule init role cranberry --driver-name docker
If you pull it:
git clone git#github.com:natemarks/cranberry.git
and run it:
make clean-venv && make molecule-test
It should set up the virtualenv and run the test successfully because it uses the project directory name 'cranberry' as the role name. If I want to override that so that my role_name is still 'cranberry' but my project directory is 'role-cranberry'. I should be able to just rename/move the project directory to 'role-cranberry' and set meta/main.yaml role_name: cranberry. This doesn't work.
similarly , I should be able to break the test without changing the project directory by just adding some garbage value to meta/main.yml role_name,like;
galaxy_info:
role_name: badrole
but that doesn't work either.
I think I'm using the latest python packages. Thanks in advance for tips
You are mixing up two things: the repository name in which the role is versioned remotely and the directory name in which the role is stored on your disk and which makes-up the name by which ansible knows that role on your local machine.
The role_name in your metadata only gives an indication to https://galaxy.ansible.com (i.e. the online service) of which name it should use when importing it. That name will be used later if you install the role from the ansible-galaxy command line (e.g. ansible-galaxy role install geerlingguy.security).
When molecule runs from your current role dir, it adds the current directory to the ANSIBLE_ROLES_PATH. From there, ansible is simply doing a normal role lookup and will know your current role after its containing directory name.
You gave as an example a role and its molecule test security by Jeff Geerling. The git repository name is ansible-role-security.
If you do a basic clone (git clone https://github.com/geerlingguy/ansible-role-security) and run the test from the freshly cloned directory (cd ansible-role-security && molecule test), it will fail complaining that geerlingguy.security was not found.
If you rename the directory to the expected name (cd .. && mv ansible-role-security geerlinguy.security && cd geerlinguy.security && molecule test), it will now succeed.
Note that the best practice to import such a role is to install it through ansible galaxy either by
installing it from the galaxy web site
ansible-galaxy role install geerlingguy.security
installing it from a git repo using a requirement file
roles/requirements.yml
- src: https://github.com/geerlingguy/ansible-role-security
scm: git
version: main
name: geerlingguy.security
Install role keeping the scm metadata (to interact with git, commit...)
ansible-galaxy role install -fgr roles/requirements.yaml
To finish with, you can have a look at the ci-pipeline in the same example repository where you will see that the author has forced the working directory name as well as the git clone directory target to align the directory name to what is expected for running the tests.

Is there a way to use galaxy roles without downloading them?

I'm running ansible within terraform.
I downloaded a galaxy role using:
ansible-galaxy install <role>
This downloaded it to my ~/.ansible/roles directory.
But when I referenced the role name in my ansible playbook that I use with terraform, it couldn't find it.
So instead I specified a directory like so:
ansible-galaxy install --roles-path . <role>
While this now works, it's mixed in with all my other scripts that are under source control.
I'm wondering if there's a way to use a galaxy role without actually downloading it? Or if there's a way to specify in my ansible playbook where to look for additional roles besides my roles?
Since Ansible only knows how to retrieve roles from the local filesystem, you must download roles before you can use them.
You can tell Ansible where to look for roles by setting the ANSIBLE_ROLES_PATH environment variable, or by setting roles_path in your ansible.cfg. See the documentation for details.

Always run ansible role before other role

I'm trying to find my way out of a dependency thicket. I'm using Ansible 1.9.2.
In a single playbook, I want to be able to install a Galaxy role (in the event, the Datadog.datadog role) and configure it. But Ansible always barfs; since the Datadog.datadog role doesn't exist until another role that I wrote installs the Galaxy role, it won't execute. This is how I'd really like it to be, cutting out the other roles that my playbook uses:
- hosts: all
roles:
- install_datadog
- (some other roles...)
- { role: Datadog.datadog, sudo: true }
vars:
datadog_api_key: "somekey"
I have tried all of the following, and none of them work for installing the Ansible Galaxy Datadog.datadog role first:
Having an earlier block in the same playbook that runs my install_datadog role.
Using an 'include' statement earlier in the playbook that includes the install_datadog role's main.yml.
Creating a pre_task statement in the above playbook.
Defining a role dependency doesn't make sense, because Datadog.datadog doesn't exist yet, so I can't define any dependencies in it. There is always an error akin to this:
ERROR: cannot find role in /etc/ansible/roles/Datadog.datadog
The only thing I can get to work is executing the install_datadog role in a prior run. This is not a great solution, as previously one playbook that had many execution blocks and role invocations configured our whole environment; this would require the execution of two playbooks in a specific order, which is highly inelegant.
So in a single run, how do I resolve a Galaxy role that won't exist until an earlier role has run to install it?
Make sure that your roles_path is correct. The roles_path variable in ansible.cfg specifies where ansible will look for roles, and the --roles-path option to ansible-galaxy will specify where the datadog role gets installed.
For example, my install task looks like this:
ansible-galaxy install Datadog.datadog --roles-path=/usr/home/vagrant
and in my ansible.cfg file I have this line:
roles_path = /vagrant/ansible/roles:/usr/home/vagrant

Run tasks in ansible before pre provisioning

I have a set of taks in my playbook that I would like to run before ansible checks to see if roles exist. (One installs roles from galaxy and github) Right now, it appears, that ansible checks if all of the roles referenced exist prior to running ANY tasks because I get fatal errors saying those roles don't cannot be found. Can I define a task that can be run before this pre-provisioning? I would like to do this via ansible and not have to put it in a bash script that runs before my playbook.
It would be a great way to automate downloading Galaxy dependencies and ensuring the latest/correct version of all roles is installed. Unfortunately this is not possible.
I tried this with
pre_tasks
playbook-includes
conditional playbook-includes
But it's all the same. The playbook is first completely parsed and resolved (includes, roles) before the first task is executed.

Resources