如何使用ansible有条件地复制文件?

How to conditionally copy files using ansible?

请参考下面的配置,想法是,如果找到配置文件,请部署配置

我尝试了很多表达这个想法的变体,尤其是在最后 3 行中,但我无法全神贯注将 stat 循环的结果与我的部署循环结合起来 以一种有意义的方式

我的结构列表如下:

config_vars:
  - war_name: TestNode_app1.war
    standalone_name: jboss_standalone.xml
    jboss_service_name: jboss_app1
    jboss_folder: jboss_app1
  - war_name: TestNode_app2.war
    standalone_name: jboss_app2_standalone.xml
    jboss_service_name: jboss_app2
    jboss_folder: jboss_app2

我有剧本

...
...

tasks:
  - name: check if war exists
    stat:
      path: files/wars/{{ item.war_name }}
    register: war_file
    loop: "{{ config_vars }}"

  - name: Deploy config file
    copy: src=files/wars/{{ item.war_name }} dest=/opt/{{ item.jboss_folder }}/standalone/deployments/{{ item.war_name }}
    when: item.stat.exists
    loop: "{{ config_vars }}"
    with_items: war_file.results

预期结果:对于存在的 war 文件,部署循环应该选取它并进行复制。如果不存在,则不采取任何行动 实际结果:多种多样。对于上面的配置,我有:

ERROR! duplicate loop in task: items
The offending line appears to be:


    - name: deploy WAR file
      ^ here

这可以通过 loopzip 实现(替换旧的 with_together 循环)。

  - name: Deploy config file
    copy: src=files/wars/{{ item.0.war_name }} dest=/opt/{{ item.0.jboss_folder }}/standalone/deployments/{{ item.0.war_name }}
    when: item.1.stat.exists
    loop: "{{ config_vars | zip(war_file.results) | list }}"

这将产生相当冗长的输出,因此如果您想将其最小化,请添加如下内容:

  loop_control:
    label: "Copy {{ item.0.war_name }}"

确实,您确实有 duplicate loop in taskloopwith_items 都是循环结构。

这里有一个简单的剧本来演示如何实现这一点。您甚至不需要使用 Matt P 提供的 with_together 结构,但是为了可读性,您可能需要使用。

- hosts: localhost
  connection: local
  gather_facts: false
  vars:
    config_vars:
      - filepath: ./f1.txt
        other: 'here'
      - filepath: ./f2.txt
        other: 'also here'
  tasks:
    - name: check if war exists
      stat:
        path: "{{ item.filepath }}"
      register: war_file
      loop: "{{ config_vars }}"
    - debug:
        msg: "Copying {{ item.item }}"
      when: item.stat.exists
      loop: "{{ war_file.results }}"

结果(仅给出 f2.txt 存在):

PLAY [localhost] *****************************************************************************************************************************************************************

TASK [check if war exists] *******************************************************************************************************************************************************
ok: [localhost] => (item={'filepath': './f1.txt', 'other': 'here'})
ok: [localhost] => (item={'filepath': './f2.txt', 'other': 'also here'})

TASK [debug] *********************************************************************************************************************************************************************
skipping: [localhost] => (item={'changed': False, 'stat': {'exists': False}, 'invocation': {'module_args': {'path': './f1.txt', 'follow': False, 'get_checksum': True, 'get_mime': True, 'get_attributes': True, 'checksum_algorithm': 'sha1', 'get_md5': None}}, 'failed': False, 'item': {'filepath': './f1.txt', 'other': 'here'}, 'ansible_loop_var': 'item'})
ok: [localhost] => (item={'changed': False, 'stat': {'exists': True, 'path': './f2.txt', 'mode': '0644', 'isdir': False, 'ischr': False, 'isblk': False, 'isreg': True, 'isfifo': False, 'islnk': False, 'issock': False, 'uid': 501, 'gid': 20, 'size': 0, 'inode': 8626896681, 'dev': 16777220, 'nlink': 1, 'atime': 1572930945.6961422, 'mtime': 1572930850.452235, 'ctime': 1572930850.452235, 'wusr': True, 'rusr': True, 'xusr': False, 'wgrp': False, 'rgrp': True, 'xgrp': False, 'woth': False, 'roth': True, 'xoth': False, 'isuid': False, 'isgid': False, 'blocks': 0, 'block_size': 4096, 'device_type': 0, 'flags': 0, 'generation': 0, 'birthtime': 1572930850.452235, 'readable': True, 'writeable': True, 'executable': False, 'pw_name': 'pwd', 'gr_name': 'staff', 'checksum': 'da39a3ee5e6b4b0d3255bfef95601890afd80709', 'mimetype': 'unknown', 'charset': 'unknown', 'version': None, 'attributes': [], 'attr_flags': ''}, 'invocation': {'module_args': {'path': './f2.txt', 'follow': False, 'get_checksum': True, 'get_mime': True, 'get_attributes': True, 'checksum_algorithm': 'sha1', 'get_md5': None}}, 'failed': False, 'item': {'filepath': './f2.txt', 'other': 'also here'}, 'ansible_loop_var': 'item'}) => {
    "msg": "Copying {'filepath': './f2.txt', 'other': 'also here'}"
}

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

请注意,war_file.results 的每个元素中都提供了 item 字典元素。此 item 包含 stat 循环中使用的项目。

这里是关于循环的更多信息:https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html

谢谢你们。以下现在运行良好:

tasks:
  - name: check if war exists
    local_action: stat path=files/wars/{{ item.war_name }}
    register: war_file
    loop: "{{ config_vars }}"

  - name: deploy war file
    become: yes
    become_user: jboss-as
    copy: |
      src=files/wars/{{ item.item.war_name }}
      dest=/opt/{{ item.item.jboss_folder }}/standalone/deployments/{{ item.item.war_name }}
    when: item.stat.exists
    loop: "{{ war_file.results }}"