ansible.builtin.uri 模块 - 读取 JSON 文件内容并将其格式化为要在负载中使用的字符串
ansible.builtin.uri module - Read and format JSON file content as a string to use in payload
我正在尝试使用 ansible.builtin.lookup plugin in order to read a JSON file from the local directory and then pass it as the payload to the ansible.builtin.uri 模块向 URI 端点发送 POST 消息。
以下是我的 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 模块双重转义所有换行符和制表符。以下是我 运行 剧本时有效载荷的发送方式:
"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
过滤器而不是 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
字符的任何指示?
您已经在 dict
值上使用了 to_json
,该值本身将被 to_json
编辑; ansible 无法通过 HTTP 传输 python dict
,因此任何还不是字符串的 yaml 结构都需要先转换为
你想要的只是那个查找结果(它将 return 一个 str
,而不是一个 dict
),然后 ansible 将应用 to_json
到由于上述原因 body:
的全部价值
但是,因为 ansible 试图“提供帮助”,它会自动将找到的以 {
back 开头的 yaml 值强制转换为 dict
——这就是为什么你只需要通过 | string
过滤器发送 lookup
的结果来加强 ansible 是的,你确实希望它保持 str
上下文
...
body:
Parameters:
Type: "LOCAL_FILE"
Target: "ALL"
IgnoreCertificateWarning: "Enabled"
Buffer: "{{ lookup('file', 'config.json') | string }}"
更新答案方法
鉴于 dict
强制转换仍然是一个问题的评论讨论,并且领先的 space 涉及 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
我正在尝试使用 ansible.builtin.lookup plugin in order to read a JSON file from the local directory and then pass it as the payload to the ansible.builtin.uri 模块向 URI 端点发送 POST 消息。
以下是我的 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 模块双重转义所有换行符和制表符。以下是我 运行 剧本时有效载荷的发送方式:
"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
过滤器而不是 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
字符的任何指示?
您已经在 dict
值上使用了 to_json
,该值本身将被 to_json
编辑; ansible 无法通过 HTTP 传输 python dict
,因此任何还不是字符串的 yaml 结构都需要先转换为
你想要的只是那个查找结果(它将 return 一个 str
,而不是一个 dict
),然后 ansible 将应用 to_json
到由于上述原因 body:
的全部价值
但是,因为 ansible 试图“提供帮助”,它会自动将找到的以 {
back 开头的 yaml 值强制转换为 dict
——这就是为什么你只需要通过 | string
过滤器发送 lookup
的结果来加强 ansible 是的,你确实希望它保持 str
上下文
...
body:
Parameters:
Type: "LOCAL_FILE"
Target: "ALL"
IgnoreCertificateWarning: "Enabled"
Buffer: "{{ lookup('file', 'config.json') | string }}"
更新答案方法
鉴于 dict
强制转换仍然是一个问题的评论讨论,并且领先的 space 涉及 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