如何在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
逻辑说明:
dict2items将键值对字典转换为[{key: "节点名", value: "设备名"}, ...]的列表json_query生成符合YAML结构的数组to_json转为JSON格式传给yq,yq自动解析并生成带引号的YAML
内容的提问来源于stack exchange,提问作者Stefanita Vilcu
相关产品推荐
相关产品推荐

