我有一个证书创建工具,可以像这样输出证书:
{
"cert": "abc123......",
"id": 10,
"key": "abc123....."
}
实际的证书和密钥字段是base64编码的,但这与这里的问题无关。
当我从 ansible 运行它并将输出注册为变量时,它会使用转义的双引号存储:
{
"cert_output": {
"changed": true,
"delta": "0:00:00.673537",
"end": "2024-05-14 13:34:45.492559",
"failed": false,
"msg": "",
"rc": 0,
"start": "2024-05-14 13:34:44.819022",
"stderr": "",
"stderr_lines": [],
"stdout": "{\"id\":233370662,\"cert\":\"abc123...\",\"key\":\"abc123...\"}",
}
}
我一生都无法解析出各个密钥。这个功能在很久以前就可以工作,但不知何故它已经被破坏了。
# does not work
- set_fact:
cert: "{{ cert_output.stdout|from_json|json_query('.cert') }}"
key: "{{ cert_output.stdout|from_json|json_query('.key') }}"
# does not work
- set_fact:
cert: "{{ cert_output.stdout|json_query('.cert') }}"
key: "{{ cert_output.stdout|json_query('.key') }}"
Ansible 错误:
FAILED! => {"msg": "JMESPathError in json_query filter plugin:\ninvalid token: Parse error at column 0, token \".\" (DOT), for expression:\n\".cert\"\n ^"}
对于此用例,您不需要使用 JMESPath,Ansible 具有很强的 JSON 功能。一旦您有了 JSON,而不是 JSON 的字符串表示形式,由于您正确使用了
from_json
过滤器,那么您就可以使用点符号返回查询字典属性:
- set_fact:
cert: "{{ (cert_output.stdout | from_json).cert }}"
key: "{{ (cert_output.stdout | from_json).key }}"
这会导致
ok: [localhost] => changed=false
ansible_facts:
cert: abc123...
key: abc123...
注意:上面的输出是使用选项
-v
运行 playbook 时生成的,其中除其他有用信息外,还显示了 set_fact
任务的结果。
对于 JMESPath 查询,访问 JSON 的“root”节点上的 JSON 标识符只需通过寻址其键(不带任何点)即可完成,因此:
- set_fact:
cert: "{{ cert_output.stdout | from_json | json_query('cert') }}"
key: "{{ cert_output.stdout | from_json | json_query('key') }}"
结果与上面相同。