Ansible playbook lookups
Ansible 有很多方式可以定义变量,如下几种:
1、通过 Inventory 文件定义
2、通过 /etc/ansible 下的文件定义主机以及组变量
3、通过 ansible-playbook 命令行传入
4、通过在 playbook 文件内使用 vars
5、通过在 playbook 文件内使用 vars_files
6、使用 register 传递变量
7、通过 vars_prompt 交互式传入
但是这些变量都是静态的,Ansible 还支持从外部数据拉取信息,比如我们可以从数据库里读取信息然后定义给一个变量的形式,这就是 Ansible 的 lookups 插件。
目前 Ansible 自带一些 lookups 组件:
一、 lookups file
file 是比较常用的一种 lookups 方式,它的原理就是使用 python 的 codecs.open 打开文件然后把结果返回给变量。下面 playbook 通过读取客户端 /etc/sysconfig/network 文件的内容,接着再打印出来:
---
- hosts: 10.1.0.51
gather_facts: False
vars:
value: "{{ lookup('file','/etc/sysconfig/network') }}"
tasks:
- name: display variable value
debug: msg="value ---> {% for i in value.split("\n")%} {{ i }} {% endfor %}"
二、lookups password
password 也是常用的一种 lookups 方式,它会对传入的内容进行加密处理。下面 playbook 通过在 playbook 中定义的字符串进行加密,然后再进行输出,并且在当前目录下保存一份密码文件:
---
- hosts: 10.1.0.51
gather_facts: False
vars:
password: "{{ lookup('password','pAssW0rd') }}"
tasks:
- name: display password
debug: msg="password ---> {{ password }}"
三、lookups pipe
pipe lookups 其实就是在控制机器上调用 subprocess.Popen 执行命令,然后将获取到的结果传递给变量,最后进行打印:
---
- hosts: 10.1.0.51
gather_facts: False
vars:
time: "{{ lookup('pipe','date +%F') }}"
tasks:
- name: display time
debug: msg="time ---> {{ time }}"
四、lookups template
template 与 file 方式有点类似,都是读取文件,但是 template 在读取文件之前需要把 jinja 模板渲染完之后再进行读取,当然,gather_facts 参数需要设置为 True,不然无法获取到主机的信息。
template 调用当前目录下的 template.j2 文件并且进行渲染取值,再进行输出,下面通过指定一个 jinja 模板文件:
template.j2 模板文件:
worker_processes {{ ansible_processor_cores }};
IPaddress {{ ansible_eth0.ipv4.address }};
template.yaml playbook 文件:
---
- hosts: 10.1.0.51
gather_facts: True
vars:
value: "{{ lookup('template','./template.j2') }}"
tasks:
- name: display template.j2
debug: msg="value ---> {% for i in value.split("\n") %} {{ i }} {% endfor %}"
Ansible playbook conditionals
ansible playbook 在实际应用过程中,经常会碰到不同的主机可能要执行不同的命令,或者执行某个 task 的时候需要进行一个简单的逻辑判断,此刻就需要在写 task 的时候进行相应的判断。目前 ansible 所有的 conditionals 方式都是使用 when 进行判断,when 的值是一个条件表达式,如果条件判断成立,这个 task 就执行某个操作,如果条件判断不成立,该 task 不执行或者某个操作会跳过。这里所说的成立与不成立就是 python 语言里面的 True 或 False,关于这个条件表达式也支持多个条件之间 and 或 or,还需要注意的是,如果我们使用一个变量进行相应的判断,一定要清楚该变量的数据类型。
下面通过一个示例来进行一些常见的判断:
一、when 进行判断地址为 10.1.0.51 地址的主机,如果匹配,则输出该 IP 地址
二、when 进行判断内存大于 1500M 并且 CPU 核心数为两个的主机,如果匹配,则输出 FQDN
三、在 when 之前,通过 shell 执行 hostname 命令,再寄存到 register 中,后面通过 info[‘stdout’] 进行取值,接着 when 进行判断该值,如匹配,则输出 FQDN
四、when 进行判断开始字符串为 node 的条件,如果匹配,则输出 FQDN
---
- hosts: client
gather_facts: True
tasks:
- name: Host 10.1.0.51 run this task
debug: msg="{{ ansible_default_ipv4.address }} ."
when: ansible_default_ipv4.address == "10.1.0.51"
- name: Memtotal > 1500M and processor_cores == 2 run this task
debug: msg="{{ ansible_fqdn }} ."
when: ansible_memtotal_mb > 1500 and ansible_processor_cores == 2
- name: all host run this task
shell: hostname
register: info
- name: Hostname is node-2 run this task
debug: msg="{{ ansible_fqdn }} ."
when: info['stdout'] == "node-2"
- name: Host name is startswith node run this task
debug: msg="{{ ansible_fqdn }} ."
when: info['stdout'].startswith('node')