Ansible の辞書リスト内の指定された辞書キーの値にアクセスする

Ansible の辞書リスト内の指定された辞書キーの値にアクセスする

私は変数を登録し、それを出力することで、Ansible にパッケージのリストをインストールしていますdebug:

  community.general.homebrew:
    name: "{{ package }}"
    state: present
  register: package_install
  until: package_install is succeeded
  loop:
    - pam-reattach
    - pinentry-mac
    - jorgelbg/tap/pinentry-touchid
  loop_control:
    loop_var: package

- debug:
    msg: "{{ package_install }}"

出力は次のようになります。
msg:
  changed: true
  msg: All items completed
  results:
  - ansible_loop_var: package
    attempts: 1
    changed: false
    changed_pkgs: []
    failed: false
    invocation:
      module_args:
        install_options: []
        name:
        - pam-reattach
        path: /usr/local/bin:/opt/homebrew/bin:/home/linuxbrew/.linuxbrew/bin
        state: present
        update_homebrew: false
        upgrade_all: false
        upgrade_options: []
    msg: 'Package already installed: pam-reattach'
    package: pam-reattach
    unchanged_pkgs:
    - pam-reattach
  - ansible_loop_var: package
    attempts: 1
    changed: true
    changed_pkgs:
    - pinentry-mac
    failed: false
    invocation:
      module_args:
        install_options: []
        name:
        - pinentry-mac
        path: /usr/local/bin:/opt/homebrew/bin:/home/linuxbrew/.linuxbrew/bin
        state: present
        update_homebrew: false
        upgrade_all: false
        upgrade_options: []
    msg: 'Package installed: pinentry-mac'
    package: pinentry-mac
    unchanged_pkgs: []
  - ansible_loop_var: package
    attempts: 1
    changed: true
    changed_pkgs:
    - jorgelbg/tap/pinentry-touchid
    failed: false
    invocation:
      module_args:
        install_options: []
        name:
        - jorgelbg/tap/pinentry-touchid
        path: /usr/local/bin:/opt/homebrew/bin:/home/linuxbrew/.linuxbrew/bin
        state: present
        update_homebrew: false
        upgrade_all: false
        upgrade_options: []
    msg: 'Package installed: jorgelbg/tap/pinentry-touchid'
    package: jorgelbg/tap/pinentry-touchid
    unchanged_pkgs: []
  skipped: false

登録された変数には、各インストールpackage_install.resultsに関連するデータを含む辞書 (またはマップ/ハッシュ - 間違っていたら訂正してください) のリストが含まれています。package

pinentry-mac前のタスク中にまたはpinentry-touchidパッケージのいずれかがインストールされているかどうかを確認する必要があります(changed各項目内のキーの値が または に等しいtrueかどうかfalse)。インストールされている場合は、指定されたコマンドを実行します。例:

- command: <command>
  when: >
    `pinentry-mac` item's attribute `changed` is `True` within `package_install.results` \
    OR \
    `pinentry-touchid` item's attribute `changed` is `True` within `package_install.results`

どうすればいいでしょうか?

現在、私は次のことを行っています。

  - command: <command>
    when: "'pinentry' in item.package and item.changed"
    loop: "{{ macterm_package_install.results }}"

ただし、この場合、コマンドは 1 回だけ実行する必要がありますが、前の手順で両方のパッケージがインストールされていれば、コマンドは 2 回実行されます。

適切に行う方法はありますか? ご意見をいただければ幸いです。

アップデート

私が見つけた「最善の」方法はこれです(2 つのステップ)。

  - name: Check if any of the pinentry packages were installed during previous tasks
    set_fact:
      pinentry_changed: True
    when: "'pinentry-' in item.package and item.changed"
    loop: "{{ macterm_package_install.results }}"

  - command: <command>
    when: pinentry_changed | default(false)

しかし、本当にこれを解決するもっとエレガントな方法はあるのでしょうか?

答え1

多くのオプションがあります。ユースケースに最適なものを選択してください。

  1. 辞書を作成する
  package_changed: "{{ package_install.results|
                       items2dict(key_name='package', value_name='changed') }}"

与える

  package_changed:
    jorgelbg/tap/pinentry-touchid: true
    pam-reattach: false
    pinentry-mac: true

すると条件は些細なものになる

    - command: <command>
      when:  package_changed['pinentry-mac'] or
             package_changed['jorgelbg/tap/pinentry-touchid']
  1. 変更されたパッケージのリストを作成する
  changed_pkgs: "{{ package_install.results|
                    map(attribute='changed_pkgs')|flatten }}"

与える

  changed_pkgs:
  - pinentry-mac
  - jorgelbg/tap/pinentry-touchid

各パッケージをテストするか

    - command: <command>
      when:  ('pinentry-mac' in changed_pkgs) or
             ('jorgelbg/tap/pinentry-touchid' in changed_pkgs)

、またはテストしたパッケージをリストに入れることができる場合は、リストを交差させる

    - command: <command>
      when:  changed_pkgs|intersect(test_pkgs)|length > 0
      vars:
        test_pkgs: [pinentry-mac, jorgelbg/tap/pinentry-touchid]
  1. リストを作成し、ベース名をマップする
  changed_pkgs: "{{ package_install.results|
                    map(attribute='changed_pkgs')|flatten|
                    map('basename')|list }}"

与える

  changed_pkgs:
  - pinentry-mac
  - pinentry-touchid

パッケージ名のみを使用する

    - command: <command>
      when:  ('pinentry-mac' in changed_pkgs) or
             ('pinentry-touchid' in changed_pkgs)

関連情報