【问题标题】:Is there a yaml editing module for ansible?是否有用于 ansible 的 yaml 编辑模块?
【发布时间】:2015-10-07 13:49:09
【问题描述】:

我需要修改一个 yaml 文件 (schleuder configuration),我想从 ansible playbook 中执行此操作 - 是否有一个模块可以执行此操作?很难用谷歌搜索,所有出现的都是如何编写剧本。

【问题讨论】:

    标签: ansible


    【解决方案1】:

    我还需要配置管理 yaml 文件。我编写了一个 ansible 模块,它在编辑 yaml 文件时尝试幂等。

    我称之为 yedit (yaml-edit)。 https://github.com/kwoodson/ansible-role-yedit

    如果您觉得有用,请告诉我。当我们的团队遇到需求时,我会根据请求或拉取请求添加功能。

    这是一个简单的剧本示例:

    roles:
    - lib_yaml_editor
    
    tasks:
    - name: edit some yaml
      yedit:
        src: /path/to/yaml/file
        key: foo
        value: bar
    
    - name: more complex data structure
      yedit:
        src: /path/to/yaml/file
        key: a#b#c#d
        value:
          e:
            f:  This is a test
    

    应该产生如下所示的东西:

    foo: bar
    a:
      b:
        c:
          d:
            e:
              f: This is a test
    

    编辑:2018 年 5 月 27 日

    【讨论】:

    • 哇,非常感谢您的提醒 - 我会看看的,我现在正忙于其他事情
    • 非常好的模块...我现在没有你可以安装角色并直接使用它...字面意思让我大吃一惊
    • 你能把它添加到 Ansible Galaxy 中吗?
    • 我已将它添加到 ansible-galaxy。唯一的缺点是我必须重命名才能让银河导入工具找到它。
    • 这适用于具有多个文档的 yaml 吗?如果是的话,你能指点我任何工作的例子吗?
    【解决方案2】:

    实现此目的的一种方法是将文件读入事实,根据需要更新事实,然后稍后将事实写回 yaml 文件。

    - name: Read the yaml
      slurp:
        path: myfile.yaml
      register: r_myfile
    
    - name: extract the data
      set_fact:
        mydata: "{{ r_myfile['content'] | b64decode | from_yaml }}"
    

    然后根据需要更新事实,例如使用ansible.utils.update_fact module

    - name: Write back to a file
      copy:
        content: '{{ mydata | to_nice_yaml }}'
        dest: myfile.yaml
    

    当然,您需要注意,这会使整个更新成为非原子更新。

    更新:我最初的建议使用了lookup('file'),但当然是访问本地文件。 slurp 是读取远程文件的正确方法。

    【讨论】:

    • 更多关于如何更改 yaml 文件内容的详细信息将真正有助于使其大放异彩。
    • @Josiah - 好点。我无法找到在 Ansible 中更改现有字典的方法。我能找到的唯一解决方案是创建一个具有相同名称的新事实,并根据需要使用combine 过滤器替换原始字典中的键。
    • 似乎the update_fact module 是要走的路。
    • 不错的解决方案,但这会删除 yaml 文件中现有的 cmets,有什么方法可以保留 cmets?
    【解决方案3】:

    根据 Kevin 和 Bogd 的回答,如果您想合并嵌套键而不是覆盖 YAML 文件的整个分支,则必须在 combine 函数中启用递归:

    mydata: "{{ mydata | combine(newdata, recursive=True) }}"
    

    来自Ansible documentation

    递归 是一个布尔值,默认为 False。组合是否应该递归合并嵌套哈希。注意:它不依赖于 ansible.cfg 中 hash_behaviour 设置的值。

    所以完整的解决方案变成:

    - name: Open yaml file
      slurp:
        path: myfile.yaml
      register: r_myfile
    
    - name: Read yaml to dictionary
      set_fact:
        mydata: "{{ r_myfile['content'] | b64decode | from_yaml }}"
    
    - name: Patch yaml dictionary
      set_fact:
        mydata: "{{ mydata | combine(newdata, recursive=True) }}"
      vars: 
        newdata:
          existing_key:
            existing_nested_key: new_value
            new_nested_key: new_value
    
    - name: Write yaml file
      copy:
        content: '{{ mydata | to_nice_yaml }}'
        dest: myfile.yaml
    

    注意:递归只能添加嵌套键或替换嵌套值。删除特定的嵌套键需要更高级的解决方案。

    【讨论】:

      【解决方案4】:

      这是基于 Kevin Keane 的回答 - 我刚刚添加了事实修改部分。而且由于似乎无法编辑现有答案(编辑队列已满),我只是为其他(像我一样)来这里寻找详细信息的人添加了这个。

      1. 从文件中读取 YAML 数据,并创建一个事实来存储该数据:

        - name: Read the yaml 
          slurp:
            path: myfile.yaml
          register: r_myfile
        
        - name: extract the data
          set_fact:
            mydata: "{{ r_myfile['content'] | b64decode | from_yaml }}"
        
      2. 我无法找到任何方式来修改 Ansible 中的现有字典。因此,实际修改数据的解决方法是创建一个与现有事实 (mydata) 同名的新字典,并根据需要使用 combine 过滤器更改键:

        - name: Create configuration for core - modify params
          set_fact:
            mydata: "{{ mydata | combine(newdata) }}"
          vars: 
            newdata:
              old_key: new_value
              new_key: new_value
        
      3. 将修改后的数据写入文件:

        - name: Write back to a file
          copy:
            content: '{{ mydata | to_nice_yaml }}'
            dest: myfile.yaml
        

      结果:

      原始 myfile.yaml:

       ---
       another_key: another_value  # This is a key that we will not touch
       old_key: old_value          # This is an old key, that we will change
      

      剧本执行后的文件:

       another_key: another_value
       new_key: new_value
       old_key: new_value
      

      请注意(正如您可能预期的那样)所有 cmets 都已消失,因为您只是在读取 YAML 数据并将其写回。

      【讨论】:

        【解决方案5】:

        没有这样的模块。你可以查看https://docs.ansible.com/ansible/list_of_all_modules.html

        最好的办法是使用 lineinfiletemplatecopy 模块。

        【讨论】:

        【解决方案6】:

        【讨论】:

        • 您似乎没有得到问题?在您指向的文档中,甚至没有提到编写 YAML,更不用说读取修改后的数据并将其写入 YAML 文件了。
        • 那么你建议如何使用 Ansible 中常用的模块来做呢?
        • 我发现这个答案很有用,因为链接页面描述了一组修改(文本)文件的可能性。尽管如此,在本案例中提出的唯一可能的解决方案是lineinfile 方法,该方法仅在简单的情况下有用。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-02-04
        • 1970-01-01
        • 1970-01-01
        • 2013-12-27
        • 1970-01-01
        • 2019-09-29
        • 1970-01-01
        相关资源
        最近更新 更多