json - ansible.builtin.uri 模块 - 读取 JSON 文件内容并将其格式化为要在有效负载中使用的字符串
问题描述
我正在尝试使用ansible.builtin.lookup插件从本地目录读取 JSON 文件,然后将其作为有效负载传递给ansible.builtin.uri模块以将 POST 消息发送到 URI 端点。
以下是我的 JSON 文件 ( config.json ) 的内容:
{
"Configuration": {
"Components": [
{
"Name": "A",
"Attributes": [
{
"Name": "A1",
"Value": "1",
"Set On Import": "True",
"Comment": "Read and Write"
},
{
"Name": "A2",
"Value": "2",
"Set On Import": "True",
"Comment": "Read and Write"
}
]
}
]
}
}
我需要将上述 JSON 内容作为有效负载中的以下字符串发送到 ansible.builtin.uri 模块:
"{\"Configuration\": {\"Components\": [{\"Name\": \"A\", \"Attributes\": [{\"Name\": \"A1\", \"Value\": \"1\", \"Set On Import\": \"True\", \"Comment\": \"Read and Write\"}, {\"Name\": \"A2\", \"Value\": \"2\", \"Set On Import\": \"True\", \"Comment\": \"Read and Write\"}]}]}}"
我正在尝试使用带有to_json过滤器的查找插件来读取和格式化 JSON 内容。以下是我的剧本:
- name: import scp
ansible.builtin.uri:
url: "https://{{ inventory_hostname }}/api/config/actions/import"
user: "{{ user }}"
password: "{{ password }}"
method: POST
headers:
Accept: "application/json"
Content-Type: "application/json"
body:
Parameters:
Type: "LOCAL_FILE"
Target: "ALL"
IgnoreCertificateWarning: "Enabled"
Buffer: "{{ lookup('file', 'config.json') | to_json }}"
body_format: json
status_code: 202
validate_certs: no
force_basic_auth: yes
但是,uri 模块会双重转义所有换行符和制表符。以下是我运行 playbook 时发送有效负载的方式:
"invocation": {
"module_args": {
"attributes": null,
"body": {
"Buffer": "\"{\\n\\t\\\"Configuration\\\": {\\n\\t\\t\\\"Components\\\": [\\n\\t\\t\\t{\\n\\t\\t\\t\\t\\\"Name\\\": \\\"A\\\",\\n\\t\\t\\t\\t\\\"Attributes\\\": [\\n\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\\"Name\\\": \\\"A1\\\",\\n\\t\\t\\t\\t\\t\\t\\\"Value\\\": \\\"1\\\",\\n\\t\\t\\t\\t\\t\\t\\\"Set On Import\\\": \\\"True\\\",\\n\\t\\t\\t\\t\\t\\t\\\"Comment\\\": \\\"Read and Write\\\"\\n\\t\\t\\t\\t\\t},\\n\\t\\t\\t\\t\\t{\\n\\t\\t\\t\\t\\t\\t\\\"Name\\\": \\\"A2\\\",\\n\\t\\t\\t\\t\\t\\t\\\"Value\\\": \\\"2\\\",\\n\\t\\t\\t\\t\\t\\t\\\"Set On Import\\\": \\\"True\\\",\\n\\t\\t\\t\\t\\t\\t\\\"Comment\\\": \\\"Read and Write\\\"\\n\\t\\t\\t\\t\\t}\\n\\t\\t\\t\\t]\\n\\t\\t\\t}\\n\\t\\t]\\n\\t}\\n}\"",
"Parameters": {
"IgnoreCertificateWarning": "Enabled",
"Type": "LOCAL_FILE",
"Target": "ALL"
},
},
"body_format": "json",
...
},
您能否让我知道如何使用 uri 模块格式化有效负载?感谢任何帮助。
已编辑(2021 年 5 月 11 日):
我按照@mdaniel 在他的回复中的建议进行了更改,并使用了string
filter 而不是to_json
. 通过建议的更改,我可以看到 JSON 被正确格式化为带有换行符 ('\n') 和制表符 ('\t') 字符的字符串。我尝试使用replace
过滤器删除\n
和\t
字符。但是,现在整个字符串被转换回 JSON。
string
以下是单独使用过滤器时的剧本和输出:
...
body:
Parameters:
Type: "LOCAL_FILE"
Target: "ALL"
IgnoreCertificateWarning: "Enabled"
Buffer: "{{ lookup('file', 'config.json') | string }}"
$ ansible-playbook import_file.yml -i hosts --tags
...
"body": {
"HostPowerState": "On",
"Buffer": "{\n\t\"Configuration\": {\n\t\t\"Components\": [\n\t\t\t{\n\t\t\t\t\"Name\": \"A\",\n\t\t\t\t\"Attributes\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Name\": \"A1\",\n\t\t\t\t\t\t\"Value\": \"1\",\n\t\t\t\t\t\t\"Set On Import\": \"True\",\n\t\t\t\t\t\t\"Comment\": \"Read and Write\"\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"Name\": \"A2\",\n\t\t\t\t\t\t\"Value\": \"2\",\n\t\t\t\t\t\t\"Set On Import\": \"True\",\n\t\t\t\t\t\t\"Comment\": \"Read and Write\"\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t]\n\t}\n}",
"Parameters": {
"IgnoreCertificateWarning": "Enabled",
"Type": "LOCAL_FILE",
"Target": "ALL"
},
},
replace
以下是过滤器与过滤器结合使用时的剧本和输出string
:
...
body:
Parameters:
Type: "LOCAL_FILE"
Target: "ALL"
IgnoreCertificateWarning: "Enabled"
Buffer: "{{ lookup('file', 'config.json') | string | replace('\n', '') | replace('\t', '') }}"
...
$ ansible-playbook import_file.yml -i hosts --tags
...
"body": {
"Buffer": {
"Configuration": {
"Components": [
{
"Attributes": [
{
"Comment": "Read and Write",
"Name": "A1",
"Set On Import": "True",
"Value": "1"
},
{
"Comment": "Read and Write",
"Name": "A2",
"Set On Import": "True",
"Value": "2"
}
],
"Name": "A"
}
]
}
},
"Parameters": {
"IgnoreCertificateWarning": "Enabled",
"Type": "LOCAL_FILE",
"Target": "ALL"
},
},
...
关于如何从字符串中删除\n
和\t
字符的任何指示?
解决方案
您已经使用to_json
了一个dict
值,该值本身将被to_json
-ed;ansible 无法dict
通过 HTTP 传输 python,因此任何不是字符串的 yaml 结构都需要先转换为一个
您需要的只是查找结果(它将返回 a str
,而不是 a dict
),然后由于上述原因,ansible 将应用于to_json
整个值body:
但是,因为 ansible 试图“提供帮助”,所以它会自动将它发现的 yaml 值强制{
转换为 a dict
- 这就是为什么你只需要lookup
通过| string
过滤器发送结果来强化 ansible 是的,你真的希望它str
在那种情况下保持不变
...
body:
Parameters:
Type: "LOCAL_FILE"
Target: "ALL"
IgnoreCertificateWarning: "Enabled"
Buffer: "{{ lookup('file', 'config.json') | string }}"
更新的答案方法
鉴于dict
强制仍然是一个问题的评论讨论,并且领先的空间涉及 OP,替代方法是完全建立实际的有效负载结构,并且在传输之前只“JSON-ify”它,以保持ansible 和 jinja 在同一页面上关于数据类型:
- name: import scp
vars:
body_dict:
Parameters:
Type: "LOCAL_FILE"
Target: "ALL"
IgnoreCertificateWarning: "Enabled"
# this will be filled in before submission
# Buffer:
whitespace_free_config_json: >-
{{ lookup('file', 'config.json')
| regex_replace('[\t\n]', '')
| string
}}
ansible.builtin.uri:
...
body: >-
{{ body_dict
| combine({"Buffer": whitespace_free_config_json})
| to_json }}
body_format: json
status_code: 202
推荐阅读
- sql - 当 where 子句中的变量时 Oracle SQL 失败
- css - 如何将 css-next 变量分配给另一个变量?
- sql - 提取 XML 值
- javascript - Array.prototype.filter 的猴子补丁破坏了 AngularJS 1.6
- typescript - 单元测试 mocha Visual Studio 代码描述未定义
- automation - Jira 应用程序属性存储在哪里
- python - twitter api 到 mysql 使用 python
- java - 断言文本时如何在Java中跳过一行
- jsch - JSch session.openChannel
- django - 如何在 apiview 中获取访问令牌