如何在没有错误的情况下退出Ansible playbook

时间:2016-04-06 12:54:34

标签: ansible

当我遇到某种情况时,我想退出而没有错误(我知道assertfail模块)。以下代码退出但失败:

  tasks:

    - name: Check if there is something to upgrade
      shell: if apt-get --dry-run upgrade | grep -q "0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded"; then echo "no"; else echo "yes"; fi
      register: upgrading

    - name: Exit if nothing to upgrade
      fail: msg="Nothing to upgrade"
      when: upgrading.stdout == "no"

6 个答案:

答案 0 :(得分:43)

在Ansible 2.2中,您可以将end_playmeta模块一起使用:

- meta: end_play

您还可以指定when有条件地结束播放:

- meta: end_play
  when: upgrading.stdout == "no"

但请注意,无论播放是否实际结束,任务都未列在ansible-playbook的输出中。此外,该任务不计入回顾中。所以,你可以这样做:

- block:
    - name: "end play if nothing to upgrade"
      debug:
        msg: "nothing to upgrade, ending play"

    - meta: end_play
  when: upgrading.stdout == "no"

只有在满足条件时才会在结束之前宣布播放结束。如果不满足条件,您将看到名为end play if nothing to upgrade的任务被适当跳过,这将为用户提供更多关于游戏结束或不结束的信息。

当然,这只会结​​束当前的播放,而不是剧本中所有剩余的播放。

答案 1 :(得分:3)

更好,更合乎逻辑的解决方法可能是反过来而不是失败,如果没有任何升级(这是一个单独的步骤只做那个)你可以附加条件依赖的所有升级任务在upgrade变量上。实质上只需添加

when: upgrading.changed

应该只在升级期间执行的任务。

这是一项更多的工作,但它也带来了清晰度和自我包含影响其内部任务的逻辑,而不是取决于某些方式可能会或可能不会提前终止它。

答案 2 :(得分:3)

让我们使用Tymoteusz建议的角色:

将你的游戏分成两个roles,其中第一个角色将执行检查(并设置一些变量保持检查的结果),第二个角色将根据检查结果进行操作。

我已使用以下内容创建aaa.yaml

---
- hosts: all
  remote_user: root
  roles:
    - check
    - { role: doit, when: "check.stdout == '0'" }
...

然后check中的角色roles/check/tasks/main.yaml

---
- name: "Check if we should continue"
  shell:
    echo $(( $RANDOM % 2 ))
  register: check
- debug:
    var: check.stdout
...

然后doit中的角色roles/doit/tasks/main.yaml

---
- name: "Do it only on systems where check returned 0"
  command:
    date
...

这就是输出:

TASK [check : Check if we should continue] *************************************
Thursday 06 October 2016  21:49:49 +0200 (0:00:09.800)       0:00:09.832 ****** 
changed: [capsule.example.com]
changed: [monitoring.example.com]
changed: [satellite.example.com]
changed: [docker.example.com]

TASK [check : debug] ***********************************************************
Thursday 06 October 2016  21:49:55 +0200 (0:00:05.171)       0:00:15.004 ****** 
ok: [monitoring.example.com] => {
    "check.stdout": "0"
}
ok: [satellite.example.com] => {
    "check.stdout": "1"
}
ok: [capsule.example.com] => {
    "check.stdout": "0"
}
ok: [docker.example.com] => {
    "check.stdout": "0"
}

TASK [doit : Do it only on systems where check returned 0] *********************
Thursday 06 October 2016  21:49:55 +0200 (0:00:00.072)       0:00:15.076 ****** 
skipping: [satellite.example.com]
changed: [capsule.example.com]
changed: [docker.example.com]
changed: [monitoring.example.com]

它并不完美:看起来你会继续看到跳过系统的所有任务的跳过状态,但可能会有所帮助。

答案 3 :(得分:1)

以下内容对我的情况很有帮助,因为meta: end_play似乎停止了所有主机的执行,而不仅仅是匹配的主机。

首先确定一个事实:

- name: Determine current version
  become: yes
  slurp:
    src: /opt/app/CHECKSUM
  register: version_check
  ignore_errors: yes

- set_fact:
  is_update_needed: "{{ ( version_check['checksum'] | b64decode != installer_file.stat.checksum)  }}"

现在包括那个只应在这种情况下执行的部分:

# update-app.yml can be placed in the same role folder
- import_tasks: update-app.yml
  when: is_update_needed

答案 4 :(得分:1)

只需注意一点:meta: end_play仅结束剧本,而不结束剧本。所以这本剧本:

---
- name: 1st play with end play
  hosts: localhost
  connection: local
  gather_facts: no
  tasks:
    - name: I'll always be printed
      debug:
        msg: next task terminates first play

    - name: Ending the 1st play now
      meta: end_play

    - name: I want to be printed!
      debug:
        msg: However I'm unreachable so this message won't appear in the output

- name: 2nd play
  hosts: localhost
  connection: local
  gather_facts: no
  tasks:
    - name: I will also be printed always
      debug:
        msg: "meta: end_play ended just the 1st play. This is 2nd one."

将产生以下输出:

$ ansible-playbook -i localhost, playbooks/end_play.yml 

PLAY [1st play with end play] **************************************************

TASK [I'll always be printed] **************************************************
ok: [localhost] => {
    "msg": "next task terminates first play"
}

PLAY [2nd play] ****************************************************************

TASK [I will also be printed always] *******************************************
ok: [localhost] => {
    "msg": "meta: end_play ended just the 1st play. This is 2nd one."
}

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

答案 5 :(得分:0)

您可以这样做,使断言条件为假

- name: WE ARE DONE. EXITING
  assert:
    that:
      - "'test' in 'stop'