2017-09-19 3 views
0

J'ai un dictionnaire de paquets avec nom_paquet étant la clé et un dictionnaire de certains détails étant la valeur :Comment filtrer les dictionnaires dans Jinja?

{ 
     "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" 
     }, 
    .... 
} 

Je voudrais réduire ci-dessus à un dictionnaire avec seulement la packages, qui ont l'attribut latest dans leurs valeurs.

Il semblerait que json_query est le filtre à utiliser, mais je ne peux pas comprendre la syntaxe. Les exemples là-bas tous semblent fonctionner sur listes des dictionnaires, des dictionnaires non de même ...

Par exemple, si je « pipe » le dictionnaire ci-dessus dans json_query('*.latest'), je reçois la liste du dernières versions réelles:

[ 
    "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" 
] 

Comment puis-je obtenir l'ensemble des éléments du dictionnaire à la place?

Un espoir?

Répondre

1

Vous avez raison de lier cette question à https://stackoverflow.com/a/41584889/2795592.

Aucune option ne permet de manipuler les clés et les valeurs simultanément avec json_query (à partir de Ansible 2.4.0).

Voici les correctifs json_query.py qui prennent en charge les fonctions to_entries/from_entries de type jq. Vous pouvez le mettre en ./filter_plugins près de votre PlayBook et de faire cette requête:

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

pour obtenir ce résultat:

"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" 
} 

Je vais faire de PR Ansible dès que j'ai un peu de temps libre.

+0

Merci, mais c'est un peu triste ... J'ai délibérément choisi la structure du dictionnaire pour les paquets de façon à pouvoir rechercher les détails d'un paquet par son nom rapidement ('O (ln (n))'). Le convertir en une liste rend tout linéaire ... Tant que nous corrigeons les choses de toute façon, ne pouvons-nous pas imaginer quelque chose de plus proche de 'with_dict' d'Ansible - où vous pouvez opérer sur chaque' item' et 'value de chaque élément 'directement? –

+0

Vous êtes libre de modifier mon exemple de gist. Ou écrivez votre plugin personnalisé pour traiter votre jeu de données spécifique très rapidement. Ou demander à un gourou Ansible de le faire :-D –

+0

Je sais, je peux écrire un filtre personnalisé. Avoir, en fait.Mais j'espérais, cela pourrait se faire sans un - avec une combinaison intelligente de 'extract',' map', 'selectattr', et/ou' json_query' ... Oh, eh bien, merci encore pour votre aide - - un résultat négatif est toujours un résultat, n'est-ce pas ... –

1

Vous ne pouvez pas effectuer cette traduction (I pensez) exclusivement avec des filtres Jinja, mais vous pouvez y arriver en appliquant une petite logique Ansible. Le PlayBook suivant utilise une boucle with_dict en boucle sur les éléments dans votre dictionnaire, et de construire un nouveau dictionnaire de ceux correspondant à:

- 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              
+0

Merci, j'ai effectivement essayé quelque chose comme ça. Cependant, la clause 'when'-list _each_ package saute - des centaines de lignes de sortie parce que, bien sûr, j'ai besoin de traiter les paquets _all_ installés sur chaque système, en filtrant ceux pour lesquels des mises à jour sont disponibles ... –

+0

tout ce qui vous intéresse est la variable résultante, 'new_packages'. Le nombre de lignes de sortie n'a pas d'importance. C'est juste informatif. – larsks