Ansible:属性でリストをフィルタリングする


83

Ansibleに「network」という名前の変数を登録しています。

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

type = "floating"でこのようなことをしてIPアドレス( "addr")を取得することは可能ですか?

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

構文が間違っていることは知っていますが、あなたはその考えを理解しています。

回答:


41

Ansibleにjmespathクエリのサポートを追加することで、この種の状況を簡単にするプルリクエスト(Ansible 2.2以降で利用可能)を送信しました。あなたの場合、それは次のように機能します:

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

戻ります:

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

3
json_queryフィルターを実行する前に、「jmespath」をインストールする必要があります。
2017年

そして、Pythonのバージョンの違いにより、jmespathのインストールをあきらめました。それはAnsible 2.4+上に見えるように、それは些細なA液としてはありません
スチュアートワット

1
@StuartWattオペレーティングシステムのPythonバージョンから自分自身を抽象化するためにpyenvが必要になる場合があります。pyenv、pyenv virtualenvsを試すことができます。または、pipenvを好む人もいます。それらはすべて同じように機能します。
Jepper

@Jepper Ansibleを使用するためにまったく新しいPythonが必要な場合、それは敗戦です。(そして、私はpyenvを使用していたし、今でもこれらの問題:-)いた
スチュアートワット

127

dictのリストをフィルタリングするには、equaltoテストと一緒にselectattrフィルターを使用できます。

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

上記には、Jinja2 v2.8以降が必要です(Ansibleのバージョンに関係なく)。


Ansibleには、matchsearch正規表現をとるテストがあります。

match文字列内で完全に一致searchする必要がありますが、文字列内で一致する必要があります。

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

dictのリストを文字列のリストに減らして、addrフィールドのリストのみを取得するには、マップフィルターを使用できます。

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

または、カンマ区切りの文字列が必要な場合:

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

組み合わせると、次のようになります。

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

1
あなたではなくカンマ区切りの文字列よりもリストとしてそれらをしたい場合は、使用することができます:{{ network.addresses.private_man | selectattr("type", "equalto", "fixed") | map(attribute='addr') | list }}
TrinitronX

1
あなたが提供するリンクは変更されましたか?私は「一致」を見つけ、そのページの「検索」することはできません
activedecay

1
@activedecayそのページから消えたようです、はい。私が今見つけた唯一の言及はこのページにあります:docs.ansible.com/ansible/latest/user_guide/…リンクを更新しました、ありがとう!
udondan

19

必ずしも良いとは限りませんが、オプションがあると便利なので、Jinjaステートメントを使用してそれを行う方法は次のとおりです。

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

または、すべてを1行にまとめたい場合:

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

どちらが返されますか:

ok: [localhost] => {
    "msg": "172.16.1.100"
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.