Извлечение вложенного значения dict с условиями из JSON с использованием JINJA2 в Ansible - PullRequest
0 голосов
/ 23 мая 2019

Я пытаюсь извлечь имя домена CDN для определенного псевдонима из cloudfront_facts Ansible со следующим (суммарным) выводом:

{
  "cdn_facts": {
   "ansible_facts": {
    "cloudfront": {
      "summary": {
       "distributions": [
        {
          "Aliases": [
           "media.example.com"
          ],
          "DomainName": "a1b2c3d4e5f6g.cloudfront.net"
        },
        {
          "Aliases": [
           "example.com"
          ],
          "DomainName": "g7f6e5d4c3b2a.cloudfront.net"
        }
      ]
     }
    }
  }
}

Другими словами, для псевдонима example.comЯ бы хотел установить факт со значением g7f6e5d4c3b2a.cloudfront.net.

. Я попытался распечатать это значение следующим образом, но он просто создает пустой список.

- debug:
    msg: "{{ cdn_facts.ansible_facts.cloudfront.summary.distributions | selectattr('Aliases[0]', 'equalto', 'example.com') | map(attribute='DomainName') | list }}"

Я в недоумении, как даже отладить это, поскольку cdn_facts.ansible_facts.cloudfront.summary.distributions производит массив диктов, но selectattr и map ничего не производят.

1 Ответ

1 голос
/ 23 мая 2019

Ничто в ваших данных не имеет атрибута с именем Aliases[0], поэтому ваш фильтр selectattr не работает.

Для извлечения данных из глубоко вложенных словарей фильтр json_query часто является лучшим выбором.чем пытаться связать нативные фильтры Jinja.Например, учитывая псевдоним example.com, следующее выражение извлечет соответствующий атрибут DomainName:

cdn_facts.ansible_facts.cloudfront.summary.distributions[?Aliases[0] == `example.com`]|[0].DomainName

Мы можем использовать это в пьесе, подобной этой:

---
- hosts: localhost
  gather_facts: false
  tasks:
    - include_vars:
        file: data.json
        name: data

    - debug:
        msg: >-
          {{ item }} ->
          {{
          (data|json_query('cdn_facts.ansible_facts.cloudfront.summary.distributions[?Aliases[0] == `{}`]|[0].DomainName'.format(item)))
          }}
      loop:
        - media.example.com
        - example.com

Что будет выводить:

TASK [debug] **********************************************************************************************************************************************************************************
ok: [localhost] => (item=media.example.com) => {
    "msg": "media.example.com -> a1b2c3d4e5f6g.cloudfront.net"
}
ok: [localhost] => (item=example.com) => {
    "msg": "example.com -> g7f6e5d4c3b2a.cloudfront.net"
}

Модули json_query используют синтаксис поиска jmespath .Вы можете поэкспериментировать с выражениями jmespath, вставив свои данные в текстовое поле на https://jmespath.org, а затем введя поисковые выражения в поле над ним.Кроме того, вы можете получить инструмент командной строки jpterm .

...