【问题标题】:Add a new key-value to a json file using Ansible使用 Ansible 向 json 文件添加新的键值对
【发布时间】:2018-06-11 11:07:08
【问题描述】:

我正在使用 Ansible 为我的应用程序虚拟机自动执行一些配置步骤,但很难将新的键值插入到远程主机上的现有 json 文件中。

假设我有这个 json 文件:

{
  "foo": "bar"
}

我想插入一个新的键值对,使文件变成:

{
  "foo": "bar",
  "hello": "world"
}

由于 json 格式不是基于行的,我将 lineinfile 模块从我的选项中排除。另外,我不希望使用任何外部模块。谷歌不断给我示例来展示如何读取 json 文件,但没有关于更改 json 值并将它们写回文件。非常感谢您的帮助!

【问题讨论】:

    标签: json ansible


    【解决方案1】:

    由于文件是 json 格式,您可以将文件导入到变量中,附加所需的额外键:值对,然后写回文件系统。

    这是一种方法:

    ---
    - hosts: localhost
      connection: local
      gather_facts: false
      vars:
    
      tasks:
      - name: load var from file
        include_vars:
          file: /tmp/var.json
          name: imported_var
    
      - debug:
          var: imported_var
    
      - name: append more key/values
        set_fact:
          imported_var: "{{ imported_var | default([]) | combine({ 'hello': 'world' }) }}"
    
      - debug:
          var: imported_var
    
      - name: write var to file
        copy: 
          content: "{{ imported_var | to_nice_json }}" 
          dest: /tmp/final.json
    

    更新

    随着 OP 更新,代码应该适用于远程主机,在这种情况下,我们不能使用 included_vars 或查找。我们可以使用slurp 模块。

    远程主机代码:

    ---
    - hosts: greenhat
      # connection: local
      gather_facts: false
      vars:
    
      tasks:
      - name: load var from file
        slurp:
          src: /tmp/var.json
        register: imported_var
    
      - debug:
          msg: "{{ imported_var.content|b64decode|from_json }}"
    
      - name: append more key/values
        set_fact:
          imported_var: "{{ imported_var.content|b64decode|from_json | default([]) | combine({ 'hello': 'world' }) }}"
    
      - debug:
          var: imported_var
    
      - name: write var to file
        copy: 
          content: "{{ imported_var | to_nice_json }}" 
          dest: /tmp/final.json
    

    希望对你有帮助

    【讨论】:

    • 我的错,我应该提到json文件在远程主机上
    • 你也可以在远程主机上运行。只需从我的剧本中删除 connection: local 行并用您自己的主机替换主机。还将实际的 var 文件复制到 /tmp/var.json 仅用于此测试。文件将被创建为/tmp/final.json
    • 看起来 ansible 在删除connection: local 后仍然在寻找本地路径,它说fatal: [192.168.63.181]: FAILED! => {"ansible_facts": {"imported_var": {}}, "ansible_included_var_files": [], "changed": false, "message": "Could not find or access '/tmp/var.json'"}
    • 你是对的,我忽略了这一点,因为当我测试远程主机的剧本时,我的本地主机上也存在该文件。请使用slurp 模块查看更新的答案
    • 这可以在特定行之后完成吗?
    【解决方案2】:

    ilias-sp's solution 太棒了!

    在我的情况下,它缺少我们可能必须创建基本 json 文件的情况。 所以只好在剧的开头加上这个任务:

    - name: Ensure json file exists
    copy:
      content: "{}"
      dest: /tmp/var.json
      force: false
    

    【讨论】:

      【解决方案3】:

      对于可以使用自定义 ansible 模块的人:https://github.com/ParticleDecay/ansible-jsonpatch 效果很好!

      有了这个,你可以简单地做到:

      - name: append key/values
        json_patch:
          src: /tmp/var.json
          operations:
            - op: add
              path: "/hello"
              value: "world"
          pretty: yes
          create: yes
      

      【讨论】:

        【解决方案4】:
         - name: update log
            copy:
              content: "{{ log | to_nice_json}}"
              dest: "{{ log_file }}"
            vars:
              log: "{{ (lookup('file', log_file) | from_json) + ([{'job': (build_id if build_id != '' else 'dev'), 'keystore': ks, 'timestamp': ansible_date_time.iso8601}]) }}"
              log_file: log/log.json
              build_id: "{{ lookup('ENV', 'BUILD_ID') }}"
            tags: log
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-11-01
          • 2020-04-22
          • 1970-01-01
          • 2020-04-22
          • 1970-01-01
          • 2020-04-26
          • 2018-01-25
          • 2021-04-24
          相关资源
          最近更新 更多