【问题标题】:Detect changes on json file in Ansible: jq uses different indention -> File is always changed检测 Ansible 中 json 文件的更改:jq 使用不同的缩进 -> 文件始终更改
【发布时间】:2021-02-19 04:23:05
【问题描述】:

使用 Ansible,我想替换 json 文件中的字符串。似乎 Ansible 没有类似 xml 用于 json 的模块,我使用的是 jq cli tool。由于需要在底层应用程序中重新启动(这需要一些时间,因为它是一个沉重且旧的 Java 应用程序),我想要进行更改检测,以便仅在需要时应用重新启动。

带有-e 参数的返回码不会改变,所以我的想法是在jq 运行之前获取文件的哈希值,然后将其与之后的哈希值进行比较。可以使用stat 模块来获取哈希:

- set_fact: 
    common_properties_file: "{{ resources_dir }}/commonProperties.json"

- name: Get hash of {{ common_properties_file }}
  stat: path={{ common_properties_file }}
  register: coomon_properties_check

- name: Hash before modification
  debug:
    var: coomon_properties_check.stat.checksum

但是在测试过程中,我发现在不做任何修改的情况下打印文件时哈希甚至会发生变化。差异显示整个文件被不同的缩进修改:

# jq '.' resources/commonProperties.json > resources/commonProperties.json_jq
# colordiff resources/commonProperties.json resources/commonProperties.json_jq
2,14c2,10
<     "name": "Notification mail customization",
<     "type": "com.ibm.connections.notification.mail",
<     "payload": {
<         "platformName": "HCL Connections",
<         "photoType":"url",
<         "style": {
<             "bodyBackgroundColor": "#eeeeee",
<             "sidebarBackgroundColor": "#3d6cf0",
<             "messageBackgroundColor": "#ffffff"
<         },
<         "activityDateFormat": "dd MMM",
<         "activityMax" : "25",
<         "subjectAppNameAppend" : "tail"
---
>   "name": "Notification mail customization",
>   "type": "com.ibm.connections.notification.mail",
>   "payload": {
>     "platformName": "HCL Connections",
>     "photoType": "url",
>     "style": {
>       "bodyBackgroundColor": "#eeeeee",
>       "sidebarBackgroundColor": "#3d6cf0",
>       "messageBackgroundColor": "#ffffff"
16c12,16
<     "path": "notify"
---
>     "activityDateFormat": "dd MMM",
>     "activityMax": "25",
>     "subjectAppNameAppend": "tail"
>   },
>   "path": "notify"

我也试过jq --tab,但没有成功。我看到的唯一方法是编写一个小型 Ansible 模块,将 json 解析为数组,检查是否需要应用修改并设置更改的状态,以便我可以使用它们来决定是否需要重新启动。

是否有无需为此目的编写 Ansible 模块的本地方式?

【问题讨论】:

    标签: json ansible jq


    【解决方案1】:

    您可以使用 jq 的 == 运算符检查新文件是否与原始文件 JSON 相等。在 stdout 上不生成任何输出的一种方法是使用 jq 的内置 halt_error/1。有很多可能性,但这里有一个简单的独立说明:

    echo '{"a": 0}' | jq --argfile f1 <(echo {}) '
       if . == $f1 then empty else null|halt_error(99) end' 
    

    为避免调用 jq 两次,另一种方法是使用 jq BOTH 来写出可能更改的文件并根据上述示例使用halt_error 建议的行设置返回码。

    【讨论】:

    • 这是个好主意。 p="HCL Connections" jq 'if .payload.platformName == env.p then . else .payload.platformName = env.p | halt_error(99) end' resources/commonProperties.json &gt; /tmp/out.json 2&gt;&amp;1 有效,但有一个副作用:当我设置 p="HCL Connections1"(= 需要修改)时,输出 json /tmp/out.json 被缩小:{"name":"Notification mail customization","type": ... 出于调试目的很难阅读,有没有办法让它变得漂亮?未经修改(if 的 . 部分)它被美化了,但似乎 halt_error 在美化完成之前停止
    • 关于漂亮的输出,这是有效的:p="HCL Connections1" jq 'if .payload.platformName == env.p then . else .payload.platformName = env.p, (empty|halt_error(99)) end' resources/commonProperties.json 但是echo $? 给了我0,即使命令将"platformName": "HCL Connections 替换为"platformName": "HCL Connections1 - RC 在上一个命令中工作p="HCL Connections" jq 'if .payload.platformName == env.p then . else .payload.platformName = env.p | halt_error(99) end'$? 中给了我 RC 99@
    • 哎呀,我的意思是if .payload.platformName == env.p then . else .payload.platformName = env.p , ( null|halt_error(99)) end
    • 这有效,并且还使得将 stderr 重定向到 stdout 变得不必要,因为 json 被打印为格式化为 stdout 而不是未格式化为 stderr。谢谢! :)
    【解决方案2】:

    在@peak 的帮助下,我找到了解决方案:

    jq --arg platform "MyPlatformName" 'if .payload.platformName == $platform then . else .payload.platformName = $platform, (null|halt_error(99)) end' resources/commonProperties.json > /tmp/out.json
    

    如果文件被编辑,这将导致返回码 99

    # echo $?
    99
    

    如果我们在修改后的文件上重新运行该工具,则无需应用修改,我们得到 rc = 0

    # jq --arg platform "MyPlatformName" 'if .payload.platformName == $platform then . else .payload.platformName = $platform, (null|halt_error(99)) end' /tmp/out.json > /tmp/out2.json
    # echo $?
    0
    

    【讨论】:

      猜你喜欢
      • 2021-08-02
      • 2015-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多