I have an ansible role with this:
---
- import_tasks: foo.yml
when: ShouldRunFoo
If ShouldRunFoo == false then the file is skipped, but the console shows its tasks (as "skipped").
I could use the display_skipped_hosts = no config option, but that hides everything skipped in a playbook, not just foo.yml.
Is there a way to do this? I want to see skipped tasks, just not those from foo.yml (if it is skipped).
I struggled with that sometime ago and using different sources I found one approach that is not pretty clean but do the trick. (I am assuming you know about the display_skipped_hosts=no and you still want to print some of the skipped ones)
You can do a loop using Jinja expression to delete the messages from the debug output (The titles of the task will always be shown):
---
- hosts: all
tasks:
- name: task to skip and display
debug:
msg: "HELLO WORLD"
when: "'SOMETHING' in group_names"
- name: task to skip and not display
debug:
msg: "HELLO WORLD"
loop: "{% if 'SOMETHING' in group_names%} {{debug_list}}{% else %}[]{% endif %}"
If in a specific use case, you can use either import_tasks or include_tasks, then do this:
$ cat playbook.yml:
---
- hosts: localhost
tasks:
- name: subtasks will be printed
import_tasks: tasks.yml
when: false
- name: subtasks will not be printed
include_tasks: tasks.yml # <----------
when: false
$ cat tasks.yml:
---
- debug: msg=1
- debug: msg=2
- debug: msg=3
$ ansible-playbook playbook.yml:
PLAY [localhost] **************************************************************
TASK [Gathering Facts] ********************************************************
ok: [localhost]
TASK [debug] ******************************************************************
skipping: [localhost]
TASK [debug] ******************************************************************
skipping: [localhost]
TASK [debug] ******************************************************************
skipping: [localhost]
TASK [subtasks will not be printed] *******************************************
skipping: [localhost]
PLAY RECAP ********************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0
I imagine this will not always be applicable, so it's not a perfect solution.
Related
Is it possible during Ansible execution to add another host in the play, without starting a new play?
I am aware of the add_host module, but that requires the start of a new play to add the host, which is undesired.
No. By design, it's not possible to add hosts to 'in-flight play'. Quoting from the Summary of Ansible bug #59401:
By design, the in-flight play will not start running tasks on newly-added hosts, but it will stop running tasks on hosts that have disappeared. Newly-created hosts from an inventory refresh are immediately visible in ansible_play_hosts, even though they're not executing.
Notes
The bug claims refresh_inventory and add_host should have the same effects.
One might expect that the option refresh_inventory of the module meta does the job. The scenario would be:
Start a play
Modify the source of the inventory
Run - meta: refresh_inventory
Unfortunately, the example of the INI file below shows that this doesn't work. The host host03 is added to the inventory and to the list ansible_play_hosts_all as well. But, then, the following task debug doesn't run at this host. Play recap doesn't include this host either.
shell> cat hosts
[test]
host01
host02
The playbook below
shell> cat playbook.yml
- hosts: test
gather_facts: false
tasks:
- debug:
var: ansible_play_hosts_all
run_once: true
- community.general.ini_file:
path: hosts
section: test
option: "{{ item.host }}"
state: "{{ item.state }}"
allow_no_value: true
loop:
- {host: host03, state: present}
run_once: true
delegate_to: localhost
- meta: refresh_inventory
- debug:
var: ansible_play_hosts_all
run_once: true
- debug:
var: inventory_hostname
gives
shell> ansible-playbook -i hosts playbook.yml
PLAY [test] **********************************************************************************
TASK [debug] *********************************************************************************
ok: [host01] =>
ansible_play_hosts_all:
- host01
- host02
TASK [community.general.ini_file] ************************************************************
changed: [host01 -> localhost] => (item={'host': 'host03', 'state': 'present'})
TASK [meta] **********************************************************************************
TASK [debug] *********************************************************************************
ok: [host01] =>
ansible_play_hosts_all:
- host01
- host02
- host03
TASK [debug] *********************************************************************************
ok: [host01] =>
inventory_hostname: host01
ok: [host02] =>
inventory_hostname: host02
PLAY RECAP ***********************************************************************************
host01 : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
host02 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
I have the following folder-structure, inspired by the best-practices section in Ansibles documentation:
my-playbook.yml
my-role
|
|── tasks
|
|── my-task.yml
I have tagged the tasks within the my-task.yml file which is part of a role. I execute the playbook using ansible-playbook.yml --tags "mytag". Unfortunately, all tasks are skipped. Can I only filter tasks directly part of the playbook?
Within my playbook, I do something like
- hosts: ansible_server
connection: local
gather_facts: no
roles:
- validate_properties
Thanks in advance!
What you should do is call the role from a task by using the include_role module. On that task you can apply tags. Take this playbook, for example:
---
- name: Tag role test
hosts: local
connection: local
gather_facts: no
tasks:
- include_role:
name: debug
tags:
- dont_run
- debug:
msg: Solo shot first
tags:
- run
Where my role/debug consists of just a task that prints Hello, world!.
If you call this playbook directly you get this output:
PLAY [Tag role test]
TASK [debug : debug]
ok: [localhost] =>
msg: Hello, world!
TASK [debug]
ok: [localhost] =>
msg: Solo shot first
PLAY RECAP
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
But, if you exclude the dont_run task like this:
ansible-playbook tag_roles.yml --skip-tags dont_run
This is the output:
PLAY [Diff test]
TASK [debug]
ok: [localhost] =>
msg: Solo shot first
PLAY RECAP
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
I hope it helps.
You have to tag the subtasks also with your tag u want to run to:
Main Task:
- name: "test tags on sub task"
include_tasks: subtask.yml
with_items: "{{ myList }}"
loop_control:
label: item
tags: test
Sub task:
debug: msg="Sub Task"
tags: test
I am using the following ansible script to import a playbook based on the user input,
---
- hosts: localhost
vars_prompt:
- name: "cleanup"
prompt: "Do you want to run cleanup? Enter [yes/no]"
private: no
- name: run the cleanup yaml file
import_playbook: cleanup.yml
when: cleanup == "yes"
Execution log:
bash-$ ansible-playbook -i hosts cleanup.yml
Do you want to run cleanup? Enter [yes/no]: no
PLAY [localhost] *********************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************
ok: [127.0.0.1]
PLAY [master] ********************************************************************************************************************
TASK [Gathering Facts] ***************************************************************************************************************
fatal: [192.168.56.128]: FAILED! => {"msg": "The conditional check 'cleanup == \"yes\"' failed. The error was: error while evaluating conditional (cleanup == \"yes\"): 'cleanup' is undefined"}
to retry, use: --limit #/home/admin/playbook/cleanup.retry
PLAY RECAP ***************************************************************************************************************************
127.0.0.1 : ok=1 changed=0 unreachable=0 failed=0
192.168.56.128 : ok=0 changed=0 unreachable=0 failed=1
It throws error in the imported playbook not in the mail playbook.
Please help me to import a playbook based on user input.
vars_prompt variables are only defined in the play in which they were called. In order to use them in other plays, a workaround is to use set_fact to bind the variable to a host, then use hostvars to access that value from the second play.
For instance:
---
- hosts: localhost
vars_prompt:
- name: "cleanup"
prompt: "Do you want to run cleanup? Enter [yes/no]"
private: no
tasks:
- set_fact:
cleanup: "{{cleanup}}"
- debug:
msg: 'cleanup is available in the play using: {{cleanup}}'
- debug:
msg: 'cleanup is also available globally using: {{hostvars["localhost"]["cleanup"]}}'
- name: run the cleanup yaml file
import_playbook: cleanup.yml
when: hostvars["localhost"]["cleanup"] == True
The handlers I have are not being run by the playbook or tasks
I have the following directory structur:
<project>
- playbook.yml
- <roles>
-<handler>
- main.yml
-<meta>
-<tasks>
-main.yml
The problem is the handler is never called.
tasks/main.yml:
- name: run task1
command: run_task
notify: "test me now"
handler/main.yml:
- name: tested
register: val1
listen: "test me now"
The playbook just calls the task/main.yml and has host:all
Do I ned an include/import? I tried in playbook but it didn't help
The play below works
tasks:
- include_tasks: tasks/main.yml
- meta: flush_handlers
- debug: var=val1.stdout
handlers:
- import_tasks: handlers/main.yml
handlers must be imported to be present when the task notifies it.
tasks may be included, or imported.
A module is missing in handler/main.yml. This would cause:
ERROR! no action detected in task. This often indicates a misspelled module name, or incorrect module path.
Use some module in handler/main.yml. For example:
- name: tested
command: "echo 'running handler'"
register: val1
listen: "test me now"
Running such play gives
val1.stdout: running handler
Simplified example
Running the playbook below
shell> cat playbook.yml
- hosts: localhost
tasks:
- include_tasks: tasks/main.yml
handlers:
- import_tasks: handlers/main.yml
shell> cat tasks/main.yml
- command: date
register: result
notify: test me now
shell> cat handlers/main.yml
- name: test me now
debug:
msg: "{{ result.stdout }} Running handler."
gives
shell> ansible-playbook playbook.yml
PLAY [localhost] *****************************************************************************
TASK [Gathering Facts] ***********************************************************************
ok: [localhost]
TASK [include_tasks] *************************************************************************
included: /export/scratch/tmp8/test-801/tasks/main.yml for localhost
TASK [command] *******************************************************************************
changed: [localhost]
RUNNING HANDLER [test me now] ****************************************************************
ok: [localhost] =>
msg: Mon 25 Apr 2022 04:59:02 PM CEST Running handler.
PLAY RECAP ***********************************************************************************
localhost : ok=4 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
You should have the structure described in https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html thus the directory should be called handlers (and not handler)
I have a main.yaml like below:
- import_playbook: 1.yaml
- import_playbook: 2.yaml
vars:
allow2: False
when: allow2
I want the playbook 2.yaml can be skipped totally (not try to execute any tasks inside 2.yaml).
But it looks all tasks in 2.yaml will be called but not executed.
File 1.yaml:
- name: Go1
hosts: test
gather_facts: false
tasks:
- debug: msg="Message from 1.yaml"
File 2.yaml:
- name: Go2
hosts: test
gather_facts: false
tasks:
- debug: msg="Message from 2.yaml"
The output is:
$ ansible-playbook main.yaml
PLAY [Go1] ***********
TASK [debug] *********
Thursday 05 October 2017 03:10:12 -0400 (0:00:00.116) 0:00:00.116 ******
ok: [test1] => {}
MSG:
Message from 1.yaml
PLAY [Go2] ************
TASK [debug] ************
Thursday 05 October 2017 03:10:12 -0400 (0:00:00.090) 0:00:00.206 ******
skipping: [test1]
The you can say the task in 2.yaml also was called but skipped.
But I want no any tasks will be called in 2.yaml.
Is it possible?
No, this is not possible this way.
Please see answer at serverfault about import/include difference.
import_playbook is static, so it's always done and when statements attached to everything inside it.
In case you do not need any conditional format and just skip running the playbook 2.yaml you may use tags by modifying the main.yaml as the following:
- import_playbook: 1.yaml
- import_playbook: 2.yaml
tags: playbook_2
And run as by skipping tag playbook_2:
bill#inspiron:~/tmp_ansible$ ansible-playbook main.yaml --skip-tags=playbook_2
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
PLAY [Go1] **************************************************************************************************************************************************************************************
TASK [debug] ************************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": "Message from 1.yaml"
}
PLAY [Go2] **************************************************************************************************************************************************************************************
PLAY RECAP **************************************************************************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0