You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Ansible中使用yq为插入的YAML项添加引号?

为yq插入的YAML字符串添加强制引号的解决方案

问题场景

使用Ansible(core 2.16.5)调用yq(v4.43.1)向YAML文件中添加节点配置条目时,插入的值内容正确,但YAML输出中字符串未被引号包裹,需要找到无需使用ansible.builtin.replace的更优方案。

原Playbook代码:

---
- name: Customize cluster.yaml
  hosts: localhost
  vars:
    rook_tag: "v1.14.0"
    ceph_datapath:
      rpi4b-1: "sda3"
      rpi4b-2: "sda3"
      rpi4b-3: "sda3"
      rpi4b-4: "sda3"
      rpi4b-5: "sda3"
      rock3a: "nvme0n1p3"
      vim4: "nvme0n1"
      nanopct6: "mmcblk0p3"
      opi5p: "mmcblk0p3"
      rock5b: "mmcblk0p3"
  tasks:
    - name: Download cluster.yaml manifest from Internet
      ansible.builtin.get_url:
        url: "https://raw.githubusercontent.com/rook/rook/{{ 'release-' + '.'.join(''.join(rook_tag.split('v')[1:]).split('.')[:2]) }}/deploy/examples/cluster.yaml"
        dest: ./cluster.yaml
        mode: '0664'

    - name: Set spec.storage.config.nodes
      ansible.builtin.shell: >
        /usr/local/bin/yq -i '.spec.storage.config.nodes += [{"name": "{{ item.key }}", "devices": [{"name": "{{ item.value }}"}]}]' cluster.yaml
      with_dict: "{{ ceph_datapath }}"
      register: command_output
      changed_when: command_output.rc == 0

生成的YAML片段(缺少引号):

config:
      nodes:
        - name: rpi4b-1
          devices:
            - name: sda3
        - name: rpi4b-2
          devices:
            - name: sda3
        - name: rpi4b-3
          devices:
            - name: sda3
        - name: rpi4b-4
          devices:
            - name: sda3
        - name: rpi4b-5
          devices:
            - name: sda3
        - name: rock3a
          devices:
            - name: nvme0n1p3
        - name: vim4
          devices:
            - name: nvme0n1
        - name: nanopct6
          devices:
            - name: mmcblk0p3
        - name: opi5p
          devices:
            - name: mmcblk0p3
        - name: rock5b
          devices:
            - name: mmcblk0p3

解决方案

方法1:使用yq的全局引号风格参数

yq v4支持--quote-style参数,指定输出字符串的引号格式,直接在命令中添加该参数即可强制所有字符串使用双引号:

- name: Set spec.storage.config.nodes (强制双引号)
  ansible.builtin.shell: >
    /usr/local/bin/yq -i --quote-style double '.spec.storage.config.nodes += [{"name": "{{ item.key }}", "devices": [{"name": "{{ item.value }}"}]}]' cluster.yaml
  with_dict: "{{ ceph_datapath }}"
  register: command_output
  changed_when: command_output.rc == 0

参数说明:--quote-style double会让yq对所有字符串输出双引号,也可指定single使用单引号。

方法2:在yq表达式中显式标记字符串类型

通过| str过滤器强制将值转为带引号的字符串类型,仅对指定字段生效:

- name: Set spec.storage.config.nodes (字段级强制引号)
  ansible.builtin.shell: >
    /usr/local/bin/yq -i '.spec.storage.config.nodes += [{"name": "{{ item.key }}" | str, "devices": [{"name": "{{ item.value }}" | str}]}]' cluster.yaml
  with_dict: "{{ ceph_datapath }}"
  register: command_output
  changed_when: command_output.rc == 0

方法3:批量生成节点配置(推荐,减少shell调用)

避免循环逐个添加,利用Ansible过滤器将ceph_datapath直接转换为目标结构,一次性传给yq,提升效率:

- name: Set spec.storage.config.nodes (批量添加)
  ansible.builtin.shell: >
    /usr/local/bin/yq -i --quote-style double '.spec.storage.config.nodes = {{ ceph_datapath | dict2items | json_query("[].{name: key, devices: [{name: value}]}") | to_json }}' cluster.yaml

逻辑说明:

  1. dict2items将键值对字典转换为[{key: "节点名", value: "设备名"}, ...]的列表
  2. json_query生成符合YAML结构的数组
  3. to_json转为JSON格式传给yq,yq自动解析并生成带引号的YAML

内容的提问来源于stack exchange,提问作者Stefanita Vilcu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 15:52:50