Ansible: lọc danh sách theo các thuộc tính của nó


83

Tôi có biến có tên "mạng" được đăng ký trong Ansible:

{
    "addresses": {
        "private_ext": [
            {
                "type": "fixed",
                "addr": "172.16.2.100"
            }
        ],
        "private_man": [
            {
                "type": "fixed",
                "addr": "172.16.1.100"
            },
            {
                "type": "floating",
                "addr": "10.90.80.10"
            }
        ]
    }
}

Có thể lấy địa chỉ IP ("addr") với type = "float" làm như thế này không?

- debug: var={{ network.addresses.private_man | filter type="fixed" | get "addr" }}

Tôi biết cú pháp là sai nhưng bạn hiểu được.

Câu trả lời:


41

Tôi đã gửi một yêu cầu kéo (có sẵn trong Ansible 2.2 +) mà sẽ làm cho loại này tình huống dễ dàng hơn bằng cách thêm jmespath hỗ trợ truy vấn trên Ansible. Trong trường hợp của bạn, nó sẽ hoạt động như sau:

- debug: msg="{{ addresses | json_query(\"private_man[?type=='fixed'].addr\") }}"

sẽ trở lại:

ok: [localhost] => {
    "msg": [
        "172.16.1.100"
    ]
}

3
Bạn cần cài đặt "jmespath" trước khi chạy bộ lọc json_query.
thúc

Và tôi vừa từ bỏ việc cố gắng cài đặt jmespath do sự khác biệt về phiên bản Python. Nó không phải là giải pháp một tầm thường như trên Ansible 2.4+
Stuart Watt

1
@StuartWatt bạn có thể cần pyenv để tự tóm tắt khỏi phiên bản python của hệ điều hành. Bạn có thể thử pyenv, pyenv virtualenv, hoặc một số người thích pipenv hơn. Chúng sẽ hoạt động như nhau.
Jepper

@Jepper Nếu bạn cần một Python hoàn toàn mới để sử dụng Ansible, đó là một trận thua. (Và tôi đang sử dụng pyenv và vẫn gặp những sự cố này :-)
Stuart Watt

127

Để lọc danh sách các phái, bạn có thể sử dụng bộ lọc selectattr cùng với kiểm tra bằng :

network.addresses.private_man | selectattr("type", "equalto", "fixed")

Ở trên yêu cầu Jinja2 v2.8 trở lên (bất kể phiên bản Ansible).


Ansible cũng có các bài kiểm tra matchsearch lấy biểu thức chính quy:

matchsẽ yêu cầu khớp hoàn toàn trong chuỗi, trong khi searchsẽ yêu cầu khớp bên trong chuỗi.

network.addresses.private_man | selectattr("type", "match", "^fixed$")

Để giảm danh sách các phái thành một danh sách các chuỗi, do đó bạn chỉ nhận được danh sách các addrtrường, bạn có thể sử dụng bộ lọc bản đồ :

... | map(attribute='addr') | list

Hoặc nếu bạn muốn một chuỗi được phân tách bằng dấu phẩy:

... | map(attribute='addr') | join(',')

Kết hợp lại, nó sẽ giống như thế này.

- debug: msg={{ network.addresses.private_man | selectattr("type", "equalto", "fixed") | map(attribute='addr') | join(',') }}

1
Nếu bạn muốn họ như một danh sách chứ không phải là một chuỗi dấu phẩy tách ra, bạn cũng có thể sử dụng:{{ network.addresses.private_man | selectattr("type", "equalto", "fixed") | map(attribute='addr') | list }}
TrinitronX

1
liên kết bạn cung cấp có thay đổi không? tôi không thể tìm thấy "phù hợp" và "tìm kiếm" trên trang đó
kích hoạt

1
@activedecay Có vẻ như nó đã bị xóa khỏi trang đó, phải. Đề cập duy nhất tôi có thể tìm thấy bây giờ là trên trang này: docs.ansible.com/ansible/latest/user_guide/… Tôi đã cập nhật liên kết, cảm ơn!
udondan

19

Không nhất thiết phải tốt hơn, nhưng vì thật tuyệt khi có các tùy chọn, đây là cách thực hiện bằng cách sử dụng câu lệnh Jinja :

- debug:
    msg: "{% for address in network.addresses.private_man %}\
        {% if address.type == 'fixed' %}\
          {{ address.addr }}\
        {% endif %}\
      {% endfor %}"

Hoặc nếu bạn muốn đặt tất cả trên một dòng:

- debug:
    msg: "{% for address in network.addresses.private_man if address.type == 'fixed' %}{{ address.addr }}{% endfor %}"

Trả về:

ok: [localhost] => {
    "msg": "172.16.1.100"
}
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.