如何使用模板模块与不同的变量集?

我的用例如下:

我有一个模板文件,我想从该模板创建2个不同的文件,每个文件的变量由不同的变量集填充。

例如,假设我想对包含以下行的文件进行模板化:

mkdir -p {{myTemplateVariable}}

我想找到一个合适的方法来让这个变量被“ File1”和“ File2”填充,比如:

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




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

其中,我可以为第一个模板指定要使用的变量是 a = “ File1”,为第二个模板指定 b = “ File2”。

142655 次浏览

For 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

For Ansible 1.x:

Unfortunately the template module does not support passing variables to it, which can be used inside the template. There was a feature request but it was rejected.

I can think of two workarounds:

1. Include

The include statement supports passing variables. So you could have your template task inside an extra file and include it twice with appropriate parameters:

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. Re-define myTemplateVariable

Another way would be to simply re-define myTemplateVariable right before every template task.

- 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

This is a solution/hack I'm using:

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

After running this, you get this is var_a in /tmp/templateA and this is var_b in /tmp/templateB.

Basically you abuse with_items to render the template with each item in the one-item list. This works because you can control what the list is when using with_items.

The downside of this is that you have to use item as the variable name in you template.

If you want to pass more than one variable this way, you can dicts as your list items like this:

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'

and then refer to them in your template like this:

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

I did it in this way.

In tasks/main.yml

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

and in vars/main.yml

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

and in templates/myTemplateFile.j2

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

Hope this solves your problem.

- name: copy vhosts
template: src=site-vhost.conf dest=/etc/apache2/sites-enabled/\{\{ item }}.conf
with_items:
- somehost.local
- otherhost.local
notify: restart apache

IMPORTANT: Note that an item does not have to be just a string, it can be an object with as many properties as you like, so that way you can pass any number of variables.

In the template I have:

<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>

With Ansible 2.x you can use vars: with tasks.

Template 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

This will pass different myTemplateVariable values into test.j2.

You can do this very easy, look my Supervisor recipe:

- 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

Output:

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

Enjoy!

I had a similar problem to solve, here is a simple solution of how to pass variables to template files, the trick is to write the template file taking advantage of the variable. You need to create a dictionary (list is also possible), which holds the set of variables corresponding to each of the file. Then within the template file access them.

see below:

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

the 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 }}"

Another real world example using a list

an extract for a template for 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 %}

This is the 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" }

Then i deploy with this

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