对于一些比较复杂的内容,例如在shell当中,我们会使用各种条件判断来进行,在Ansible当中也是,Ansible可使用conditionals,在符合特定条件时执行任务或play。例如,可以利用一个条件在Ansible安装或配置服务前确定受管主机上的可用内存。
我们可以利用条件来区分不同的受管主机,并根据它们所符合的条件来分配功能角色。Playbook变量、注册的变量和Ansible事实都可通过条件来进行测试。可以使用比较字符串、数字数据和布尔值的运算符。
以下场景说明了在Ansible中使用条件的情况:
when语句用于有条件地运行任务。它取要测试的条件为真。如果条件满足,则运行任务。如果条件不满足,则跳过任务。
简单的条件语句案例:
这个条件语句的意思是当my_server生效时才安装httpd;如果设置成False那么my_server并不生效
---
- name: when test
hosts: servera
remote_user: root
vars:
my_server: False
tasks:
- name: "{{ my_server }} is installed"
yum:
name: httpd
state: latest
when: my_server
测试可执行性:
[student@servera ~]$ ansible-playbook test.yml
PLAY [when test] ***********************************************************************************
TASK [Gathering Facts]******************************************************** ********************
ok: [servera]
TASK [False is installed] **************************************************************************
skipping: [servera]
PLAY RECAP ***************************************************************************************
servera : ok=1 changed=0 unreachable=0 failed=0
# 测试执行时直接跳过了。
这里跳过的原因是因为要安装httpd服务的条件是my_server变量必须存在,而将my_server设置成False后,**my_server变量不生效就不满足when的条件,**所以即使这个playbook语法有问题也可以执行,但其中包含的任务是不能被执行的所以直接跳过了。
如果将False改为True:
[student@workstation ~]$ ansible-playbook -i hosts test.yml
---
- name: when test
hosts: servera
remote_user: root
vars:
my_server: True
tasks:
- name: "{{ my_server }} is installed"
yum:
name: httpd
state: latest
when: my_server
执行测试
PLAY [when test] ************************************************************************
TASK [Gathering Facts] ******************************************************************
ok: [servera]
TASK [True is installed] ****************************************************************
changed: [servera]
PLAY RECAP ******************************************************************************
servera : ok=2 changed=1 unreachable=0 failed=0
# 此时的状态变成了changed而不是skipped
当状态变为changed证明任务状态已经发生改变,httpd服务已经符合了安装条件
另一种写法(defined):
---
- name: when test
hosts: servera
remote_user: root
tasks:
- name: "ensure {{ my_server }} is installed"
yum:
name: "{{ my_server }}"
state: latest
when: my_server is defined
需要注意的是,这里的my_server变量依旧是没有被定义的
[student@servera ~]$ ansible-playbook test.yml
PLAY [when test] ***********************************************************************************
TASK [Gathering Facts] ****************************************************************************
ok: [servera]
TASK [ensure {{ my_server }} is installed] *******************************************************
skipping: [servera]
PLAY RECAP **************************************************************************************
servera : ok=1 changed=0 unreachable=0 failed=0
# 所以在执行测试时也跳过了任务
如果定义my_server而不赋值:
[student@servera ~]$ cat test.yml
---
- name: when test
hosts: servera
remote_user: root
vars:
my_server:
tasks:
- name: "ensure {{ my_server }} is installed"
yum:
name: "{{ my_server }}"
state: latest
when: my_server is defined
# 这里的条件是如果变量my_server被定义则执行安装的任务
执行测试:
[student@servera ~]$ ansible-playbook test.yml
PLAY [when test] ************************************************************************
TASK [Gathering Facts] ******************************************************************
ok: [servera]
TASK [ensure is installed] *************************************************************
fatal: [servera]: FAILED! => {"changed": false, "module_stderr": "Shared connection to servera closed.\r\n", "module_stdout": "Traceback (most recent call last):\r\n File \"/root/.ansible/tmp/ansible-tmp-1599491486.79-25931710335605/AnsiballZ_yum.py\", line 113, in <module>\r\n _ansiballz_main()\r\n File \"/root/.ansible/tmp/ansible-tmp-1599491486.79-25931710335605/AnsiballZ_yum.py\", line 105, in _ansiballz_main\r\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\r\n File \"/root/.ansible/tmp/ansible-tmp-1599491486.79-25931710335605/AnsiballZ_yum.py\", line 48, in invoke_module\r\n imp.load_module('__main__', mod, module, MOD_DESC)\r\n File \"/tmp/ansible_yum_payload_FaoojI/__main__.py\", line 1532, in <module>\r\n File \"/tmp/ansible_yum_payload_FaoojI/__main__.py\", line 1527, in main\r\n File \"/tmp/ansible_yum_payload_FaoojI/__main__.py\", line 374, in __init__\r\n File \"/tmp/ansible_yum_payload_FaoojI/ansible_yum_payload.zip/ansible/module_utils/yumdnf.py\", line 79, in __init__\r\nTypeError: 'NoneType' object is not iterable\r\n", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}
to retry, use: --limit @/home/student/test.retry
PLAY RECAP ******************************************************************************
servera : ok=1 changed=0 unreachable=0 failed=1
# 在执行测试时会这样报错
如果定义的变量,却不给变量赋值。那么这个playbook是不能成功执行的,因为yum模块当中name是不能定义为空的。
如果我们给变量赋值:
---
- name: when test
hosts: servera
remote_user: root
vars:
my_server: httpd
tasks:
- name: "ensure {{ my_server }} is installed"
yum:
name: "{{ my_server }}"
state: latest
when: my_server is defined
# 这里指定my_server为httpd
测试执行:
[student@servera ~]$ ansible-playbook test.yml
PLAY [when test] ************************************************************************
TASK [Gathering Facts] ******************************************************************
ok: [servera]
TASK [ensure httpd is installed] ********************************************************
changed: [servera]
PLAY RECAP ******************************************************************************
servera : ok=2 changed=1 unreachable=0 failed=0
# 执行测试成功
如果这样编写playbook:
---
- name: when test
hosts: servera
remote_user: root
vars:
my_server:
tasks:
- name: "ensure httpd is installed"
yum:
name: httpd
state: latest
when: my_server is defined
这里的条件是如果my_server变量为被定义则执行安装httpd的任务。在条件语句中只要满足when的条件就执行任务。
然后也添加了vars,这样就相当于定义了my_server,只不过此时my_server的值为空,此时仍可以安装httpd服务即使my_server的值为空,因为空值也是有定义。
[student@servera ~]$ ansible-playbook -i hosts test.yml
PLAY [when test] ******************************************************************************
TASK [Gathering Facts] *************************************************************************
ok: [servera]
TASK [ensure httpd is installed] ***************************************************************
changed: [servera]
PLAY RECAP ***********************************************************************************
servera : ok=2 changed=1 unreachable=0 failed=0
下表显示了在处理条件时可使用的一些运算:
比较难理解应该是最后的那个语法,可参考以下剧本的演示来进行理解。
ansible_distribution in supported_distros类型的例子:
---
- name: when test
hosts: servera
remote_user: root
vars:
opreate_system:
- x86_64
- x86_32
tasks:
- name: httpd installed
yum:
name: httpd
state: present
when: ansible_facts['architecture'] in opreate_system
这里的条件语句意思是,如果ansible_facts中的ansible_architecture的值能在opreate_system变量中找到符合的值,则安装httpd服务,opreate_system是自己指定的变量
测试执行:
[student@servera ~]$ ansible-playbook -i hosts test.yml
PLAY [when test] ************************************************************************
TASK [Gathering Facts] ******************************************************************
ok: [servera]
TASK [httpd installed] ******************************************************************
changed: [servera]
PLAY RECAP ******************************************************************************
servera : ok=2 changed=1 unreachable=0 failed=0
注意when语句的缩进。由于when语句不是模块变量,它必须通过缩进到任务的最高级别,放置在模块的外面。
任务是YAML散列/字典,when语句只是任务中的又一个键,就如任务的名称以及它所使用的模块一样。通常的惯例是将可能存在的任何when关键字放在任务名称和模块(及模块参数)的后面。
阅读量:1092
点赞量:0
收藏量:0