【发布时间】:2020-06-08 17:06:08
【问题描述】:
我们需要为 nodeJS 产品提供一个双引号转义 JSON 字符串到 AWS 机密中。双引号内的单引号格式不适用于该应用程序。结构化数据采用 dict-list-dict 格式。示例:
{
"data": "[{\"URL\": \"beta.test.net\", \"token\": \"beta-token\"}, {\"URL\": \"beta-prod.test.net\", \"token\": \"beta-prod-token\"}]"
}
我尝试了一些过滤器来获取 ansible 和 jinja 以获取 JSON 变量并将其转换为所需格式的字符串,但结果永远不会完全正确。 | to_json |字符串给出以下结果:
{
"data": "[{'URL': 'beta.test.net', 'token': 'beta-token'}, {'token': 'test-token', 'URL': 'beta-prod.test.net'}]"
}
当我尝试使用替换或正则表达式替换时,似乎即使使用保护字符,我最终也会遇到 python 解析错误。这是一个仅使用带有重音符号“`”转义符的替换的示例。
TASK [Update secret in AWS] ***************************************************************************************************
task path: path:27
The full traceback is:
Traceback (most recent call last):
File "/home/.local/lib/python3.5/site-packages/ansible/executor/task_executor.py", line 146, in run
res = self._execute()
File "/home/.local/lib/python3.5/site-packages/ansible/executor/task_executor.py", line 587, in _execute
self._task.post_validate(templar=templar)
File "/home/.local/lib/python3.5/site-packages/ansible/playbook/task.py", line 296, in post_validate
super(Task, self).post_validate(templar)
File "/home/.local/lib/python3.5/site-packages/ansible/playbook/base.py", line 431, in post_validate
value = templar.template(getattr(self, name))
File "/home/.local/lib/python3.5/site-packages/ansible/template/__init__.py", line 623, in template
disable_lookups=disable_lookups,
File "/home/.local/lib/python3.5/site-packages/ansible/template/__init__.py", line 578, in template
disable_lookups=disable_lookups,
File "/home/.local/lib/python3.5/site-packages/ansible/template/__init__.py", line 806, in do_template
data = _escape_backslashes(data, myenv)
File "/home/.local/lib/python3.5/site-packages/ansible/template/__init__.py", line 149, in _escape_backslashes
for token in jinja_env.lex(d2):
File "/home/.local/lib/python3.5/site-packages/jinja2/lexer.py", line 739, in tokeniter
name, filename)
jinja2.exceptions.TemplateSyntaxError: unexpected char '`' at 51
line 1
fatal: [beta-prod]: FAILED! => {
"msg": "Unexpected failure during module execution.",
"stdout": ""
}
使用正则表达式替换,我可以一直删除单引号并将其替换为 '\',但任何添加 '\"' 的尝试总是会因上述解析错误而失败。
这是调用 AWS 机密的 ansible 代码,我尝试了一些提供正确格式的尝试:
- name: Update secret in AWS
aws_secret:
name: '{{ aws_secret_name }}'
state: present
secret_type: 'string'
# secret: "{{ token_list_update | to_json | replace(\"'\",\"\") | string }}"
secret: '{{ token_list_update | to_json | string }}'
# secret: ' {"data": "{{ token_list | to_json | regex_replace(`"`,`\\"`) }}"}'
任何帮助将不胜感激。我得到了我需要编写自己的过滤器来处理这个问题的想法。我确实询问过应用程序是否会接受单引号内双引号的 JSON 字符串,但团队表示这是不可接受的。格式必须是双引号转义的 JSON 字符串。
最终编辑:
经过几天的工作,想出了这个。在每个步骤中,您都需要转换正确的类型以保留 JSON 格式。在进行更新时,每个列表元素都需要过滤到 to_json。示例:
token_list: "{{ (token_list | default([]) + [_update]) | to_json }}"
_update 是一个辅助变量,它是一个 JMESPath 搜索
最终提交到 AWS:
- name: Update secret in AWS
aws_secret:
name: "{{ aws_secret_name }}"
state: present
secret_type: "string"
secret: "{\"data\":{{ token_list | to_json}}}"
【问题讨论】:
-
token_list_update这个值是什么? -
如果您在不使用非 JSON 字符(例如反引号)的情况下发布了错误,也会很有帮助;我怀疑 ansible 正在做正确的事情,但是如果您不习惯它,将消息打包为 JSON 本身的默认 stdout 回调可能会令人困惑。再往下走,你确定
secret: "{{ token_list_update | to_json }}"没有做你想做的事吗?您是否在 AWS 中检查该项目是否按预期存储? -
token_list_update是 dict-list-dict 本机对象。抱歉,我没有澄清这一点。"{{ token_list_update | to_json }}"在 AWS 中存储了不正确的值 -{ "data": "[{'URL': 'beta.test.net', 'token': 'beta-token'}, {'token': 'test-token', 'URL': 'beta-prod.test.net'}]" }