Come utilizzare il modulo modello con diversi set di variabili?


92

Il mio caso d'uso è il seguente:

Ho un file modello e vorrei creare 2 file diversi da quel modello, con le variabili riempite da un diverso insieme di variabili per ogni file.

Ad esempio, diciamo che voglio modellare il file contenente la riga:

mkdir -p {{myTemplateVariable}}

Vorrei trovare un modo corretto per riempire questa variabile con "File1" e "File2". Qualcosa di simile a :

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


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

dove potrei specificare per il primo template che la variabile da usare è a = "File1" e per il secondo, b = "File2".


È esattamente quello che faccio con tutte le mie ricette, guarda questo commento stackoverflow.com/a/40189525/1571310 , spero che questo aiuto!
Tecnocat

Risposte:


51

Per 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

Per Ansible 1.x:

Sfortunatamente il templatemodulo non supporta il passaggio di variabili ad esso, che possono essere utilizzate all'interno del modello. È stata richiesta una funzione ma è stata rifiutata.

Posso pensare a due soluzioni alternative:

1. Includi

L' includeistruzione supporta il passaggio di variabili. Quindi potresti avere la tua templateattività all'interno di un file extra e includerla due volte con parametri appropriati:

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. Ridefinire myTemplateVariable

Un altro modo sarebbe semplicemente ridefinire myTemplateVariable subito prima di ogni templateattività.

- 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

Grazie per la risposta. Tuttavia, è davvero impossibile fare a meno di soluzioni alternative? Attualmente sto tryng qualcosa di simile: stackoverflow.com/questions/26020465/... , ma continua ad avere alcuni errori (forse non direttamente correlati).
Kestemont Max

Sì, puoi farlo anche con un ciclo, ma è comunque una soluzione alternativa. :)
udondan

14
non più richiesto. "vars" è ora supportato. vedi la risposta @ konstantin-suvorov di seguito.
sonjz

123

Con Ansible 2.x puoi usare vars:con le attività.

Modello test.j2:

mkdir -p {{myTemplateVariable}}

Playbook:

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

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

Questo passerà myTemplateVariablevalori diversi a test.j2.


9
inizialmente ho commesso un errore e avevo vars: rientrato come il resto degli argomenti del modello (come src :). Immagino che il livello di rientro significhi vars: è dell'attività, non del modello. Quindi puoi farlo ovunque, non solo nei modelli. simpatico.
Greg

37

Puoi farlo molto facilmente, guarda la mia ricetta del supervisore:

- 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

Produzione:

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'})

Godere!


Questo dovrebbe essere contrassegnato come risposta corretta. Dal momento che è supportato ora
PoX

23

Questa è una soluzione / hack che sto usando:

task / 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 }}

Dopo aver eseguito questo, si entra this is var_ain / tmp / templateA e this is var_bin / tmp / templateB.

Fondamentalmente si abusa with_itemsdi rendere il modello con ogni elemento nell'elenco di un elemento. Funziona perché puoi controllare qual è l'elenco quando usi with_items.

Lo svantaggio di questo è che devi usare itemcome nome della variabile nel tuo modello.

Se vuoi passare più di una variabile in questo modo, puoi dettare gli elementi dell'elenco in questo modo:

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'

e poi fai riferimento a loro nel tuo modello in questo modo:

{{ item.var_1 }}
{{ item.var_2 }}

1
Soluzione pulita, ma cappello da usarewith_items: '{{ var_a }}'
Peter Ajtai

8

L'ho fatto in questo modo.

In tasks / main.yml

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

e in vars / main.yml

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

e in templates / myTemplateFile.j2

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

Spero che questo risolva il tuo problema.


with_dictè la soluzione migliore.
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: nota che un elemento non deve essere solo una stringa, può essere un oggetto con tutte le proprietà che desideri, in questo modo puoi passare un numero qualsiasi di variabili.

Nel modello ho:

<VirtualHost *:80>
    ServerAdmin me@example.org
    ServerName {{ item }}
    DocumentRoot /vagrant/public


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

</VirtualHost>

1
Come potrei renderlo un oggetto?
camdixon

1

Ho avuto un problema simile da risolvere, ecco una semplice soluzione su come passare variabili ai file modello, il trucco è scrivere il file modello sfruttando la variabile. È necessario creare un dizionario (è possibile anche l'elenco), che contiene l'insieme di variabili corrispondenti a ciascuno dei file. Quindi all'interno del file modello accedi ad essi.

vedi sotto:

the template file: test_file.j2
# {{ ansible_managed }} created by xbalaji@gmail.com

{% 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 }}

il playbook

---
#
# file: template_test.yml
# author: xbalaji@gmail.com
#
# 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 }}"

0

Un altro esempio del mondo reale che utilizza un elenco

un estratto per un modello per 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 %}

Questa è 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" }

Quindi mi schiero con questo

- 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}}"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.