Ansible: копирование нескольких файлов из нескольких источников в несколько мест назначения в одной команде - PullRequest
1 голос
/ 25 апреля 2020

Я пытаюсь скопировать некоторые файлы конфигурации из / tmp в / opt. Здесь сначала я рекурсивно ищу файлы в каталогах / tmp и / opt и сохраняю их в переменных tmp_file_path и code_file_path соответственно, которые имеют атрибут files.path, который мне нужно использовать в источнике и месте назначения для копирования

- name: Find files in tmp
  find:
    paths: /tmp/
    file_type: file
    recurse: yes
    patterns:
      - file1
      - file2
      - file3
  register: tmp_file_path
- debug:
    var: tmp_file_path

- name: Find files in code
  find:
    paths: /opt/
    file_type: file
    recurse: yes
    patterns: 
      - file1
      - file2
      - file3
  register: code_file_path
- debug:
    var: code_file_path

Здесь пути к исходным файлам могут быть / tmp / folder1 / file1, / tmp / folder2 / file2, / tmp / folder13 / file3. Пунктами назначения могут быть / opt / folderA / file1, / opt / folderB / file3, / opt / folderC / file3

На данный момент мне удалось написать задачу, как показано ниже

- name: Copy files from tmp to code directory
  copy:
    src: "{{item.path}}"
    dest: "{{item.path}}"
    remote_src: yes
  with_items:
    - { "{{ tmp_file_path.files }}", "{{ code_file_path.files }}" }

Копирование должно быть выполнено одной командой, чтобы я не стал жестко задавать пути для источника и места назначения. Может ли кто-нибудь помочь мне в достижении этого?

Приведенный ниже фрагмент кода работал для рекурсивного копирования файлов из code_file_path в / tmp

- name: Copy files from code directory to tmp
  copy:
    src: "{{item.path}}"
    dest: /tmp/
    remote_src: yes
  with_items: "{{code_file_path.files}}"

Ответы [ 2 ]

1 голос
/ 26 апреля 2020

Этого можно добиться с помощью следующего условия: каждое имя файла уникально, так как если в вашем списке из одного каталога / opt 2 файла имеют одинаковые имена, их содержимое должно быть одинаковым.

Если это В этом случае вы можете использовать with_nested l oop и использовать условный при в имени файла.

Например:

- name: Copy files from tmp to code directory
  copy:
    src: "{{ item.0 }}"
    dest: "{{ item.1 }}"
    remote_src: yes
  when: 
    - item.0|basename == item.1|basename
  with_nested:
    - "{{ tmp_file_path.files|map(attribute='path')|list }}"
    - "{{ code_file_path.files|map(attribute='path')|list }}"

Единственная «проблема» с этим решением - вы часто запускаете l oop ...

Вы также можете использовать l oop синтакс над с_ синтаксом и используйте немного loop_control , чтобы выбрать, что будет напечатано: https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html


Если у вас есть Загруженное расширение jinja.ext.do (в вашем ansible .cfg: jinja2_extensions = jinja2.ext.do) вы можете затем создать dict с вашими путями:

- name: Make a dict
  set_fact:
    files_dict: |
      {%- set out_dict = dict() -%}
      {%- for tmp_file in tmp_file_path.files|map(attribute='path')|list -%}
      {%-   do out_dict.update({tmp_file|basename: {'tmp': tmp_file}}) -%}
      {%- endfor -%}
      {%- for opt_file in code_file_path.files|map(attribute='path')|list -%}
      {%-   do out_dict[opt_file|basename].update({'opt': opt_file}) -%}
      {%- endfor -%}
      {{ out_dict }}

- name: Copy from dict
  copy:
    src: "{{ item.value.tmp }}"
    dest: "{{ item.value.opt }}"
    remote_src: yes
  with_dict: "{{ files_dict }}"
1 голос
/ 26 апреля 2020

Попробуйте это

- name: Copy files from tmp to code directory
  copy:
    src: "{{ item.0 }}"
    dest: "{{ item.1 }}"
    remote_src: yes
  with_together:
    - "{{ tmp_file_path.files|map(attribute='path')|list|sort }}"
    - "{{ code_file_path.files|map(attribute='path')|list|sort }}"

Попробуйте сначала отладить

    - debug:
        msg:
          - "src: {{ item.0 }}"
          - "dest: {{ item.1 }}"
      with_together:
        - "{{ tmp_file_path.files|map(attribute='path')|list|sort }}"
        - "{{ code_file_path.files|map(attribute='path')|list|sort }}"

Может быть полезно сначала проверить здравомыслие

    - debug:
        msg: The numbers of files do not match
      when: tmp_file_path.files|map(attribute='path')|list|length !=
            code_file_path.files|map(attribute='path')|list|length

Q: "Это не сработало, как ожидалось, потому что файлы, которые я ищу в code_file_path, имеют несколько подкаталогов. Это сортировка по всему пути к файлу, возвращаемому code_file_path.files, а не только по имени файла."

A: Создать список с путями и именами. Затем отсортируйте список по имени. Например

    - set_fact:
        code_files: "{{ code_files|default([]) +
                        [{'path': item, 'name': item|basename}] }}"
      loop: "{{ code_file_path.files|map(attribute='path')|list }}"

    - debug:
        msg:
          - "src: {{ item.0 }}"
          - "dest: {{ item.1.path }}"
      with_together:
        - "{{ tmp_file_path.files|map(attribute='path')|list|sort }}"
        - "{{ code_files|sort(attribute='name') }}"

Пример

shell> tree tmp
tmp
├── file1
├── file2
└── file3

shell> tree opt
opt
├── bar
│   └── file2
├── baz
│   └── file3
└── foo
    └── file1

Задачи ниже

    - set_fact:
        code_files: "{{ code_files|default([]) +
                        [{'path': item, 'name': item|basename}] }}"
      loop: "{{ code_file_path.files|map(attribute='path')|list }}"

    - debug:
        var: code_files|sort(attribute='name')

    - debug:
        msg:
          - "src: {{ item.0 }}"
          - "dest: {{ item.1.path }}"
      with_together:
        - "{{ tmp_file_path.files|map(attribute='path')|list|sort }}"
        - "{{ code_files|sort(attribute='name') }}"

дают


    "code_files|sort(attribute='name')": [
        {
            "name": "file1", 
            "path": "/export/test/opt/foo/file1"
        }, 
        {
            "name": "file2", 
            "path": "/export/test/opt/bar/file2"
        }, 
        {
            "name": "file3", 
            "path": "/export/test/opt/baz/file3"
        }
    ]

    "msg": [
        "src: /export/test/tmp/file1", 
        "dest: /export/test/opt/foo/file1"
    ]

    "msg": [
        "src: /export/test/tmp/file2", 
        "dest: /export/test/opt/bar/file2"
    ]

    "msg": [
        "src: /export/test/tmp/file3", 
        "dest: /export/test/opt/baz/file3"
    ]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...