Как пропустить все остальные пьесы в ANSIBLE Playbook, если какое-то условие не выполняется? - PullRequest
1 голос
/ 07 октября 2019

У меня есть несколько пьес в ниже Playbook. Я хочу игнорировать все другие воспроизведения, если какое-либо условие не выполняется.

Так, например, для приведенного ниже примера - если я не могу найти какой-либо новый файл в Play1, тогда я не хочу выполнять Play2 и Play3 вообще (это следует пропустить). Как я могу это сделать?

У меня есть end_play в Play1, но он пропускает только 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/

Обновление:

Таким образом, решение блочного модуля не работает, потому что вы не можете использовать вложенное воспроизведение в блоке, как этот ..

Ответы [ 2 ]

1 голос
/ 11 октября 2019

Существует два способа решения вашей проблемы:

  1. Хотя понятно, что вы пытались определить hosts: localhost для запуска некоторых задач на контроллере, вам это на самом деле не нужно. Использование delegate_to: localhost и run_once: true на шагах, которые вы хотите запустить на своем контроллере, является гораздо лучшим подходом.
  2. Если вы действительно хотите пойти по этому пути(используя hosts: localhost), по какой-то причине вам необходимо сохранить возврат вашего find с set_fact, чтобы повторно использовать его на других хостах с помощью глобального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..."

ГдеВы можете видеть, что я пропускаю самое последнее сообщение отладки, заканчивая воспроизведение, когда я завершил два из трех хостов, которые у меня есть в моей группе хостов на шаге до этого.

Вывод этой книги воспроизведения:

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_result, зарегистрированной из find результата

Вотвыход для этого

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   
0 голосов
/ 07 октября 2019

Попробуйте использовать блок, который запускает только ваши вторые две задачи после выполнения вашей первой:

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 != ""
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...