lookup插件从外部数据源(文件,数据库,API等)获取数据,它是在控制节点上运行的。
下面以 file
插件为例。
假设在控制节点上,有文件 /tmp/a.txt
和 /tmp/b.txt
。
/tmp/a.txt
内容如下:
xxx
yyyyy
z
/tmp/b.txt
内容如下:
good
better
best
可以通过 file
插件来读取文件内容:
---
- hosts: all
vars:
var1: "{{ lookup('file', '/tmp/a.txt') }}"
tasks:
- name: task1
debug:
msg: "{{ var1 }}"
运行结果如下:
......
TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => {
"msg": "xxx\nyyyyy\nz"
}
......
查看 var1
类型:
......
- name: task2
debug:
msg: "{{ var1 | type_debug }}"
......
运行结果如下:
......
TASK [task2] ***************************************************************************************
ok: [192.168.1.55] => {
"msg": "AnsibleUnsafeText"
}
......
可见,其类型是字符串( AnsibleUnsafeText
)。
我们常见的 with_
,都是使用了 xxx
lookup。因此,二者通常可以互换。
把上面的 lookup('file', '
改为 with_file
的形式:
......
- name: task1
debug:
msg: "{{ item }}"
with_file: "/tmp/a.txt"
......
运行结果如下:
TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => (item=xxx
yyyyy
z) => {
"msg": "xxx\nyyyyy\nz"
}
若想访问多个文件,只需对 lookup()
添加多个参数:
---
- hosts: all
vars:
var1: "{{ lookup('file', '/tmp/a.txt', '/tmp/b.txt', wantlist=True) }}"
tasks:
- name: task1
debug:
msg: "{{ item }}"
loop: "{{ var1 }}"
注意:一般情况下,对于多个文件,我们希望得到一个list,所以需要显式的指定 wantlist=True
。
......
TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => (item=xxx
yyyyy
z) => {
"msg": "xxx\nyyyyy\nz"
}
ok: [192.168.1.55] => (item=good
better
best) => {
"msg": "good\nbetter\nbest"
}
......
var1
的类型是list,可以遍历 var1
,访问各个文件内容。
如果不指定 wantlist=True
:
---
- hosts: all
vars:
var1: "{{ lookup('file', '/tmp/a.txt', '/tmp/b.txt') }}"
tasks:
- name: task1
debug:
msg: "{{ var1 }}"
运行结果如下:
......
TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => {
"msg": "xxx\nyyyyy\nz,good\nbetter\nbest"
}
......
可见, 若不指定 wantlist=True
,则 var1
类型为字符串,会通过逗号,把多个文件的内容拼接在一起。
当然,对于单个文件,也可以指定 wantlist=True
,只不过list里只有一个元素而已。
---
- hosts: all
tasks:
- name: task1
debug:
msg: "{{ item }}"
with_file:
- "/tmp/a.txt"
- "/tmp/b.txt"
运行结果如下:
......
TASK [task1] ***************************************************************************************
ok: [192.168.1.55] => (item=xxx
yyyyy
z) => {
"msg": "xxx\nyyyyy\nz"
}
ok: [192.168.1.55] => (item=good
better
best) => {
"msg": "good\nbetter\nbest"
}
......
query
是一个Jinja2函数,会调用lookup插件。 query
会返回一个list,也就是相当于lookup指定了 wantlist=True
。
上面的例子,用query改写如下:
---
- hosts: all
vars:
#var1: "{{ lookup('file', '/tmp/a.txt', '/tmp/b.txt', wantlist=True) }}"
var1: "{{ query('file', '/tmp/a.txt', '/tmp/b.txt') }}"
tasks:
- name: task1
debug:
msg: "{{ item }}"
loop: "{{ var1 }}"
注: query
可简写为 q
。
具体参见文末的lookup插件列表。
常见的比如 items
lookup。
---
- hosts: all
vars:
var1: "{{ query('items', 'aaa', 'bbb', 'ccc') }}"
# var1: "{{ lookup('items', 'aaa', 'bbb', 'ccc', wantlist=True) }}" # 两种写法都可以
tasks:
- name: task1
debug:
msg: "{{ item }}"
loop: "{{ var1 }}"
也可以写成 with_items
的形式:
---
- hosts: all
tasks:
- name: task1
debug:
msg: "{{ item }}"
with_items:
- "aaa"
- "bbb"
- "ccc"
比如,要访问的文件不存在,则会报错。
---
- hosts: all
vars:
var1: "{{ query('file','/tmp/a.txt', '/tmp/z.txt') }}"
tasks:
- name: task1
debug:
msg: "{{ item }}"
loop: "{{ var1 }}"
报错如下:
......
TASK [task1] ***************************************************************************************
fatal: [192.168.1.55]: FAILED! => {"msg": "An unhandled exception occurred while templating '{{ query('file','/tmp/a.txt', '/tmp/z.txt') }}'. Error was a , original message: The 'file' lookup had an issue accessing the file '/tmp/z.txt'. file not found, use -vvvvv to see paths searched" }
PLAY RECAP *****************************************************************************************
192.168.1.55 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
可以添加一个 errors
参数:
strict
:默认值,即报错ignore
:忽略错误warn
:警告指定 ignore
:
---
- hosts: all
vars:
var1: "{{ query('file', '/tmp/a.txt', '/tmp/z.txt', errors='ignore') }}"
tasks:
- name: task1
debug:
msg: "{{ item }}"
loop: "{{ var1 }}"
运行结果如下:
......
TASK [task1] ***************************************************************************************
skipping: [192.168.1.55]
PLAY RECAP *****************************************************************************************
192.168.1.55 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
指定 warn
:
---
- hosts: all
vars:
var1: "{{ query('file', '/tmp/a.txt', '/tmp/z.txt', errors='warn') }}"
tasks:
- name: task1
debug:
msg: "{{ item }}"
loop: "{{ var1 }}"
运行结果如下:
TASK [task1] ***************************************************************************************
[WARNING]: Lookup failed but the error is being ignored: The 'file' lookup had an issue accessing
the file '/tmp/z.txt'. file not found, use -vvvvv to see paths searched
skipping: [192.168.1.55]
PLAY RECAP *****************************************************************************************
192.168.1.55 : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_lookups.html
https://docs.ansible.com/ansible/latest/plugins/lookup.html
https://docs.ansible.com/ansible/latest/collections/ansible/builtin/file_lookup.html
https://docs.ansible.com/ansible/latest/collections/ansible/builtin/index.html#lookup-plugins