首页 > 解决方案 > Ansible XML 更新

问题描述

我有一个使用 ansible 创建的 xml 文件。xml文件的输出如下。

<?xml version="1.0" encoding="UTF-8"?>
<files>
   <file filename="/tmp/dir2/6" group="root" permission="600" user="root" is_exists="True" target_permission="600" />
   <file filename="/tmp/dir2/5" group="root" permission="600" user="root" is_exists="True" target_permission="600" />
</files>

target_permission在这个 xml 文件中创建了一个属性。现在我需要把它分成三个。( user_perm="6" grp_perm="0" oth_perm="0")

Ansible 中有没有办法做到这一点?

  - name: Update XML with file permissions mismatch
    xml:
     path: "{{output_file}}"
     xpath: /files/file
     attribute: user_perm
     value: 'target_permission | split[0:1]'  // I need something like this, what will be the syntax?

标签: xmlansible

解决方案


由于 Jinja 允许使用Python 方法,是的,您可以像在纯 Python 中一样对字符串进行切片:

- debug:
    msg: >-
      user_perm: {{ perm[0:1] }}
      grp_perm: {{ perm[1:2] }}
      oth_perm: {{ perm[2:] }}
  vars:
    perm: "600"

您也可以按照文档中的提示使用列表过滤器:

如果它是一个字符串,则返回的列表将是一个字符列表。

- debug:
    msg: >-
      user_perm: {{ (perm | list)[0] }}
      grp_perm: {{ (perm | list)[1] }}
      oth_perm: {{ (perm | list)[2] }}
  vars:
    perm: "600"

这两种语法都给出:

PLAY [all] ********************************************************************************************************

TASK [debug] ******************************************************************************************************
ok: [localhost] => {
    "msg": "user_perm: 6 grp_perm: 0 oth_perm: 0"
}

PLAY RECAP ********************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

现在,为了更改您在 xml 中的现有节点,您必须分两步进行,一是读取现有 XML,二是填写value,因为它是一个简单的原始参数

我会说,在您的情况下,最好的方法是通过xpath基于您的filename属性来定位正确的 XML 元素:

鉴于剧本

- hosts: all
  gather_facts: no    
        
  tasks:
    - xml:
        path: xml.xml
        xpath: /files/file
        content: attribute
      register: xml
      
    - xml:
        path: xml.xml
        xpath: '/files/file[@filename="{{ item.file.filename }}"]'
        attribute: user_perm
        value: "{{ item.file.permission[0:1] }}"
      loop: "{{ xml.matches }}"

还有你的 xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<files>
   <file filename="/tmp/dir2/6" group="root" permission="600" user="root" is_exists="True" target_permission="600" />
   <file filename="/tmp/dir2/5" group="root" permission="600" user="root" is_exists="True" target_permission="600" />
</files>

这产生了回顾:

PLAY [all] **************************************************************************************

TASK [xml] **************************************************************************************
ok: [localhost]

TASK [xml] **************************************************************************************
changed: [localhost] => (item={'file': {'filename': '/tmp/dir2/6', 'group': 'root', 'permission': '600', 'user': 'root', 'is_exists': 'True', 'target_permission': '600'}})
changed: [localhost] => (item={'file': {'filename': '/tmp/dir2/5', 'group': 'root', 'permission': '600', 'user': 'root', 'is_exists': 'True', 'target_permission': '600'}})

PLAY RECAP **************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

并给出生成的 xml:

<?xml version='1.0' encoding='UTF-8'?>
<files>
   <file filename="/tmp/dir2/6" group="root" permission="600" user="root" is_exists="True" target_permission="600" user_perm="6"/>
   <file filename="/tmp/dir2/5" group="root" permission="600" user="root" is_exists="True" target_permission="600" user_perm="6"/>
</files>

只需对其他属性重复此操作,您就有了您所要求的行为。


推荐阅读