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

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

问题描述

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

因此对于下面的示例-如果在Play1中找不到任何新文件,那么我根本就不想执行Play2Play3(应该跳过它).我该怎么办?

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

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

更新:

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

解决方案

有两种方法可以解决您的问题:

  1. 虽然您可以尝试定义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 execute Play2 and Play3 at all (it should skip it). How can I do that?

    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/
    

    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:

    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


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

    Here 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屋!

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