Làm thế nào để sử dụng mô-đun mẫu với các tập biến khác nhau?


92

Trường hợp sử dụng của tôi như sau:

Tôi có một tệp mẫu và tôi muốn tạo 2 tệp khác nhau từ mẫu đó, với các biến được điền bởi một nhóm biến khác nhau cho mỗi tệp.

Ví dụ: giả sử tôi muốn tạo mẫu tệp có chứa dòng:

mkdir -p {{myTemplateVariable}}

Tôi muốn tìm một cách thích hợp để biến này được điền bởi "File1" và "File2". Cái gì đó như :

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


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

trong đó tôi có thể chỉ định cho lần tạo mẫu đầu tiên mà biến sẽ sử dụng là a = "File1" và cho lần thứ hai, b = "File2".


Đó có phải là chính xác mà tôi làm với tất cả các công thức nấu ăn của mình không, hãy xem nhận xét này stackoverflow.com/a/40189525/1571310 , hy vọng điều này sẽ giúp ích!
Tecnocat

Câu trả lời:


51

Đối với 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

Đối với Ansible 1.x:

Thật không may, templatemô-đun không hỗ trợ chuyển các biến cho nó, có thể được sử dụng bên trong mẫu. Có một yêu cầu tính năng nhưng nó đã bị từ chối.

Tôi có thể nghĩ ra hai cách giải quyết:

1. Bao gồm

Câu includelệnh hỗ trợ truyền các biến. Vì vậy, bạn có thể có templatenhiệm vụ của mình bên trong một tệp bổ sung và bao gồm nó hai lần với các tham số thích hợp:

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. Xác định lại myTemplateVariable

Một cách khác là chỉ cần xác định lại myTemplateVariable ngay trước mỗi templatetác vụ.

- 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

Cảm ơn bạn đã trả lời. Tuy nhiên, nó có thực sự không thể làm được nếu không có cách giải quyết? Tôi hiện đang thử một cái gì đó như: stackoverflow.com/questions/26020465/… , nhưng vẫn gặp một số lỗi (có thể không liên quan trực tiếp).
Kestemont Max,

Có, bạn cũng có thể làm điều đó với một vòng lặp - vẫn là một cách giải quyết. :)
udondan

14
không cần thiết nữa. "vars" hiện đã được hỗ trợ. xem câu trả lời của @ konstantin-suvorov bên dưới.
sonjz

123

Với Ansible 2.x, bạn có thể sử dụng vars:với các tác vụ.

Bản mẫu test.j2:

mkdir -p {{myTemplateVariable}}

Sách vở:

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

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

Điều này sẽ chuyển các myTemplateVariablegiá trị khác nhau vào test.j2.


9
ban đầu tôi đã mắc lỗi và có vars: thụt vào giống như phần còn lại của các đối số mẫu (như src :). Tôi đoán mức thụt lề có nghĩa là các vars: là của nhiệm vụ, không phải của mẫu. Vì vậy, bạn có thể làm điều này ở bất cứ đâu, không chỉ các mẫu. đẹp.
Greg

37

Bạn có thể làm điều này rất dễ dàng, hãy xem công thức Người giám sát của tôi:

- 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

Đầu ra:

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

Thưởng thức!


Đây phải được đánh dấu là câu trả lời đúng. Kể từ khi nó được hỗ trợ bây giờ
PoX

23

Đây là một giải pháp / hack mà tôi đang sử dụng:

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'

Template / test.j2:

{{ item }}

Sau khi chạy cái này, bạn this is var_avào / tmp / templateA vàthis is var_b trong / tmp / templateB.

Về cơ bản, bạn lạm dụng with_itemsđể hiển thị mẫu với mỗi mục trong danh sách một mục. Điều này hoạt động vì bạn có thể kiểm soát danh sách là gì khi sử dụng with_items.

Nhược điểm của điều này là bạn phải sử dụng itemlàm tên biến trong mẫu của bạn.

Nếu bạn muốn chuyển nhiều hơn một biến theo cách này, bạn có thể coi các mục danh sách của mình như sau:

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'

và sau đó tham khảo chúng trong mẫu của bạn như sau:

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

1
Giải pháp làm sạch, nhưng mũ để sử dụngwith_items: '{{ var_a }}'
Peter Ajtai

8

Tôi đã làm theo cách này.

Trong task / main.yml

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

và trong vars / main.yml

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

và trong các mẫu / myTemplateFile.j2

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

Hy vọng điều này sẽ giải quyết vấn đề của bạn.


with_dictlà giải pháp tốt hơ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

QUAN TRỌNG: Lưu ý rằng một mục không nhất thiết phải chỉ là một chuỗi, nó có thể là một đối tượng có bao nhiêu thuộc tính tùy thích, do đó bạn có thể chuyển bất kỳ số biến nào.

Trong mẫu tôi có:

<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
Làm thế nào tôi có thể biến nó thành một đối tượng?
camdixon

1

Tôi đã gặp một vấn đề tương tự cần giải quyết, đây là một giải pháp đơn giản về cách chuyển các biến vào tệp mẫu, mẹo là viết tệp mẫu tận dụng lợi thế của biến. Bạn cần tạo một từ điển (cũng có thể có danh sách), từ điển này chứa tập hợp các biến tương ứng với mỗi tệp. Sau đó, trong tệp mẫu truy cập chúng.

xem bên dưới:

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

sách vở

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

Một ví dụ thực tế khác sử dụng danh sách

một trích xuất cho một mẫu cho 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 %}

Đây là 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" }

Sau đó, tôi triển khai với cái này

- 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}}"
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.