Ansible - Sử dụng mặc định nếu một biến không được xác định


98

Tôi đang tùy chỉnh usersviệc tạo linux bên trong vai trò của mình. Tôi cần phải cho phép người dùng tùy chỉnh về vai trò của tôi home_directory, group_name, name, password.

Tôi đã tự hỏi liệu có cách nào linh hoạt hơn để đối phó với các giá trị mặc định hay không.

Tôi biết rằng mã dưới đây là có thể:

- name: Create default
  user:
    name: "default_name"
  when: my_variable is not defined

 - name: Create custom
  user:
    name: "{{my_variable}}"
  when: my_variable is defined

Nhưng như tôi đã đề cập, có rất nhiều biến tùy chọn và điều này tạo ra rất nhiều khả năng.

Có một cái gì đó giống như mã ở trên?

user:
  name: "default_name", "{{my_variable}}"

Mã sẽ được đặt name="default_name"khi my_variablekhông được xác định.

Tôi có thể bật tất cả các biến defaults/main.ymlvà tạo người dùng như vậy:

- name: Create user
  user:
    name: "{{my_variable}}"

Nhưng những biến đó nằm bên trong một hàm băm thực sự lớn và có một số hàm băm bên trong hàm băm đó không thể là mặc định.


Câu trả lời:


190

Bạn có thể sử dụng Jinja's default:

- name: Create user
  user:
    name: "{{ my_variable | default('default_value') }}"

10
Và nếu biến mặc định phụ thuộc vào một biến khác. Ví dụ default('/home/' {{ anothervar }}), có cách nào để nối các giá trị đó không?
Bernardo Vale,

8
Chỉ cần loại bỏ các 'xung quanh default_valuevà nó sẽ sử dụng một biến gọi là DEFAULT_VALUE
dagonza

7
Không hoạt động nếu biến được lồng vào nhau như {{ dict.key | default(5) }}. Nó sẽ không thành công nếu không dictđược xác định.
Jordan Stewart

1
FYI, điều này bây giờ sẽ tạo ra một lỗi:[WARNING]: when statements should not include jinja2 templating delimiters such as {{ }} or {% %}.
bryan kennedy.

1
@JordanStewart Tôi cũng gặp trường hợp tương tự - với các biến lồng nhau. Tôi đã đăng một câu trả lời với các giải pháp khả thi bên dưới.
Roman Kruglov

11

Không hoàn toàn liên quan, nhưng bạn cũng có thể kiểm tra cả biến undefinedAND empty(ví dụ my_variable:). (LƯU Ý: chỉ hoạt động với phiên bản ansible> 1.9, xem: liên kết )

- name: Create user
  user:
    name: "{{ ((my_variable == None) | ternary('default_value', my_variable)) \
    if my_variable is defined else 'default_value' }}"

2
Điều này là tuyệt vời, rất hữu ích.
Eagle33322,

5

Nếu ai đó đang tìm kiếm một tùy chọn xử lý các biến lồng nhau, có một số tùy chọn như vậy trong vấn đề github này .

Tóm lại, bạn cần sử dụng bộ lọc "mặc định" cho mọi cấp độ của các vars lồng nhau. Đối với biến "a.nested.var", nó sẽ giống như sau:

- hosts: 'localhost'
  tasks:
    - debug:
        msg: "{{ ((a | default({})).nested | default({}) ).var | default('bar') }}"

hoặc bạn có thể đặt giá trị mặc định của các ô trống cho từng cấp độ khác nhau, có thể sử dụng bộ lọc "kết hợp". Hoặc sử dụng bộ lọc "json_query". Nhưng tùy chọn tôi đã chọn có vẻ đơn giản hơn đối với tôi nếu bạn chỉ có một cấp độ lồng.


4

Nếu bạn có một lần chơi mà bạn muốn lặp lại các mục, hãy xác định danh sách đó trong group_vars / all hoặc một nơi nào khác có ý nghĩa:

all_items:
  - first
  - second
  - third
  - fourth

Sau đó, nhiệm vụ của bạn có thể trông như thế này:

  - name: List items or default list
    debug:
      var: item
    with_items: "{{ varlist | default(all_items) }}"

Chuyển vào varlist dưới dạng một mảng JSON:

ansible-playbook <playbook_name> --extra-vars='{"varlist": [first,third]}'

Trước đó, bạn cũng có thể muốn một nhiệm vụ kiểm tra xem mỗi mục trong varlist cũng nằm trong all_items :

  - name: Ensure passed variables are in all_items
    fail:
      msg: "{{ item }} not  in all_items list"
    when: item not in all_items
    with_items: "{{ varlist | default(all_items) }}"

3

Trong trường hợp bạn sử dụng tra cứu để đặt mặc định đọc từ môi trường, bạn cũng đã đặt tham số thứ hai của mặc định thành true:

- set_facts:
    ansible_ssh_user: "{{ lookup('env', 'SSH_USER') | default('foo', true) }}"

Bạn cũng có thể nối nhiều định nghĩa mặc định:

- set_facts:
    ansible_ssh_user: "{{ some_var.split('-')[1] | default(lookup('env','USER'), true) | default('foo') }}"

1

Câu hỏi khá cũ, nhưng còn:

- hosts: 'localhost'
  tasks:
    - debug:
        msg: "{{ ( a | default({})).get('nested', {}).get('var','bar') }}"

Nó trông bớt cồng kềnh hơn với tôi ...


1

Nếu bạn đang gán giá trị mặc định cho thực tế boolean thì hãy đảm bảo rằng không có dấu ngoặc kép nào được sử dụng bên trong default ().

- name: create bool default
  set_fact:
    name: "{{ my_bool | default(true) }}"

Đối với các biến khác được sử dụng cùng một phương pháp được đưa ra trong câu trả lời đã xác minh.

- name: Create user
  user:
    name: "{{ my_variable | default('default_value') }}"
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.