如果不满足某些条件,如何跳过 ansible 剧本中的所有其他剧本? [英] How to skip all other plays in ansible playbook if some condition is not met?

查看:39
本文介绍了如果不满足某些条件,如何跳过 ansible 剧本中的所有其他剧本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在下面的剧本中有多个剧本.如果不满足某些条件,我想忽略所有其他播放.

I have multiple plays in below playbook. I want to ignore all other plays if some condition is not met.

所以对于下面的例子 - 如果我在 Play1 中找不到任何新文件,那么我不想执行 Play2Play3 在全部(它应该跳过它).我该怎么做?

So for below example - If I cannot find any new file in Play1 then I don't want to execute Play2 and Play3 at all (it should skip it). How can I do that?

我在 Play1 中有 end_play 但它只跳过 Play1 而它仍然执行 Play2Play3

I have end_play in Play1 but it only skips Play1 and it still executes Play2 and 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/

更新:

所以块模块解决方案看起来不起作用,因为你不能像那样在块中使用嵌套播放..

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:

  1. 尽管您尝试定义一个 hosts: localhost 来在控制器上运行一些任务是可以理解的,但您实际上并不需要它.使用 delegate_to: localhostrun_once: true在控制器上运行的步骤是一个更好的方法.
  2. 如果你真的想走这条路(使用hosts: localhost),出于某种原因,那么你需要保存你的find的返回,用set_fact 按顺序在全局 hostvars
  1. Although it is understandable that you tried defining a hosts: localhost to run some tasks on the controller, you don't really need this. Using delegate_to: localhost and run_once: true on the steps you want to run on your controller is a far better approach.
  2. If you really want to go this way (using hosts: localhost), for some reason, then you'll need to save the return of your find, with set_fact in order to reuse it in other hosts with the help of the global hostvars

<小时>

使用委托

剧中的任何任务都可以委托给其他主持人.这很简单,只需在您的任务中使用一个额外的 delegate_to 选项:

- name: Delegate a find to localhost
  find: 
    path: /test
    file_type: any
  register: localhost_find
  delegate_to: localhost
  run_once: true

这样做时,我建议您也使用 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.

该剧本的输出:

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.

这是例子

---
- 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

您可以看到,在主机的每个新任务组开始时,我只是根据变量 find_result 运行 meta 来结束播放注册出find结果

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 variable find_result registered out of the 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   

这篇关于如果不满足某些条件,如何跳过 ansible 剧本中的所有其他剧本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆