¿Cómo usar el módulo de plantilla con diferentes conjuntos de variables?

93

Mi caso de uso es el siguiente:

Tengo un archivo de plantilla y me gustaría crear 2 archivos diferentes a partir de esa plantilla, con las variables llenas de un conjunto diferente de variables para cada archivo.

Por ejemplo, digamos que quiero modelar el archivo que contiene la línea:

mkdir -p {{myTemplateVariable}}

Me gustaría encontrar una forma adecuada de llenar esta variable con "Archivo1" y "Archivo2". Algo como :

- name: template test 1
  template: 
        src=myTemplateFile
        dest=result1


- name: template test 2
  template: 
        src=myTemplateFile
        dest=result2

donde podría especificar para la primera plantilla que la variable a usar es a = "Archivo1" y para la segunda, b = "Archivo2".

Kestemont Max
fuente
¿Es eso exactamente lo que hago con todas mis recetas, mira este comentario stackoverflow.com/a/40189525/1571310 , espero que esto te ayude!
Tecnocat

Respuestas:

52

Para Ansible 2.x:

- name: template test
  template: 
    src: myTemplateFile
    dest: result1
  vars:
    myTemplateVariable: File1

- name: template test
  template: 
    src: myTemplateFile
    dest: result2
  vars:
    myTemplateVariable: File2

Para Ansible 1.x:

Desafortunadamente, el templatemódulo no admite el paso de variables, que se pueden usar dentro de la plantilla. Hubo una solicitud de función pero fue rechazada.

Puedo pensar en dos soluciones:

1. Incluir

La includedeclaración admite el paso de variables. Por lo tanto, podría tener su templatetarea dentro de un archivo adicional e incluirlo dos veces con los parámetros adecuados:

my_include.yml:

- name: template test
  template: 
        src=myTemplateFile
        dest=destination

main.yml:

- include: my_include.yml destination=result1 myTemplateVariable=File1

- include: my_include.yml destination=result2 myTemplateVariable=File2

2. Vuelva a definir myTemplateVariable

Otra forma sería simplemente volver a definir myTemplateVariable justo antes de cada templatetarea.

- set_fact:
     myTemplateVariable: File1

- name: template test 1
  template: 
        src=myTemplateFile
        dest=result1

- set_fact:
     myTemplateVariable: File2

- name: template test 2
  template: 
        src=myTemplateFile
        dest=result2
udondan
fuente
Gracias por la respuesta. Sin embargo, ¿es realmente imposible prescindir de soluciones alternativas? Actualmente estoy intentando algo como: stackoverflow.com/questions/26020465/… , pero todavía tengo algunos errores (quizás no directamente relacionados).
Kestemont Max
Sí, también puede hacerlo con un bucle, pero es una solución alternativa. :)
udondan
14
ya no es necesario. "vars" ahora es compatible. vea la respuesta de @ konstantin-suvorov a continuación.
sonjz
123

Con Ansible 2.x puedes usarlo vars:con tareas.

Plantilla test.j2:

mkdir -p {{myTemplateVariable}}

Libro de jugadas:

- template: src=test.j2 dest=/tmp/File1
  vars:
    myTemplateVariable: myDirName

- template: src=test.j2 dest=/tmp/File2
  vars:
    myTemplateVariable: myOtherDir

Esto pasará diferentes myTemplateVariablevalores a test.j2.

Konstantin Suvorov
fuente
9
Inicialmente cometí un error y tenía vars: sangrado como el resto de los argumentos de la plantilla (como src :). Supongo que el nivel de sangría significa vars: es de la tarea, no de la plantilla. Así que puedes hacer esto en cualquier lugar, no solo en plantillas. bonito.
Greg
39

Puedes hacer esto muy fácil, mira mi receta de Supervisor:

- name: Setup Supervisor jobs files
  template:
    src: job.conf.j2
    dest: "/etc/supervisor/conf.d/{{ item.job }}.conf"
    owner: root
    group: root
    force: yes
    mode: 0644
  with_items:
    - { job: bender, arguments: "-m 64", instances: 3 }
    - { job: mailer, arguments: "-m 1024", instances: 2 }
  notify: Ensure Supervisor is restarted

job.conf.j2:

[program:{{ item.job }}]
user=vagrant
command=/usr/share/nginx/vhosts/parclick.com/app/console rabbitmq:consumer {{ item.arguments }} {{ item.job }} -e prod
process_name=%(program_name)s_%(process_num)02d
numprocs={{ item.instances }}
autostart=true
autorestart=true
stderr_logfile=/var/log/supervisor/{{ item.job }}.stderr.log
stdout_logfile=/var/log/supervisor/{{ item.job }}.stdout.log

Salida:

TASK [Supervisor : Setup Supervisor jobs files] ********************************
changed: [loc.parclick.com] => (item={u'instances': 3, u'job': u'bender', u'arguments': u'-m 64'})
changed: [loc.parclick.com] => (item={u'instances': 2, u'job': u'mailer', u'arguments': u'-m 1024'})

¡Disfrutar!

Tecnocat
fuente
Esto debe marcarse como respuesta correcta. Dado que es compatible ahora
PoX
23

Esta es una solución / truco que estoy usando:

tasks / main.yml:

- name: parametrized template - a
  template:
    src: test.j2
    dest: /tmp/templateA
  with_items: var_a

- name: parametrized template - b
  template:
    src: test.j2
    dest: /tmp/templateB
  with_items: var_b

vars / main.yml

var_a:
  - 'this is var_a'
var_b:
  - 'this is var_b'

templates / test.j2:

{{ item }}

Después de ejecutar esto, obtiene this is var_aen / tmp / templateA y this is var_ben / tmp / templateB.

Básicamente, abusa with_itemsde representar la plantilla con cada elemento de la lista de un elemento. Esto funciona porque puede controlar cuál es la lista al usar with_items.

La desventaja de esto es que debe usarlo itemcomo nombre de variable en su plantilla.

Si desea pasar más de una variable de esta manera, puede dictar los elementos de su lista de esta manera:

var_a:
  -
    var_1: 'this is var_a1'
    var_2: 'this is var_a2'
var_b:
  -
    var_1: 'this is var_b1'
    var_2: 'this is var_b2'

y luego refiérase a ellos en su plantilla de esta manera:

{{ item.var_1 }}
{{ item.var_2 }}
asmigala
fuente
1
Solución limpia, pero sombrero para usarwith_items: '{{ var_a }}'
Peter Ajtai
8

Lo hice de esta manera.

En tasks / main.yml

- name: template test
  template: 
        src=myTemplateFile.j2
        dest={{item}}
   with_dict: some_dict

y en vars / main.yml

some_dict:
  /path/to/dest1:
    var1: 1
    var2: 2
  /path/to/dest2:
    var1: 3
    var2: 4

y en templates / myTemplateFile.j2

some_var = {{ item.value.var1 }}
some_other_var = {{ item.value.var2 }}

Espero que esto resuelva tu problema.

Nabarun Chatterjee
fuente
with_dictes la mejor solución.
zx1986
1
- name: copy vhosts
  template: src=site-vhost.conf dest=/etc/apache2/sites-enabled/{{ item }}.conf
  with_items:
    - somehost.local
    - otherhost.local
  notify: restart apache

IMPORTANTE: Tenga en cuenta que un elemento no tiene que ser solo una cadena, puede ser un objeto con tantas propiedades como desee, por lo que puede pasar cualquier cantidad de variables.

En la plantilla tengo:

<VirtualHost *:80>
    ServerAdmin [email protected]
    ServerName {{ item }}
    DocumentRoot /vagrant/public


    ErrorLog ${APACHE_LOG_DIR}/error-{{ item }}.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

</VirtualHost>
Bart McLeod
fuente
1
¿Cómo podría convertirlo en un objeto?
camdixon
1

Tuve un problema similar que resolver, aquí hay una solución simple de cómo pasar variables a archivos de plantilla, el truco es escribir el archivo de plantilla aprovechando la variable. Necesita crear un diccionario (la lista también es posible), que contenga el conjunto de variables correspondientes a cada uno de los archivos. Luego, dentro del archivo de plantilla, acceda a ellos.

vea abajo:

the template file: test_file.j2
# {{ ansible_managed }} created by [email protected]

{% set dkey  = (item | splitext)[0]  %}
{% set fname = test_vars[dkey].name  %}
{% set fip   = test_vars[dkey].ip    %}
{% set fport = test_vars[dkey].port  %}
filename: {{ fname }}
ip address: {{ fip }}
port: {{ fport }}

el libro de jugadas

---
#
# file: template_test.yml
# author: [email protected]
#
# description: playbook to demonstrate passing variables to template files
#
# this playbook will create 3 files from a single template, with different
# variables passed for each of the invocation
#
# usage:
# ansible-playbook -i "localhost," template_test.yml

- name: template variables testing
  hosts: all
  gather_facts: false

  vars:
    ansible_connection: local
    dest_dir: "/tmp/ansible_template_test/"
    test_files:
      - file_01.txt
      - file_02.txt
      - file_03.txt
    test_vars:
      file_01:
        name: file_01.txt
        ip: 10.0.0.1
        port: 8001
      file_02:
        name: file_02.txt
        ip: 10.0.0.2
        port: 8002
      file_03:
        name: file_03.txt
        ip: 10.0.0.3
        port: 8003

  tasks:
    - name: copy the files
      template:
        src: test_file.j2
        dest: "{{ dest_dir }}/{{ item }}"
      with_items:
        - "{{ test_files }}"
xbalaji
fuente
0

Otro ejemplo del mundo real usando una lista

un extracto de una plantilla para php.ini

{% if 'cli/php.ini' in item.d %}
max_execution_time = 0
memory_limit = 1024M
{% else %}
max_execution_time = 300
memory_limit = 512M
{% endif %}

Esta es la var

php_templates:
  - { s: 'php.ini.j2', d: "/etc/php/{{php_version}}/apache2/php.ini" }
  - { s: 'php.ini.j2', d: "/etc/php/{{php_version}}/cli/php.ini" }

Entonces me despliego con esto

- name: push templated files
  template:
    src: "{{item.s}}"
    dest: "{{item.d}}"
    mode: "{{item.m | default(0644) }}"
    owner: "{{item.o | default('root') }}"
    group: "{{item.g | default('root') }}"
    backup: yes
  with_items: "{{php_templates}}"
krad
fuente