Ansible: Xác định có điều kiện các biến trong tệp vars nếu một điều kiện nhất định được đáp ứng


19

Tùy thuộc vào giá trị (Đúng / Sai) của một biến được xác định trong nhóm nhóm, tôi đang cố gắng xác định một số biến trong tệp vars. Giá trị của chúng phụ thuộc vào giá trị của nhóm var.

Tệp var hiện tại của tôi trông như thế này:

{% if my_group_var %}
test:
   var1: value
   var2: value
   ...
   varn: value
{% else %}
test:
   var1: other_value
   var2: other_value
   ...
   varn: other_value
{% endif %}

Đối với mỗi vai trò của tôi, tôi đang sử dụng một biến được xác định trong tệp này.

Playbook thử nghiệm của tôi trông như dưới đây:

- name: blabla
  hosts: blabla
  vars_files:
     - <path>/test_vars.yml
  roles: blabla 

Lỗi tôi nhận được sau khi chạy Playbook là:

{% if my_group_var %}
 ^ here

exception type: <class 'yaml.scanner.ScannerError'>
exception: while scanning for the next token
found character that cannot start any token
  in "<unicode string>"

Tôi đang làm điều gì đó ngu ngốc ở đây hay điều này thậm chí không được hỗ trợ? Tôi đã cố gắng tìm một cách khác để xác định các vars này (tôi có rất nhiều trong số chúng) nhưng tôi đã không quản lý để có được một cái gì đó chức năng ở đây. Bất kỳ đề xuất?


Trường hợp những lọ này cuối cùng được sử dụng? Điều này có thể không cần thiết nếu tất cả những gì bạn sẽ sử dụng chúng là một phần của templatecuộc gọi mô-đun.
84104

Nếu testphụ thuộc vào nhóm, nó nên được đặt vào nhóm.
Konstantin Suvorov

Thật không may, kiểm tra không phụ thuộc vào nhóm. Như đã đề cập trong phần mô tả, kiểm tra phụ thuộc vào giá trị của biến group_var.
pandoJohn

Câu trả lời:


11

Tôi không nghĩ bạn có thể, tôi thường tạo các tệp riêng biệt để chứa các bộ sưu tập biến có điều kiện và sử dụng whenmệnh đề để đưa chúng vào một điều kiện cụ thể:

- include_vars: test_environment_vars.yml
  when: global_platform == "test"

- include_vars: staging_environment_vars.yml
  when: global_platform == "staging"

- include_vars: prod_environment_vars.yml
  when: 
    - global_platform != "test" 
    - global_platform != "staging" 

2
Đây là điều tôi đang cố tránh. Tôi không muốn sử dụng bao gồm các vars hoặc để xác định 2 tệp var bổ sung cho các tác vụ của mình.
pandoJohn

Tôi không hiểu điều đó..khi có thể sử dụng bao gồm các điều kiện với điều kiện, tại sao không thể định nghĩa biến với điều kiện?
GP92

9

Ansible cho phép một trong các hình thức sau để xác định biến có điều kiện:

    test:
      var1: "{% if my_group_var %}value{% else %}other_value{% endif %}"
      var2: "{{'value' if (my_group_var) else 'other_value'}}"

Kết hợp cú pháp trên với tra cứu vars, chúng ta có thể tải các vars phức tạp (danh sách trong trường hợp này):

test_value_when_my_group_var_is_true:
   var1: value
   var2: value

test_value_when_my_group_var_is_false:
   var1: other_value
   var2: other_value

test: "{{ lookup('vars','test_value_when_my_group_var_is_true') if (my_group_var) else lookup('vars','test_value_when_my_group_var_is_false')}}"

Có một cách khác để thực hiện tải cây có điều kiện với tra cứu vars. Cách này thuận tiện khi bạn cần triển khai logic trường hợp (nghĩa là biến điều kiện có nhiều hơn hai giá trị có thể):

test_value_when_my_group_var_is_foo:
   var1: value
   var2: value

test_value_when_my_group_var_is_bar:
   var1: other_value
   var2: other_value

test_value_when_my_group_var_is_baz:
   var1: yet_another_value
   var2: yet_another_value

test: "{{ lookup('vars','test_value_when_my_group_var_is_' + my_group_var) }}"

2

Mặc dù nó sẽ rất tuyệt, tôi sợ rằng cách của bạn là không thể (hoặc tôi không nhận thức đúng cách).

Trước tiên tôi khuyên bạn nên chuẩn bị tệp vars từ mẫu jinja và sau đó bao gồm nó với tệp bao gồm. Xem ví dụ về playbook:

---
- name: -Test-
  hosts: local
  vars:
    my_group_var: False
#    my_group_var: True

  tasks:

  - name: Prepare vars file from template.
    template: src=/tmp/vars.yaml.j2
              dest=/tmp/vars.yaml

  - name: Include vars
    include_vars: "/tmp/vars.yaml"

Nội dung của ví dụ mẫu jinja /tmp/vars.yaml.j2 là:

{% if my_group_var %}                                                                                                                                                                                             
test:                                                                                                                                                                                                             
   var1: value                                                                                                                                                                                                    
   var2: value                                                                                                                                                                                                    
{% else %}                                                                                                                                                                                                        
test:                                                                                                                                                                                                             
   var1: other_value                                                                                                                                                                                              
   var2: other_value                                                                                                                                                                                              
{% endif %}

Tôi thích điều này nhưng vấn đề là sau khi tạo tệp .yml từ mẫu jinja, điều này không có sẵn cho các tác vụ tiếp theo từ playbook của tôi.
pandoJohn

Tại sao? Khi tôi cố gắng mở rộng playbook thử nghiệm với nhiệm vụ gỡ lỗi - debug: var=testtôi có thể thấy, rằng có cả hai test.var1test.var2với các giá trị dự kiến. Vì vậy, bạn sẽ có thể sử dụng các biến này trong các nhiệm vụ khác của playbook.
Jaroslav Kucera

0

AFAIK, điều {} này bạn đang thử là dành cho các mẫu Jinja2 chứ không phải cho các tệp yml. Từ tài liệu :

ansible cho phép các vòng lặp Jinja2 và các điều kiện trong các mẫu, nhưng trong các vở kịch, chúng tôi không sử dụng chúng.

Bạn có thể chuẩn bị một tệp .yml riêng biệt với một lần phát để thiết lập các biến bạn cần sử dụng khi mệnh đề, sau đó nhập (hoặc bao gồm) chúng trong sổ chơi chính của bạn. Bằng cách đó, bạn có thể có tất cả các vars được xác định có điều kiện trong một tệp duy nhất.

HOẶC: Sử dụng vai trò. Tôi nghĩ vai trò là cách tiếp cận đầy đủ nhất để giải quyết vấn đề của bạn.


0

Cuối cùng, những gì tôi đã làm là tạo 2 tệp var riêng biệt - hãy gọi chúng type_a.ymltype_b.yml- và tôi đã xác định một biến nhóm cho biết tệp nào sẽ sử dụng - đại loại như thế type_of_file: a. Đây là cách chơi của tôi bây giờ:

- name: blabla
  hosts: blabla
  vars_files:
     - <path>/type_{{ type_of_file }}.yml
  roles: blabla

Cảm ơn tất cả các câu trả lời. Tôi thấy chúng thực sự hữu ích.


0

Tôi hy vọng đoạn snip sau (lấy từ Tài liệu Ansible ) có thể bổ sung đáng giá cho những đóng góp hữu ích từ những người khác ở trên.

- name: Show value of 'variablename'
  debug: msg="{{ lookup('vars', 'variabl' + myvar)}}"
  vars:
    variablename: hello
    myvar: ename
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.