Copie vários arquivos com o Ansible

104

Como posso copiar mais de um único arquivo em nós remotos por Ansible em uma tarefa?

Eu tentei duplicar a linha do módulo de cópia em minha tarefa para definir arquivos, mas ela apenas copia o primeiro arquivo.

Marca
fonte

Respostas:

131

Você pode usar o with_fileglobloop para isso:

- copy:
    src: "{{ item }}"
    dest: /etc/fooapp/
    owner: root
    mode: 600
  with_fileglob:
    - /playbooks/files/fooapp/*
Arbab Nazar
fonte
3
Essa abordagem poderia me ajudar se eu tivesse todos os meus arquivos na mesma raiz para copiar na máquina remota, que tal ter alguns arquivos em vários diretórios. Por exemplo, quero copiar 3 arquivos de 3 diretórios diferentes
Marcos,
Ei, estou tentando mover todos os arquivos do meu, /roles/db/filesmas não consigo fazê-lo funcionar com este método. Eu tentei, with_fileglob: - /roles/db/file/* mas não consegui resolver o caminho
Batman
A grande desvantagem desse método é que ele nivela a estrutura do diretório.
Quintin Par
115
- name: Your copy task
  copy: src={{ item.src }} dest={{ item.dest }}
  with_items:
    - { src: 'containerizers', dest: '/etc/mesos/containerizers' }
    - { src: 'another_file', dest: '/etc/somewhere' }
    - { src: 'dynamic', dest: '{{ var_path }}' }
  # more files here
guenhter
fonte
É possível ter essa solução com o destconjunto como variável? { src: 'containerizers', dest: {{ containerizers }} }.
Gesias
2
@Gesias, sim. Na verdade, ambos os lados podem ser variáveis:{ src: '{{ source.var }}', dest: '{{ dest.var }}' }
ntwrkguru
16

Você pode usar with_together para esta finalidade:

- name: Copy multiple files to multiple directories
  copy: src={{ item.0 }} dest={{ item.1 }}
  with_together:
    - [ 'file1', 'file2', 'file3' ]
    - [ '/dir1/', '/dir2/', '/dir3/' ]
Mircea Husz
fonte
Embora funcione, isso não é semanticamente limpo - existem opções mais limpas.
plesiv
11

Se você precisar de mais de um local, precisará de mais de uma tarefa. Uma tarefa de cópia pode copiar apenas de um local (incluindo vários arquivos) para outro no nó.

- copy: src=/file1 dest=/destination/file1
- copy: src=/file2 dest=/destination/file2

# copy each file over that matches the given pattern
- copy: src={{ item }} dest=/destination/
  with_fileglob:
    - /files/*
flxPeters
fonte
- nome: copiar arquivo1 cópia: src = / arquivo1 dest = / destino / arquivo1 - nome: copiar arquivo2 cópia: src = / arquivo2 dest = / destino / arquivo2
Marcar em
Depende. Mais simples e provavelmente mais limpo, mas pode ser feito usando estruturas de dados mais complexas, como uma lista de dicionários anônimos com dados de origem e destino, em loop com_itens. É o mesmo em qualquer idioma - você tem que fazer um julgamento. Há casos em que uma função de delegação é mais eficiente e sustentável do que uma longa série de instruções if de copiar / colar. Sou aquela aberração que prefere manter a parte concisa de um código bem estruturado do que uma lista longa e tediosa de diretivas quase idênticas, mas não presumo que todos concordem. Faça o que é sustentável para você.
Paul Hodges
8

Desde o Ansible 2.5, as with_*construções estão obsoletas e a loopsintaxe deve ser usada. Um exemplo prático simples:

- name: Copy CA files
  copy:
    src: '{{item}}'
    dest: '/etc/pki/ca-trust/source/anchors'
    owner: root
    group: root
    mode: 0644
  loop:
    - symantec-private.crt
    - verisignclass3g2.crt

Richlv
fonte
7
- hosts: lnx
  tasks:
    - find: paths="/appl/scripts/inq" recurse=yes patterns="inq.Linux*"
      register: file_to_copy
    - copy: src={{ item.path }} dest=/usr/local/sbin/
      owner: root
      mode: 0775
      with_items: "{{ files_to_copy.files }}"
Diego roberto dos santos
fonte
apenas uma nota lateral que o findmódulo só funciona para ansible 2.x, mas não para ansible 1.x
Arbab Nazar
Corrigi sua resposta porque você mencionou stdout_linesno valor de retorno, mas não é aplicável para o findmódulo. Tem apenas files, examinede matchedcomo valores de retorno. Espero que ajude outros
Arbab Nazar
2
Alguém conseguiu fazer isso funcionar para copiar arquivos para nós remotos? findsó parece olhar para o sistema remoto, não permitindo pegar nada do nó de gerenciamento. Essas respostas, usando with_fileglob, parecem ser mais adequadas: stackoverflow.com/a/42290160/272387 , stackoverflow.com/a/36720342/272387 .
Richlv
4

Ou você pode usar with_items:

- copy:
    src: "{{ item }}"
    dest: /etc/fooapp/
    owner: root
    mode: 600
  with_items:
    - dest_dir
MxWild
fonte
3
- name: find inq.Linux*
  find:  paths="/appl/scripts/inq" recurse=yes patterns="inq.Linux*"
  register: find_files


- name: set fact
  set_fact:
    all_files:
      - "{{ find_files.files | map(attribute='path') | list }}"
  when: find_files > 0


- name: copy files
  copy:
    src: "{{ item }}"
    dest: /destination/
  with_items: "{{ all_files }}"
  when: find_files > 0
Fredric Andersson
fonte
6
Uma boa resposta contém não apenas código, mas também algumas explicações ou referências de documentação.
Laurenz Albe de
Os módulos find, set_fact e copy são explicados na documentação ansible. Leia sobre filtros, também explicados na documentação do ansible se você quiser saber mais sobre esta seção (- "{{find_files.files | map (attribute'path ') | list}}")
Fredric Andersson
1

Você pode percorrer a variável com a lista de diretórios:

- name: Copy files from several directories
  copy:
    src: "{{ item }}"
    dest: "/etc/fooapp/"
    owner: root
    mode: "0600"
  loop: "{{ files }}"
  vars:
    files:
      - "dir1/"
      - "dir2/"
Stan
fonte
1

Use o seguinte código-fonte para copiar vários arquivos em sua máquina cliente.


 - name: Copy data to the client machine
   hosts: hostname
   become_method: sudo
   become_user: root
   become: true
   tasks: 
     # Copy twice as sometimes files get skipped (mostly only one file skipped from a folder if the folder does not exist)
     - name: Copy UFO-Server 
       copy:
         src: "source files path"
         dest: "destination file path"
         owner: root
         group: root
         mode: 0644
         backup: yes
       ignore_errors: true

Nota:

Se você estiver passando vários caminhos usando a variável, então

src: "/ root / {{item}}"

Se você está passando o caminho usando uma variável para itens diferentes, então

src: "/ root / {{item.source_path}}"

Shaha Nawaj Mulla
fonte
0

copymódulo é uma ferramenta errada para copiar muitos arquivos e / ou estrutura de diretório, use o synchronizemódulo que usa rsynccomo backend. Lembre-se de que ele requer rsyncinstalação no controlador e no host de destino. É realmente poderoso, verifique a documentação do ansible .

Exemplo - copie arquivos do builddiretório (com subdiretórios) do controlador para o /var/www/htmldiretório no host de destino:

synchronize:
  src: ./my-static-web-page/build/
  dest: /var/www/html
  rsync_opts:
    - "--chmod=D2755,F644" # copy from windows - force permissions
mrówa
fonte