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
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 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.
I want to validate few things before i run my main play in Ansible. For example below command is taking 2 input arguments from the user so I want to validate them before executing the main tasks.
ansible-playbook -i my-inventory my-main.yml --tags=repodownload -e release_version=5.0.0-07 -e target_env=dev/prod/preprod
In the above case, release_version should not be empty and target_env must be these type of values -
5.0.0.34
I want to display a message to user about what is wrong. How do i achieve it?
Any help is appreciated.
If you absolutely need the user to provide the variables, I would first of all use vars_prompt so that the variable value is asked interactively if user forgot to provide them as extra vars. This also makes a good inline documentation.
Then you can use pre_tasks to validate the input that was provided, either interactively or as an extra var. For validation, I usually use the fail module. The point here is to use run_once: true to force the test to run only once even if there are several hosts in your play.
Here is an example based on your input. Adapt to your exact needs
---
- name: Prompt and validation demo
hosts: all
gather_facts: false
vars:
_allowed_envs:
- dev
- preprod
- prod
vars_prompt:
- name: release_version
prompt: "What is the release version ? [w.x.y-z]"
private: no
- name: target_env
prompt: "What is the target environment ? [{{ _allowed_envs | join(', ') }}]"
private: no
pre_tasks:
- name: Make sure version is ok
fail:
msg: >-
Release version is not formatted correctly. Please make sure
it is of the form w.x.y-zz
when: not release_version is regex('\d*(\.\d*){2}-\d\d')
run_once: true
- name: Make sure target_env is allowed
fail:
msg: >-
Environment "{{ target_env }}" is not allowed.
Please choose a target environment in {{ _allowed_envs | join(', ') }}
when: not target_env in _allowed_envs
run_once: true
tasks:
- name: "Dummy task just to have a complete playbook for the example"
debug:
msg: "Deploying version {{ release_version }} for environment {{ target_env }} on {{ inventory_hostname }}"
And here are some examples launching the playbook:
##########################
# Fully interactive runs #
##########################
$ ansible-playbook -i localhost, playbook.yml
What is the release version ? [w.x.y-z]: wrong
What is the target environment ? [dev, preprod, prod]: prod
PLAY [Prompt and validation demo] ************************************
TASK [Make sure version is ok] ***************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Release version is not formatted correctly. Please make sure it is of the form w.x.y-zz"}
NO MORE HOSTS LEFT ***************************************************
PLAY RECAP **********************************************************
localhost : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
$ ansible-playbook -i localhost, playbook.yml
What is the release version ? [w.x.y-z]: 1.2.3-44
What is the target environment ? [dev, preprod, prod]: dev
PLAY [Prompt and validation demo] ************************************
TASK [Make sure version is ok] ***************************************
skipping: [localhost]
TASK [Make sure target_env is allowed] *******************************
skipping: [localhost]
TASK [Dummy task just to have a complete playbook for the example] ***
ok: [localhost] => {
"msg": "Deploying version 1.2.3-44 for environment dev on localhost"
}
PLAY RECAP ***********************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
###############
# Hybrid run #
###############
$ ansible-playbook -i localhost, playbook.yml -e target_env=prod
What is the release version ? [w.x.y-z]: 1.2.3-44
PLAY [Prompt and validation demo] ************************************
TASK [Make sure version is ok] ***************************************
skipping: [localhost]
TASK [Make sure target_env is allowed] *******************************
skipping: [localhost]
TASK [Dummy task just to have a complete playbook for the example] ***
ok: [localhost] => {
"msg": "Deploying version 1.2.3-44 for environment prod on localhost"
}
PLAY RECAP ***********************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=2 rescued=0 ignored=0
###################
# Fully automated #
###################
$ ansible-playbook -i localhost, playbook.yml -e target_env=prod -e release_version=1.2.3-44
PLAY [Prompt and validation demo] ************************************
TASK [Make sure version is ok] ***************************************
skipping: [localhost]
TASK [Make sure target_env is allowed] *******************************
skipping: [localhost]
TASK [Dummy task just to have a complete playbook for the example] ***
ok: [localhost] => {
"msg": "Deploying version 1.2.3-44 for environment prod on localhost"
}
PLAY RECAP ***********************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=2 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
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)