死磕ansible系列--when函数的作用

when

可以使用when做条件判断

1
2
3
4
tasks:
- name: "shut down Debian flavored systems"
command: /sbin/shutdown -t now
when: ansible_facts['os_family'] == "Debian"

同时我们可以使用 or 来指定多个条件语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
tasks:
- name: "shut down CentOS 6 and Debian 7 systems"
command: /sbin/shutdown -t now
when: (ansible_facts['distribution'] == "CentOS" and ansible_facts['distribution_major_version'] == "6") or
(ansible_facts['distribution'] == "Debian" and ansible_facts['distribution_major_version'] == "7")
````

我们可以写多行来实现and的情况

```yaml
tasks:
- name: "shut down CentOS 6 systems"
command: /sbin/shutdown -t now
when:
- ansible_facts['distribution'] == "CentOS"
- ansible_facts['distribution_major_version'] == "6"

假设我们要忽略一个语句的错误,然后根据成功或失败决定有条件地执行某项操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
tasks:
- command: /bin/false
register: result
ignore_errors: True

- command: /bin/something
when: result is failed

# In older versions of ansible use ``success``, now both are valid but succeeded uses the correct tense.
- command: /bin/something_else
when: result is succeeded

- command: /bin/still/something_else
when: result is skipped

var 可以使用 ‘yes’, ‘on’, ‘1’, ‘true’ 这些值设置bool值,然后进行规制判断。

1
2
3
vars:
epic: true
monumental: "yes"
1
2
3
tasks:
- shell: echo "This certainly is epic!"
when: epic or monumental|bool
1
2
3
tasks:
- shell: echo "This certainly isn't epic!"
when: not epic

可以判断当前变量是否定义来执行相应的条件

1
2
3
4
5
6
tasks:
- shell: echo "I've got '{{ foo }}' and am not afraid to use it!"
when: foo is defined

- fail: msg="Bailing out. this play requires 'bar'"
when: bar is undefined

when函数可以结合loop函数一起使用

1
2
3
4
tasks:
- command: echo {{ item }}
loop: [ 0, 2, 4, 6, 8, 10 ]
when: item > 5
1
2
3
- command: echo {{ item }}
loop: "{{ mylist|default([]) }}"
when: item > 5

loop 可以是个字典

1
2
3
- command: echo {{ item.key }}
loop: "{{ query('dict', mydict|default({})) }}"
when: item.value > 5

when 条件还可以在 role incloud import 下使用

1
2
- import_tasks: tasks/sometasks.yml
when: "'reticulating splines' in output"
1
2
3
4
- hosts: webservers
roles:
- role: debian_stock_config
when: ansible_facts['os_family'] == 'Debian'

当我们使用incloud_*的时候,它仅适用于包含任务本身,而不适用于包含文件中的任何其他任务。例子如下

1
2
3
4
5
6
7
8
9
10
11
12
# We wish to include a file to define a variable when it is not
# already defined

# main.yml
- import_tasks: other_tasks.yml # note "import"
when: x is not defined

# other_tasks.yml
- set_fact:
x: foo
- debug:
var: x

上面的配置,等同于

1
2
3
4
5
6
- set_fact:
x: foo
when: x is not defined
- debug:
var: x
when: x is not defined

因此,如果最初未定义x,则将跳过调试任务。通过使用include_tasks而不是import_tasks,other_tasks.yml中的两个任务都将按预期执行。

有些时候我们希望一个playbook可以应用多个操作系统。我们可以这是配置

1
2
3
4
5
6
7
8
9
---
- hosts: all
remote_user: root
vars_files:
- "vars/common.yml"
- [ "vars/{{ ansible_facts['os_family'] }}.yml", "vars/os_defaults.yml" ]
tasks:
- name: make sure apache is started
service: name={{ apache }} state=started
1
2
3
4
---
# for vars/RedHat.yml
apache: httpd
somethingelse: 42

Register Variables 可以和when一起使用

1
2
3
4
5
6
7
8
9
10
- name: test play
hosts: all

tasks:

- shell: cat /etc/motd
register: motd_contents

- shell: echo "motd contains the word hi"
when: motd_contents.stdout.find('hi') != -1
1
2
3
- hosts: webservers
roles:
- { role: debian_stock_config, when: ansible_os_family == 'Debian' }

register 中有个stdout_lines的变量,可以帮你将结果按照split做切割。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- name: registered variable usage as a loop list
hosts: all
tasks:

- name: retrieve the list of home directories
command: ls /home
register: home_dirs

- name: add home dirs to the backup spooler
file:
path: /mnt/bkspool/{{ item }}
src: /home/{{ item }}
state: link
loop: "{{ home_dirs.stdout_lines }}"
# same as loop: "{{ home_dirs.stdout.split() }}"

也可以判断 stdout 是否为空

1
2
3
4
5
6
7
8
9
10
11
12
13
- name: check registered variable for emptiness
hosts: all

tasks:

- name: list contents of directory
command: ls mydir
register: contents

- name: check contents for emptiness
debug:
msg: "Directory is empty"
when: contents.stdout == ""
1
2
3
4
5
6
7
8
- name: test play
hosts: mfs
tasks:
- shell: cat /etc/motd
register: motd_contents

- shell: echo "motd contains the word hi" > /tmp/test2
when: motd_contents.stdout.find('hi') != -1

changed_when

1
2
3
4
5
6
7
8
tasks:
- shell: /usr/bin/billybass --mode="take me to the river"
register: bass_result
changed_when: "bass_result.rc != 2"

# this will never report 'changed' status
- shell: wall 'beep'
changed_when: False

failed_when

1
2
3
4
- name: this command prints FAILED when it fails
command: /usr/bin/example-command -x -y -z
register: command_result
failed_when: "'FAILED' in command_result.stderr"
1
2
3
4
5
6
7
8
  - name: this command prints FAILED when it fails
command: /usr/bin/example-command -x -y -z
register: command_result
ignore_errors: True

- name: fail the play if the previous command did not succeed
fail: msg="the command failed"
when: "'FAILED' in command_result.stderr"