繁体   English   中英

如果不满足某些条件,如何跳过 ansible 剧本中的所有其他剧本?

[英]How to skip all other plays in ansible playbook if some condition is not met?

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

所以对于下面的例子 - 如果我在Play1中找不到任何新文件,那么我根本不想执行Play2Play3 (它应该跳过它)。 我怎样才能做到这一点?

我在end_play中有 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来在 controller 上运行一些任务是可以理解的,但您并不真的需要这个。 在要在 controller 上运行的步骤上使用delegate_to: localhostrun_once: true是一种更好的方法。
  2. 如果您真的想以这种方式 go (使用hosts: localhost ),出于某种原因,那么您需要使用set_fact保存find的返回值,以便在全局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 ,因为如果您将任务委托给另一台主机,则无需运行十次,如果您的主机组中有十台主机。

这是一个关于这个的小例子

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

在您可以看到的地方,我通过结束播放跳过了最后一条调试消息,当时我结束了前一步在我的主机组中拥有的三个主机中的两个。

该剧本的 Output :

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  

在 output 中,您可以轻松发现委托,output 也是如此

changed: [host1 -> localhost]

当非委派任务只是 go

changed: [host1]

使用主机变量

我想说这种方法比现有技术的 state 少一点,但如果您想在边缘情况下委托,可能会变得很方便。 我以前用过它,所以它并不是没有最终无法成为正确解决方案的情况。

这是示例

---
- 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结果中注册的变量find_result运行meta来结束播放

这是这个的 output

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   

尝试使用仅在您执行第一个任务后触发您的后两个任务的块:

https://docs.ansible.com/ansible/latest/user_guide/playbooks_blocks.html

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

  - name: Play 2 & 3 if Play 1 has a file
    block:
      - 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
    when: files != ""
...

在主机值中使用变量

您可以使用的一个技巧是为 Play1 中的其他播放设置目标主机的值,这样您可以将其设置为您的库存中不存在的值(在下面显示的情况下为 DONOTEXECUTE),其他播放将被简单地跳过

- 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

      - name: Copy file, if found
        copy:
          src: "some stuff here"
          dest: "some other stuff here"
        when: files.files|count > 0
        
     - name: end_plays
        set_fact:
            play2_hosts: DONOTEXECUTE
            play3_hosts: DONOTEXECUTE
        when: files.files|count == 0
        
      - name: continue_plays
        set_fact:
            play2_hosts: all
            play3_hosts: 127.0.0.1
        when: files.files|count > 0

- name: Play 2
  hosts: "{{hostvars['localhost']['play2_hosts']}}"
  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: "{{hostvars['localhost']['play3_hosts']}}"
  tasks:
      - name: execute command
        shell: ./data_init --init_file ./goldy.init.qa
        args:
          chdir: /var/lib/jenkins/jobs/process/workspace/data_init/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM