Zugriffswert des angegebenen Wörterbuchschlüssels innerhalb einer Liste von Wörterbüchern in Ansible

Zugriffswert des angegebenen Wörterbuchschlüssels innerhalb einer Liste von Wörterbüchern in Ansible

Ich installiere eine Liste von Paketen in der Ansible-Registrierungsvariable und gebe sie mit folgendem aus 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 }}"

Die Ausgabe sieht folgendermaßen aus:
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

Die registrierte Variable package_install.resultsenthält eine Liste von Wörterbüchern (oder Maps/Hashes – bitte korrigieren Sie mich, wenn ich falsch liege) mit den Daten, die sich auf jede packageInstallation beziehen.

Ich muss prüfen, ob während der vorherigen Aufgabe entweder pinentry-macoder pinentry-touchid-Pakete installiert wurden (ist der Schlüsselwert changedinnerhalb jedes Elements gleich trueoder false) und wenn ja, dann einen angegebenen Befehl ausführen, z. B.:

- 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`

Wie würde ich das machen?

Im Moment mache ich Folgendes:

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

In diesem Fall wird der Befehl jedoch zweimal ausgeführt, wenn beide Pakete im vorherigen Schritt installiert wurden, obwohl der Befehl nur einmal ausgeführt werden muss.

Gibt es eine Möglichkeit, es richtig zu machen? Ich bin für jeden Gedanken dankbar.

AKTUALISIEREN

Der „beste“ Weg, den ich finden konnte, ist dieser (in zwei Schritten):

  - 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)

Aber gibt es wirklich eine elegantere Möglichkeit, dieses Problem zu lösen?

Antwort1

Es gibt viele Optionen. Wählen Sie diejenige aus, die am besten zu Ihrem Anwendungsfall passt.

  1. Erstellen Sie das Wörterbuch
  package_changed: "{{ package_install.results|
                       items2dict(key_name='package', value_name='changed') }}"

gibt

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

Dann sind die Bedingungen trivial

    - command: <command>
      when:  package_changed['pinentry-mac'] or
             package_changed['jorgelbg/tap/pinentry-touchid']
  1. Erstellen Sie die Liste der geänderten Pakete
  changed_pkgs: "{{ package_install.results|
                    map(attribute='changed_pkgs')|flatten }}"

gibt

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

Testen Sie entweder jedes Paket

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

, oder schneiden Sie die Listen, wenn Sie die getesteten Pakete in eine Liste einfügen können

    - command: <command>
      when:  changed_pkgs|intersect(test_pkgs)|length > 0
      vars:
        test_pkgs: [pinentry-mac, jorgelbg/tap/pinentry-touchid]
  1. Erstellen Sie die Liste und ordnen Sie den Basisnamen zu
  changed_pkgs: "{{ package_install.results|
                    map(attribute='changed_pkgs')|flatten|
                    map('basename')|list }}"

gibt

  changed_pkgs:
  - pinentry-mac
  - pinentry-touchid

Verwenden Sie nur die Namen der Pakete

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

verwandte Informationen