如果不满足某些条件,如何跳过ansible剧本中的所有其他剧本? [英] How to skip all other plays in ansible playbook if some condition is not met?
问题描述
我在下面的剧本中有多个剧本.如果不满足某些条件,我想忽略所有其他播放.
因此对于下面的示例-如果在Play1
中找不到任何新文件,那么我根本就不想执行Play2
和Play3
(应该跳过它).我该怎么办?
我在Play1中有end_play
,但它只跳过了Play1
,它仍然执行Play2
和Play3
---
- name: Play 1
hosts: 127.0.0.1
tasks:
- name: find the latest file
find: paths=/var/lib/jenkins/jobs/process/workspace/files
file_type=file
age=-1m
age_stamp=mtime
register: files
- meta: end_play
when: files.files|count == 0
- name: Copy file, if found
copy:
src: "some stuff here"
dest: "some other stuff here"
when: files.files|count > 0
- name: Play 2
hosts: all
serial: 5
tasks:
- name: copy latest file
copy: src=data_init/goldy.init.qa dest=/data01/admin/files/goldy.init.qa owner=golden group=golden
- name: copy latest file
copy: src=data_init/goldy.init.qa dest=/data02/admin/files/goldy.init.qa owner=golden group=golden
- name: Play 3
hosts: 127.0.0.1
tasks:
- name: execute command
shell: ./data_init --init_file ./goldy.init.qa
args:
chdir: /var/lib/jenkins/jobs/process/workspace/data_init/
更新:
所以块模块解决方案看起来不起作用,因为您不能像这样那样在块中使用嵌套播放.
有两种方法可以解决您的问题:
- 虽然您可以尝试定义
hosts: localhost
以便在控制器上运行某些任务,这是可以理解的,但实际上并不需要它.使用delegate_to: localhost
和set_fact
,以便借助全局在哪里可以看到,当我在上一步的主机组中拥有三台主机中的两台时,我通过结束播放跳过了最后一条调试消息.
该剧本的输出:
PLAY [hosts] ************************************************************************************************************************** TASK [Delegate directory creation to localhost] *************************************************************************************** ok: [host1 -> localhost] TASK [Create directory on hosts] **************************************************************************************************** ok: [host3] ok: [host2] ok: [host1] TASK [Delegate file creation to localhost] ******************************************************************************************** changed: [host1 -> localhost] TASK [Create file on hosts] **************************************************************************************************** changed: [host2] changed: [host1] changed: [host3] TASK [Delegate a find to localhost] *************************************************************************************************** ok: [host1 -> localhost] TASK [Find in the host for comparison] ************************************************************************************************ ok: [host1] ok: [host3] ok: [host2] TASK [List /test of localhost] ******************************************************************************************************** ok: [host1] => { "msg": [ "/test/localhost.txt" ] } ok: [host2] => { "msg": [ "/test/localhost.txt" ] } ok: [host3] => { "msg": [ "/test/localhost.txt" ] } TASK [List /test of host] ************************************************************************************************************* ok: [host1] => { "msg": [ "/test/host.txt" ] } ok: [host2] => { "msg": [ "/test/host.txt" ] } ok: [host3] => { "msg": [ "/test/host.txt" ] } TASK [Remove /test folder on localhost] *********************************************************************************************** changed: [host1 -> localhost] TASK [Delegate an empty find to localhost] ******************************************************************************************** ok: [host1 -> localhost] TASK [Here are our hostnames from the inventory] ************************************************************************************** ok: [host1] => { "msg": "host1" } ok: [host2] => { "msg": "host2" } ok: [host3] => { "msg": "host3" } TASK [debug] ************************************************************************************************************************** ok: [host1] => { "msg": "I am a sad message, because I will never display :'( But hopefully host1 likes me :')" } PLAY RECAP **************************************************************************************************************************** host1 : ok=12 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 host2 : ok=6 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 host3 : ok=6 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
在输出中,您可以轻松地发现委托,就像输出
changed: [host1 -> localhost]
当未委派的任务刚开始时
changed: [host1]
使用hostvars
我要说的是,这种方法比现有技术要少一些,但是如果您想委托边缘案例,它可能会派上用场.我以前使用过它,所以这并不是说不可能以正确的解决方案结束它.
这里是例子
--- - hosts: localhost gather_facts: false tasks: - name: Find in localhost find: path: /not/existing/folder file_type: any register: find - name: This will register the list under find.files as a variable on the host, making it accessible via hostvars set_fact: find_result: "{{ find.files }}" - meta: end_play when: find.files | count == 0 - debug: msg: I am the sanity check message, proving the end_play did happen - hosts: hosts gather_facts: false tasks: - name: Just to show we are not cheating with an empty host group, we display the hosts names debug: msg: "{{ inventory_hostname }}" - name: To show it is really our empty list and not an empty string or a null variable debug: msg: "{{ hostvars['localhost']['find_result'] }}" - meta: end_play when: "hostvars['localhost']['find_result'] | count == 0" - debug: msg: I am a first sanity check message, proving the end_play did happen - debug: msg: I am a second sanity check message, proving the end_play did happen - hosts: localhost gather_facts: false tasks: - name: To show it is really our empty list and not an empty string or a null variable debug: msg: "{{ hostvars['localhost']['find_result'] }}" - meta: end_play when: "hostvars['localhost']['find_result'] | count == 0" - debug: msg: I am a first sanity check message, proving the end_play did happen - debug: msg: I am a second sanity check message, proving the end_play did happen
您可以看到,在主机的每个新任务组的开头,我只是运行
meta
以结束播放,这是基于find
结果中注册的变量find_result
>这是这一个的输出
PLAY [localhost] ********************************************************************************************************************** TASK [Find in localhost] ************************************************************************************************************** ok: [localhost] TASK [This will register the list under find.files as a variable on the host, making it accessible via hostvars] ********************* ok: [localhost] PLAY [hosts] ************************************************************************************************************************** TASK [Just to show we are not cheating with an empty host group, we display the hosts names] ****************************************** ok: [host1] => { "msg": "host1" } ok: [host2] => { "msg": "host2" } ok: [host3] => { "msg": "host3" } TASK [To show it is really our empty list and not an empty string or a null variable] ************************************************ ok: [host1] => { "msg": [] } ok: [host2] => { "msg": [] } ok: [host3] => { "msg": [] } PLAY [localhost] ********************************************************************************************************************** TASK [To show it is really our empty list and not an empty string or a null variable] ************************************************ ok: [localhost] => { "msg": [] } PLAY RECAP **************************************************************************************************************************** host1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 host2 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 host3 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
I have multiple plays in below playbook. I want to ignore all other plays if some condition is not met.
So for below example - If I cannot find any new file in
Play1
then I don't want to executePlay2
andPlay3
at all (it should skip it). How can I do that?I have
end_play
in Play1 but it only skipsPlay1
and it still executesPlay2
andPlay3
--- - name: Play 1 hosts: 127.0.0.1 tasks: - name: find the latest file find: paths=/var/lib/jenkins/jobs/process/workspace/files file_type=file age=-1m age_stamp=mtime register: files - meta: end_play when: files.files|count == 0 - name: Copy file, if found copy: src: "some stuff here" dest: "some other stuff here" when: files.files|count > 0 - name: Play 2 hosts: all serial: 5 tasks: - name: copy latest file copy: src=data_init/goldy.init.qa dest=/data01/admin/files/goldy.init.qa owner=golden group=golden - name: copy latest file copy: src=data_init/goldy.init.qa dest=/data02/admin/files/goldy.init.qa owner=golden group=golden - name: Play 3 hosts: 127.0.0.1 tasks: - name: execute command shell: ./data_init --init_file ./goldy.init.qa args: chdir: /var/lib/jenkins/jobs/process/workspace/data_init/
Update:
So block module solution doesn't work looks like because you cannot use nested play in block like that..
解决方案There are two ways to approach your issue:
- Although it is understandable that you tried defining a
hosts: localhost
to run some tasks on the controller, you don't really need this. Usingdelegate_to: localhost
andrun_once: true
on the steps you want to run on your controller is a far better approach. - If you really want to go this way (using
hosts: localhost
), for some reason, then you'll need to save the return of yourfind
, withset_fact
in order to reuse it in other hosts with the help of the globalhostvars
Using delegation
Any task in the play can be delegated to another host. This is quite simple to do and would just use one extra
delegate_to
options on your task:- name: Delegate a find to localhost find: path: /test file_type: any register: localhost_find delegate_to: localhost run_once: true
When doing so, I would advice you to also use
run_once: true
, because, if you delegate the task to another host, there is no need to, let's say run it ten times if you have ten hosts in your host group.Here is a little example about that
--- - hosts: hosts become: true gather_facts: false tasks: - name: Delegate directory creation to localhost file: path: /test state: directory delegate_to: localhost run_once: true - name: Create directory on hosts file: path: /test state: directory - name: Delegate file creation to localhost file: path: /test/localhost.txt state: touch delegate_to: localhost run_once: true - name: Create file on hosts file: path: /test/host.txt state: touch - name: Delegate a find to localhost find: path: /test file_type: any register: localhost_find delegate_to: localhost run_once: true - name: Find in the hosts for comparison find: path: /test file_type: any register: host_find - name: List /test of localhost debug: msg: "{{ localhost_find.files | map(attribute='path') | list }}" - name: List /test of host debug: msg: "{{ host_find.files | map(attribute='path') | list }}" - name: Remove /test folder on localhost file: path: /test state: absent delegate_to: localhost run_once: true - name: Delegate an empty find to localhost find: path: /test file_type: any register: empty_find delegate_to: localhost run_once: true - name: Here are our hostnames from the inventory debug: msg: "{{ inventory_hostname }}" - name: I am the evil host killer meta: end_host when: empty_find.files | count == 0 and inventory_hostname != 'host1' - debug: msg: "I am a sad message, because I will never display :'( But hopefully host1 likes me :')" - name: I am the evil playbook killer meta: end_play when: empty_find.files | count == 0 - debug: msg: "I am a sad message, because I will never display :'( No one likes me..."
Where you can see, that, I am skipping the very last debug message by ending the play, when I ended two out of the three hosts I have in my hosts group on the step before.
Output of that playbook:
PLAY [hosts] ************************************************************************************************************************** TASK [Delegate directory creation to localhost] *************************************************************************************** ok: [host1 -> localhost] TASK [Create directory on hosts] **************************************************************************************************** ok: [host3] ok: [host2] ok: [host1] TASK [Delegate file creation to localhost] ******************************************************************************************** changed: [host1 -> localhost] TASK [Create file on hosts] **************************************************************************************************** changed: [host2] changed: [host1] changed: [host3] TASK [Delegate a find to localhost] *************************************************************************************************** ok: [host1 -> localhost] TASK [Find in the host for comparison] ************************************************************************************************ ok: [host1] ok: [host3] ok: [host2] TASK [List /test of localhost] ******************************************************************************************************** ok: [host1] => { "msg": [ "/test/localhost.txt" ] } ok: [host2] => { "msg": [ "/test/localhost.txt" ] } ok: [host3] => { "msg": [ "/test/localhost.txt" ] } TASK [List /test of host] ************************************************************************************************************* ok: [host1] => { "msg": [ "/test/host.txt" ] } ok: [host2] => { "msg": [ "/test/host.txt" ] } ok: [host3] => { "msg": [ "/test/host.txt" ] } TASK [Remove /test folder on localhost] *********************************************************************************************** changed: [host1 -> localhost] TASK [Delegate an empty find to localhost] ******************************************************************************************** ok: [host1 -> localhost] TASK [Here are our hostnames from the inventory] ************************************************************************************** ok: [host1] => { "msg": "host1" } ok: [host2] => { "msg": "host2" } ok: [host3] => { "msg": "host3" } TASK [debug] ************************************************************************************************************************** ok: [host1] => { "msg": "I am a sad message, because I will never display :'( But hopefully host1 likes me :')" } PLAY RECAP **************************************************************************************************************************** host1 : ok=12 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 host2 : ok=6 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 host3 : ok=6 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
In the output, you can easily spot the delegation, as is will output
changed: [host1 -> localhost]
When a non-delegated task would just go
changed: [host1]
Using hostvars
I would say the approach is a little bit less state of the art, but could become handy if you would like to delegate on edge cases. I have used it before, so it is not like there is no situation where it could not end up has being the right solution.
Here is the example
--- - hosts: localhost gather_facts: false tasks: - name: Find in localhost find: path: /not/existing/folder file_type: any register: find - name: This will register the list under find.files as a variable on the host, making it accessible via hostvars set_fact: find_result: "{{ find.files }}" - meta: end_play when: find.files | count == 0 - debug: msg: I am the sanity check message, proving the end_play did happen - hosts: hosts gather_facts: false tasks: - name: Just to show we are not cheating with an empty host group, we display the hosts names debug: msg: "{{ inventory_hostname }}" - name: To show it is really our empty list and not an empty string or a null variable debug: msg: "{{ hostvars['localhost']['find_result'] }}" - meta: end_play when: "hostvars['localhost']['find_result'] | count == 0" - debug: msg: I am a first sanity check message, proving the end_play did happen - debug: msg: I am a second sanity check message, proving the end_play did happen - hosts: localhost gather_facts: false tasks: - name: To show it is really our empty list and not an empty string or a null variable debug: msg: "{{ hostvars['localhost']['find_result'] }}" - meta: end_play when: "hostvars['localhost']['find_result'] | count == 0" - debug: msg: I am a first sanity check message, proving the end_play did happen - debug: msg: I am a second sanity check message, proving the end_play did happen
Where you can see that, at the beginning of each new tasks group for a host, I just run the
meta
to end the play, based on the variablefind_result
registered out of thefind
resultHere is the output for this one
PLAY [localhost] ********************************************************************************************************************** TASK [Find in localhost] ************************************************************************************************************** ok: [localhost] TASK [This will register the list under find.files as a variable on the host, making it accessible via hostvars] ********************* ok: [localhost] PLAY [hosts] ************************************************************************************************************************** TASK [Just to show we are not cheating with an empty host group, we display the hosts names] ****************************************** ok: [host1] => { "msg": "host1" } ok: [host2] => { "msg": "host2" } ok: [host3] => { "msg": "host3" } TASK [To show it is really our empty list and not an empty string or a null variable] ************************************************ ok: [host1] => { "msg": [] } ok: [host2] => { "msg": [] } ok: [host3] => { "msg": [] } PLAY [localhost] ********************************************************************************************************************** TASK [To show it is really our empty list and not an empty string or a null variable] ************************************************ ok: [localhost] => { "msg": [] } PLAY RECAP **************************************************************************************************************************** host1 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 host2 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 host3 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
这篇关于如果不满足某些条件,如何跳过ansible剧本中的所有其他剧本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- Although it is understandable that you tried defining a