Ansible how to use tasks multiple times in different roles? - ansible

I have 3 tasks that will get the version from the database and I have 3 roles inside these roles few tasks have a dependency on the version.
I can't use a variable here because the value is dynamic and I cant set facts because I should be able to run individual roles and only a few tasks from each role with tags.
My Example below.
Role1:-
Tasks I need to run multiple times(example):-
- name: get version
block:
- command: "mongo get_version.js"
register: op
- name: filter version number from output
shell: "echo {{ present_version.stdout }}| grep 'version'"
register: present_version
tags: role1_db_tag
- name: do something
- name: do something when a version is something
when: present_version == "something"
tags: role1_db_tag
Role2:
- name: get version
block:
- command: "mongo get_version.js"
register: op
- name: filter version number from output
shell: "echo {{ present_version.stdout }}| grep 'version'"
register: present_version
tags: role2_db_tag
- name: do some other things
- name: do something else when a version is something
when: present_version == "something"
tags: role2_db_tag
Now I am running the get version tasks 3 times in each role now.
Is there any way like handlers just to mention some name for these repetitive tasks and call when required?
Expecting:-
Role2:
- name: fetch version
function: get_version
register: present_version
tags: role1_db_tag
- name: do something else when a version is something
when: present_version == "something"
tags: role2_db_tag
PS: Is there a better way than include_* or import_*.

As you have already surmised, the way you would typically handle this is by moving the get version task into a separate role, and then including that in the dependent roles using e.g. import_role:
- import_role:
name: get_version
If you have a number of small shared tasks, you can create a "library" role with multiple task files:
- import_role:
name: library
tasks_from: get_version
See "Using Roles" for a discussion of include_role vs import_role.
You can get similar behavior by adding a dependency to your role
instead. E.g., in Role1, create a file meta/main.yml with the
following content:
dependencies:
- get_version
This will automatically run the get_version role before role1 any
time you run role1.
See "Using Role Dependencies" for more information.

Related

Ansible run role based on condition

I'm using Ansible to install an agent on Linux servers. There are different install procedures based on if the system is running systemd or initd. I created a role for both install procedures, but I want to see if the server is running systemd or initd first and then run the corresponding role. Below is the code I have created. Will this type of conditional work this way or am I missing the mark?
tasks:
- name: check if running initd or systemd and role the correct role
command: pidof systemd
register: pid_systemd
- name: check if running initd or systemd and role the correct role
command: pidof /sbin/init
register: pid_initd
- include_role:
name: install-appd-machine-agent-initd
when: pid_initd.stdout == '1'
- include_role:
name: install-appd-machine-agent-systemd
when: pid_systemd.stdout == '1'
Ansible collects facts of a system using gather_facts via setup module. This provides a magic variable called ansible_service_mgr. This variable can be used to conditionally execute tasks.
For example, to run your roles conditionally:
tasks:
- include_role:
name: install-appd-machine-agent-initd
when: ansible_service_mgr == "sysvinit"
- include_role:
name: install-appd-machine-agent-systemd
when: ansible_service_mgr == "systemd"

Ansible roles and tags

I have some issues tagging tasks in roles.
I need to put some sql in sync mode, update some for patching with other hosts, and after etc
When i run my playbook i pass the tags different ways. I tried all sort of ways
Ans in the roles tasks i tag the tasks in the files with the tags i want to associate
When i use a main.yml, it tried to run all the tasks in the main regardless of the tagging, for the first host on the first line
When i dont use a main.yml or its empty the hosts tagging works but it does not run the playbook, only gather facts
here is my playbook:
---
- name: put sql in sync mode
hosts: v1sql02d
roles:
- role: winupdates
tags: [ sync ]
- name: update sql not on primary
hosts: v3sqlax01d, v3sql01d, v1sql03d
roles:
- role: winupdates
tags: [ updates ]
here is my main.yml
- name: run sql ag sync tasks
include: winagsync.yml tags=sync
- name: update sql on secondary
include: winupdates.yml tags=updates
here is my first task in tasks
win_shell: |
Set-ExecutionPolicy RemoteSigned
Powershell lines
tags:
- sync
and my winupdate one
win_updates:
state: searched
server_selection: default
register: update_count
debug: var=update_count
log_path: c:\ansible_win_updates.log
tags:
- updates
- name: Install Updates, Security and Critical
win_updates:
state: installed
server_selection: default
register: update_count
debug: var=update_count
log_path: c:\ansible_win_updates.log
reboot: yes
tags:
- updates
Please enlight me or help me
Thanks
Theoneakta

How to set an Ansible tag from within a playbook?

I would like to skip some of the plays based on a conditional value.
I could have a task at the beginning that would skip some of the other tasks when a condition is met.
I know I could always use set_fact and use this as a condition to run the other plays (roles and tasks) or evaluate the said condition directly in each play I want to skip.
However, since the plays already have a tagging system in place, is there something like set_tags in Ansible that I could leverage on to avoid having to add conditions all over my plays and bloat my already heavy playbook.
Something such as:
- name: skip terraform tasks if no file is provided
hosts: localhost
tasks:
set_tags:
- name: terraform
state: skip
when: terraform_files == ""
The two plays I'd like to skip:
- name: bootstrap a testing infrastructure
hosts: localhost
roles:
- role: terraform
state: present
tags:
- create_servers
- terraform
[...]
- name: flush the testing infrastructure
hosts: localhost
roles:
- role: terraform
state: absent
tags:
- destroy_servers
- terraform
If I understood correctly, the following should do the job:
- name: bootstrap a testing infrastructure
hosts: localhost
roles:
- role: terraform
state: present
when: terraform_files != ""
tags:
- create_servers
- terraform
[...]
- name: flush the testing infrastructure
hosts: localhost
roles:
- role: terraform
state: absent
when: terraform_files != ""
tags:
- destroy_servers
- terraform
This is basically the same as setting the when clause on every single tasks in the role. So each task will be inspected but skipped if the condition is false.

Starting role from "tasks/alternate.yml" instead of "tasks/main.yml"

I have a large playbook that uses multiple roles to setup new servers. I'd like to re-use the playbook but for the decommission stage instead of calling into role_name/tasks/main.yml and having a lot of when: statements, I'd like to tell Ansible to call the role but start in role_name/tasks/decommission.yml.
As a first test I setup my main.yml file like this:
- name: "Provisioning new server"
block:
- name: "Include the provisioning steps."
include_tasks: provision.yml
when:
- not decom
- name: "DECOM - Unregister from Satellite server"
block:
- name: "DECOM - Include the deprovision steps."
include_tasks: decommission.yml
when:
- decom
But that's getting really ugly to maintain. Is this possible or am I overlooking an alternative way to setup the playbook?
Q: "Tell Ansible to call the role but start in role_name/tasks/decommission.yml"
A: Use include_role
- include_role:
name: role_name
tasks_from: decommission.yml
,or import_role
- import_role:
name: role_name
tasks_from: decommission.yml
See Re-using files and roles on what is the difference between including and importing a role.

Ansible: Skips "always" tags in roles

I have a playbook which calls multiple roles I have written. This playbook has each role tagged so than I can call them separately or run the entire procedure from start to end. Within the roles additional tags may be provided to break up the works within those as well. Some of the role tasks are tagged with "always" because I want them to execute whenever the role is ran, regardless of any role specific tags.
The problem I am running into is that these "always" tags execute whether the role specific tag is called or not. If I don't call the tag for a role, I don't want to role to execute at all, including any "always" tasks specific to that role.
Example:
# Playbook
- hosts: localhost
roles:
- role: roleA
tags: do_roleA
- role: roleB
tags: do_roleB
# Role A:
- name: Always do this when doing role A
debug: msg="test"
tags: always
- name: Task1
debug: msg="task1"
tags: do_task1
- name: Task2
debug: msg="task2"
tags: do_task2
Example call:
ansibile-playbook my-playbook.yml --tags "do_roleB"
But this causes the debug in Role A to occur as well.
Some requirements I have:
Can not skip "always" as roleB may have some tasks that require it.
Do not want to change the tag from always and add a list of tags for every sub task. i.e. [do_task1,do_task2] as the number of tags would become large and easy to forget to add one.
Basically I am looking for a way to tell Ansible, if I call a "playbook tag" execute only roles from the playbook where the tag matches; do not execute any of the tasks in roles that do not match, even if they are tagged with "always". But if I call a "role tag" execute all the tasks in that role which either have tags of "always" or the tag I called.
Does Ansible have a feature like this? If it helps I am using Ansible 2.0.1.0
Keep in mind that applying tag do_roleA to a role adds do_roleA tag to every task in that role.
So your example role actually becomes:
# Role A:
- name: Always do this when doing role A
debug: msg="test"
tags:
- always
- do_roleA
- name: Task1
debug: msg="task1"
tags:
- do_task1
- do_roleA
- name: Task2
debug: msg="task2"
tags:
- do_task2
- do_roleA
You can remove always tag from that task, so after tagging a role with do_roleA it will be the only tag for that task.
So calling playbook with -t do_roleB will not execute that task.
For anybody who might land on this page having the same issue -- the solution is to use untagged:
playbook.yaml
- name: Preparing gateway node
hosts: "{{ hosts }}"
serial: 1
remote_user: root
any_errors_fatal: true
tasks:
- include_role:
name: my-role
tags: [ untagged, install, config, my-role-enable-service ]
my-role/tasks/main.yaml
- name: Task 1
debug:
msg: "Run when tags: untagged and config"
tags: [ untagged, config ]
- name: Task 2
debug:
msg: "Run when tags: untagged and install"
tags: [ untagged, install ]
- name: Task 3
debug:
msg: "Run when tags: my-role-enable-service"
tags: [ untagged, my-role-enable-service ]
When you run:
ansible-playbook playbook.yaml -- runs all tasks
ansible-playbook playbook.yaml --tags config -- runs only Task 1
ansible-playbook playbook.yaml --tags install -- runs only Task 2
ansible-playbook playbook.yaml --tags my-role-enable-service -- runs only Task 3
This quickly becomes handy when you have all-in-one roles that does installation or building from source in conjunction with configuration.
You can simply use --tags config after the installation steps have completed to speed-up your playbook instead of having to wait for things to build from sources every time.

Resources