У меня есть словарь пакетов с именем пакета, являющимся ключом , и словарем некоторых деталей, являющимся значением значения :

{
        "php7.1-readline": {
            "latest": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1", 
            "origins": [
                "ppa.launchpad.net"
            ], 
            "version": "7.1.6-2~ubuntu14.04.1+deb.sury.org+1", 
            "www": "http://www.php.net/"
        }, 
        "php7.1-xml": {
            "latest": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1", 
            "origins": [
                "ppa.launchpad.net"
            ], 
            "version": "7.1.6-2~ubuntu14.04.1+deb.sury.org+1", 
            "www": "http://www.php.net/"
        }, 
        "plymouth": {
            "version": "0.8.8-0ubuntu17.1"
        },
    ....
}

Я хотел бы свести приведенное выше к словарю, содержащему только те пакеты, которые имеют в своих значениях атрибут latest -.

Казалось бы, json_query - это фильтр для использования, но я не могу понять синтаксис. Кажется, что все примеры работают с списками словарей, а не с словарями того же ...

Например, если я «перенесу» вышеприведенный словарь в json_query('*.latest'), я получу список актуальных последних версий:

[
  "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
  "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
  "7.1.6-2~ubuntu14.04.1+deb.sury.org+1"
]

Как я могу получить весь словарь-элементы вместо этого?

Есть надежда?

7
Mikhail T. 19 Сен 2017 в 20:20

3 ответа

Лучший ответ

С dict2items фильтром добавлен в декабре 2017 года , это возможно, используя родной функционал:

- debug:
    msg: "{{ dict(pkg | dict2items | json_query('[?value.latest].[key, value.latest]')) }}"

Результат:

"msg": {
    "php7.1-readline": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
    "php7.1-xml": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1"
}
3
techraf 8 Сен 2018 в 08:31

Вы не можете выполнить этот перевод (я думаю ) исключительно с фильтрами Jinja, но вы можете добиться этого, применив небольшую логику Ansible. В следующем playbook используется цикл with_dict для циклического перемещения по элементам в вашем словаре и создания нового словаря из соответствующих:

- hosts: localhost                                                              
  vars:                                                                         
    packages: {                                                                 
        "php7.1-readline": {                                                    
          "latest": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",                     
          "origins": [                                                          
            "ppa.launchpad.net"                                                 
          ],                                                                    
          "version": "7.1.6-2~ubuntu14.04.1+deb.sury.org+1",                    
          "www": "http://www.php.net/"                                          
        },                                                                      
        "php7.1-xml": {                                                         
          "latest": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",                     
          "origins": [                                                          
            "ppa.launchpad.net"                                                 
          ],                                                                    
          "version": "7.1.6-2~ubuntu14.04.1+deb.sury.org+1",                    
          "www": "http://www.php.net/"                                          
        },                                                                      
        "plymouth": {                                                           
          "version": "0.8.8-0ubuntu17.1"                                        
        }                                                                       
      }                                                                         

  tasks:                                                                        
    - set_fact:                                                                 
        new_packages: >                                                         
          {{ new_packages|default({})|                                          
                combine({item.key: item.value}) }}                              
      with_dict: "{{ packages }}"                                               
      when: "{{ item.value.latest is defined }}"                                

    - debug:                                                                    
        var: new_packages                                                       
3
larsks 19 Сен 2017 в 19:18

Вы правильно связали этот вопрос с https://stackoverflow.com/a/41584889/2795592.

Нет никаких опций для манипулирования ключами и значениями одновременно с json_query из коробки (по состоянию на Ansible 2.4.0).

Вот исправленный json_query.py, который поддерживает jq-like to_entries / {{X1} } функции. Вы можете поместить его в ./filter_plugins рядом с вашей пьесой и выполнить этот запрос:

- debug:
    msg: "{{ pkg | json_query('to_entries(@) | [?value.latest].{key:key, value:value.latest} | from_entries(@)')}}"

Чтобы получить этот результат:

"msg": {
    "php7.1-readline": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1",
    "php7.1-xml": "7.1.9-1+ubuntu14.04.1+deb.sury.org+1"
}

Я сделаю пиар ответчиком, как только у меня будет свободное время.

1
Konstantin Suvorov 21 Сен 2017 в 08:20