web-dev-qa-db-ja.com

Jinjaで辞書をフィルタリングする方法は?

Package-nameがkeyであるパッケージの辞書と、いくつかの詳細の辞書がvalueであるパッケージがあります。

_{
        "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')に「パイプ」すると、実際の最新バージョンのlistが得られます。

_[
  "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.

dict2itemsフィルター 2017年12月に追加、ネイティブ機能を使用して可能です:

- 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

この変換(I think)をJinjaフィルターだけで実行することはできませんが、Ansibleロジックを少し適用することでそこに到達できます。次のプレイブックでは、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

この質問を https://stackoverflow.com/a/41584889/2795592 にリンクするのは正しいです。

箱から出してjson_queryと同時にキーと値を操作するオプションはありません(Ansible 2.4.0以降)。

これがパッチされた json_query.py jqのようなto_entries/from_entries関数をサポートします。プレイブックの近くの./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"
}

暇があればすぐにPRをansibleにします。

1