Implantando uma pasta de arquivos de modelo usando o ansible

47

Existe uma maneira fácil de implantar uma pasta cheia de pasta .j2 de modelo em uma caixa Linux, usando o mesmo nome que o modelo, mas sem a extensão .j2, em vez de usar o módulo de modelo para cada arquivo?

Agora eu tenho uma longa lista de:

- name: create x template
  template:
    src=files/x.conf.j2
    dest=/tmp/x.conf
    owner=root
    group=root
    mode=0755
  notify:
    - restart myService
Trololololol
fonte

Respostas:

67

Você pode usar with_fileglobpara obter a lista de arquivos do diretório de modelos e usar filtros para remover a extensão j2 dessa maneira.

- name: create x template
  template:
    src: {{ item }}
    dest: /tmp/{{ item | basename | regex_replace('\.j2','') }}
  with_fileglob:
    - ../templates/*.j2
Russell
fonte
11
note que with_fileglobsempre opera a partir de files/, você pode obter modelos com ../templates/mytemplate/*. stackoverflow.com/a/27407566/1695680
ThorSummoner
2
Obrigado, isso é super útil. Eu descobri que tinha que usar duas barras invertidas para escapar do período literal na função regex_replace. Talvez porque eu tinha a parte inteira do modelo de destino entre aspas duplas para poder usar o formato YAML para a definição da tarefa (que eu prefiro sobre o formato de uma linha).
Tony Cesaro
11
isso pressupõe que apenas arquivos estejam na pasta de modelos, se você precisar suportar diretórios e arquivos na pasta de modelos, precisará de with_filetree - consulte stackoverflow.com/questions/41667864/…
danday74
Uma observação que regex_replacedeve corresponder no final da linha \.j2$para os casos em que o padrão pode existir dentro do nome do arquivo.
Brett Ryan
20

Michael DeHaan (criador do Ansible) fez um post no CoderWall que fala sobre assuntos muito semelhantes. Você pode ajustá-lo e expandi-lo de acordo com suas necessidades (como permissões e propriedade). Parte relevante da postagem está aqui:


Isso pode ser simplificado usando " with_items" e uma única notifyinstrução. Se alguma das tarefas for alterada, o serviço será notificado exatamente da mesma maneira que precisa reiniciar no final da execução do manual.

 - name:  template everything for fooserv
   template: src={{item.src}} dest={{item.dest}}
   with_items:
      - { src: 'templates/foo.j2', dest: '/etc/splat/foo.conf' }
      - { src: 'templates/bar.j2', dest: '/etc/splat/bar.conf' }
   notify: 
      - restart fooserv

Observe que, como temos tarefas que levam mais de um argumento único, não apenas dizemos " item" na template:linha ' ', mas usamos with_itemscom uma variável de hash (dicionário). Você também pode mantê-lo um pouco mais curto usando listas, se quiser. Esta é uma preferência estilística:

 - name:  template everything for fooserv
   template: src={{item.0}} dest={{item.1}}
   with_items:
      - [ 'templates/foo.j2', '/etc/splat/foo.conf' ]
      - [ 'templates/bar.j2', '/etc/splat/bar.conf' ]
   notify: 
      - restart fooserv

É claro que também poderíamos definir a lista em que você estava navegando em outro arquivo, como um " groupvars/webservers" arquivo para definir todas as variáveis ​​necessárias para o webserversgrupo ou um arquivo YAML carregado da varsfilesdiretiva " " dentro do manual. Veja como isso pode ser resolvido se o fizermos.

- name: template everything for fooserv
  template: src={{item.src}} dest={{item.dest}}
  with_items: {{fooserv_template_files}}
  notify: 
      - restart fooserv
Mxx
fonte
5
Um método mais simples pode ser escrever template: src=templates/{{item}}.j2 dest=/etc/splat/{{item}}.confe, em seguida, usar uma lista simples de itens:with_items: - foo - bar
Ethan
Isso realmente parece errado agora. A linha correta do modelo seria template: src={{item.src}} dest={{item.dest}}(ou seja, ${var}mas não melhor {{var}}) #
Fabiano Francesconi
@FabianoFrancesconi atualizado.
Mxx13:
9

A resposta de Russel funciona, mas precisa ser aprimorada

- name: create x template
- template: src={{ item }} dest=/tmp/{{ item | basename | regex_replace('.j2','') }}
- with_fileglob:
   - files/*.j2

Os abetos de todos os $ precisam ir, pois estava errado na regex no regex_replace. Em segundo lugar, todos os arquivos devem estar no diretório de arquivos, e não no diretório de modelos

HJ_VORTEX
fonte
4
Bem-vindo à falha do servidor! Sua resposta sugere que uma solução viável para a pergunta está disponível por meio de uma resposta anterior; portanto, seria mais apropriado como uma edição dessa resposta. Considere excluir sua resposta atual e sugerir uma edição na resposta de Russell.
Paul
7

Eu escrevi um plug-in de pesquisa de arquivos de filas que pode ajudar com ações em árvores de arquivos.

Você pode repetir os arquivos em uma árvore de arquivos e, com base nas propriedades do arquivo, executar ações (por exemplo, modelo ou cópia). Como o caminho relativo é retornado, você pode recriar a árvore de arquivos no (s) sistema (s) de destino com facilidade.

- name: Template complete tree
  template:
    src: '{{ item.src }}'
    dest: /web/{{ item.path }}
    force: yes
  with_filetree: some/path/
  when: item.state == 'file'

Isso cria playbooks mais legíveis.

Dag Wieers
fonte
Ainda não foi mesclado :-(
Morgan Christiansson
2
Foi mesclado.
Dag Wieers 26/09/16
Existe uma maneira de filtrar, digamos, apenas arquivos * .conf?
Andrey
Claro, na parte "quando:" você pode escrever uma expressão que atenda às suas necessidades.
Dag Wieers
11
O plug-in não é lento, é o processo de modelar e copiar cada arquivo individualmente que o torna lento. Mas isso não tem quase nada a ver com o plug-in, o plug-in poderia ser útil para outras coisas além de modelar ou copiar.
Dag Wieers
3

O comando abaixo trabalhou para mim fazer uma pesquisa recursiva para arquivos j2 em modelos e movê-lo para o destino. Espero que ajude alguém que procura uma cópia recursiva de modelos ao destino.

     - name: Copying the templated jinja2 files
       template: src={{item}} dest={{RUN_TIME}}/{{ item | regex_replace(role_path+'/templates','') | regex_replace('\.j2', '') }}
       with_items: "{{ lookup('pipe','find {{role_path}}/templates -type f').split('\n') }}"
Robin
fonte
1

Existe a possibilidade de pegar a lista de arquivos reais do diretório automaticamente e iterá-los depois.

- name:         get the list of templates to transfer
  local_action: "shell ls templates/* | sed 's~.*/~~g'"
  register:     template_files

- name:         iterate and send templates
  template:     src=templates/{{ item }} dest=/mydestination/{{ item }}
  with_items:
  - "{{ template_files.stdout.splitlines() }}"
Roman Dolejsi
fonte
Observe a advertência padrão sobre a divisão em nova linha - os nomes de arquivos podem conter novas linhas. Uma solução mais segura é usar um utilitário de shell que suporte print0, como find, e depois dividir \u0000.
precisa saber é o seguinte