Always run ansible role before other role - ansible

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

Related

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.

Run an ansible task that is not included in the play, but is part of the role

I have a playbook that calls the active_directory role. Within the main.yml I do not call the rm_user task but would like to remove users in the event that I needed to via the CLI. Even tags don't work if the task is not included in the play.
is there a way to run tasks that are not included in the play (but are included in the active_directory role directory) via the CLI?
To answer your question:
Is there a way to run tasks that are not included in the play (but are included in the active_directory role directory) via the CLI?
Yes. There is include_role module.
You can run
# ansible -m include_role -a "name=active_directory tasks_from=file_you_chose.yml"

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

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.

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.

Can I install (or remove) Ansible role from Galaxy using ansible-pull?

I'm working with Ansible using ansible-pull (runs on cron).
Can I install Ansible role from Ansible Galaxy without login in to all computers (just by adding a command to my Ansible playbook)?
If I understand you correctly, you're trying to download and install roles from Ansible Galaxy from the command line, in a hands-off manner, possibly repeatedly (via cron). If this is the case, here's how you can do it.
# download the roles
ansible-galaxy install --ignore-errors f500.elasticsearch groover.packerio
# run ansible-playbook to install the roles downloaded from Ansible Galaxy
ansible-playbook -i localhost, -c local <(echo -e '- hosts: localhost\n roles:\n - { role: f500.elasticsearch, elasticsearch_cluster_name: "my elasticsearch cluster" }\n - { role: groover.packerio, packerio_version: 0.6.1 }\n')
Explanation / FYI:
To download roles from Ansible Galaxy, use ansible-galaxy, not ansible-pull. For details, see the manual. You can download multiple roles at once.
If the role had been downloaded previously, repeated attempts at downloading using ansible-galaxy install will result in an error. If you wish to call this command repeatedly (e.g. from cron), use --ignore-errors (skip the role and move on to the next item) or --force (force overwrite) to work around this.
When running ansible-playbook, we can avoid having to create an inventory file using -i localhost, (the comma at the end signals that we're providing a list, not a file).
-c local (same as --connection=local) means that we won't be connecting remotely but will execute commands on the localhost.
<() functionality is process substitution. The output of the command appears as a file, so we can feed a "virtual playbook file" into the ansible-playbook command without saving the playbook to the disk first (e.g., playbookname.yml).
As shown, it's possible to embed role variables, such as packerio_version: 0.6.1 and apply multiple roles in a single command.
Note that whitespace is significant in playbooks (they are YAML files). Just as in Python code, be careful about indentation. It's easy to make typos in long lines with echo -e and \n (newlines).
You can run updates of roles from Ansible Galaxy and ansible-playbook separately.
With a bit of magic, you don't have to create inventory files or playbooks (this can be useful sometimes). The solution to install Galaxy roles remotely via push is less hacky / cleaner but if you prefer to use cron and pulling then this can help.
I usually add roles from galaxy as submodules in my own repository; that way I have control over when I update them, and ansible-pull will automatically fetch them - removing the need to run ansible-galaxy.
E.g.:
mkdir roles
git submodule add https://github.com/groover/ansible-role-packerio roles/groover.packerio
Yes you can.
# install Ansible Galaxy requirements via the pull playbook itself
- hosts: localhost
tasks:
- command: ansible-galaxy install -r requirements.yml

Resources