Frage Anhängen an Listen oder Hinzufügen von Schlüsseln zu Wörterbüchern in Ansible


(Bezüglich Callbacks oder Hooks und wiederverwendbare Taskserien in Ansible-Rollen):

Gibt es eine bessere Möglichkeit, eine Liste anzuhängen oder einen Schlüssel zu einem Wörterbuch in Ansible hinzuzufügen als (ab) einen jina2-Vorlagenausdruck zu verwenden?

Ich weiß, dass du etwas tun kannst wie:

- name: this is a hack
  shell: echo "{% originalvar.append('x') %}New value of originalvar is {{originalvar}}"

Aber gibt es wirklich keine Art von Meta-Aufgabe oder Helfer, dies zu tun?

Es fühlt sich fragil an, scheint undokumentiert zu sein und beruht auf vielen Annahmen darüber, wie Variablen in Ansible funktionieren.

Mein Anwendungsfall sind mehrere Rollen (Datenbankservererweiterungen), die jeweils eine Konfiguration für eine Basisrolle (den Datenbankserver) bereitstellen müssen. Es ist nicht so einfach wie das Anhängen einer Zeile an die Konfigurationsdatei des Datenbankservers; Jede Änderung gilt für die gleiche Linie, z.B. die Erweiterungen bdr und pg_stat_statements müssen beide auf einer Ziellinie erscheinen:

shared_preload_libaries = 'bdr, pg_stat_statements'

Ist die Ansible Möglichkeit, dies zu tun, um die Konfigurationsdatei nur mehrmals (einmal pro Erweiterung) mit einem regulären Ausdruck zu verarbeiten, der den aktuellen Wert extrahiert, analysiert und dann neu schreibt? Wenn ja, wie macht man dieses Idempotent über mehrere Läufe hinweg?

Was ist, wenn die Konfiguration schwieriger zu parsen ist und es nicht so einfach ist, einen anderen kommagetrennten Wert anzuhängen? Denken Sie an XML-Konfigurationsdateien.


27
2018-04-26 14:17


Ursprung


Weißt du was? Ich mag den Schnitt deines seitenwirksamen Jibs - DomQ


Antworten:


Sie können zwei Listen in einer Variablen mit zusammenführen +. Sag, du hast ein group_vars Datei mit diesem Inhalt:

---
# group_vars/all
pgsql_extensions:
  - ext1
  - ext2
  - ext3

Und es wird in einer Vorlage verwendet pgsql.conf.j2 mögen:

# {{ ansible_managed }}
pgsql_extensions={% for item in pgsql_extensions %}{{ item }}, {% endfor %}

Sie können dann den Test-Datenbankservern Erweiterungen wie folgt hinzufügen:

---
# group_vars/testing_db
append_exts:
  - ext4
  - ext5
pgsql_extensions: "{{ pgsql_extensions + append_exts }}"

Wenn die Rolle auf einem der Testserver ausgeführt wird, werden die zusätzlichen Erweiterungen hinzugefügt.

Ich bin mir nicht sicher, ob dies auch für Wörterbücher funktioniert, und achten Sie auch auf Leerzeichen und lassen Sie am Ende der Zeile ein freies Komma stehen.


11
2018-06-26 16:51



Sie können, aber Sie müssen alles tun group_varsDie Rollen können sich nicht um die Details der Einrichtung der Erweiterungen selbst kümmern. Es fügt vars hinzu Rollen die ich besonders suche, also kann eine Rolle an eine von einer anderen Rolle ausgesetzte Var anhängen. - Craig Ringer
Kennt Ihre Basisrolle jede Erweiterungsrolle? Ich hatte einen ähnlichen Fall, in dem ich die Verkettung bis zu einem Punkt verlassen konnte with_items Satz. - GnP
Nein, und das ist wirklich das Problem. In einer Bereitstellung könnte die Basisrolle al sein - Craig Ringer
Nein, und das ist wirklich das Problem. Die Basisrolle kann eigenständig in einer Bereitstellung verwendet werden, mit einer Erweiterung in einer anderen Bereitstellung und zwei verschiedenen Erweiterungen in einer anderen. Anstatt die Rolle für jeden zu kopieren und zu bearbeiten, mit dem resultierenden Wartungs-Albtraum, möchte ich es einfach wiederverwendbar machen, damit ich es als ein Git-Submodul einbringen kann. - Craig Ringer
Es scheint, als ob Sie versuchen, dies zu tun, um zwei Listen zu verketten, und es denkt, dass es eine unendlich rekursive Vorlage ist, weil die linke Seite auch auf der rechten Seite ist. Missverständnis ich, wie man das benutzt? - Ibrahim


Seit Ansible v2.x können Sie dies tun:

# use case I: appending to LIST variable:

      - name: my appender
        set_fact:
          my_list_var: '{{my_list_myvar + new_items_list}}'

# use case II: appending to LIST variable one by one:

      - name: my appender
        set_fact:
          my_list_var: '{{my_list_var + [item]}}'
        with_items: '{{my_new_items|list}}'

# use case III: appending more keys DICT variable in a "batch":

      - name: my appender
        set_fact:
          my_dict_var: '{{my_dict_var|combine(my_new_keys_in_a_dict)}}'

# use case IV: appending keys DICT variable one by one from tuples
      - name: setup list of tuples (for 2.4.x and up
        set_fact:
          lot: >
            [('key1', 'value1',), ('key2', 'value2',), ..., ('keyN', 'valueN',)],
      - name: my appender
        set_fact:
          my_dict_var: '{{my_dict_var|combine({item[0]: item[1]})}}'
        with_items: '{{lot}}'
# use case V: appending keys DICT variable one by one from list of dicts (thanks to @ssc)

  - name: add new key / value pairs to dict
    set_fact:
      my_dict_var: "{{ my_dict_var | combine({item.key: item.value}) }}"
    with_items:
    - { key: 'key01', value: 'value 01' }
    - { key: 'key02', value: 'value 03' }
    - { key: 'key03', value: 'value 04' }

all das ist dokumentiert in: http://docs.ansible.com/ansible/playbooks_filters.html


24
2017-12-09 09:28



Anwendungsfall IV fügt nur hinzu u'(': u\"'\"}" - ssc
Danke, @ssc. Ich habe bemerkt, dass es nicht mit Ansible funktioniert 2.4.x (FEST) - Max Kovgan
@ssc danke für den Vorschlag +1 - Max Kovgan
nach Usecase # 4 habe ich den Standardwert hinzugefügt undefinierter Fehler in meinem Szenario: set_fact: my_dict_var: '{{my_dict_var|default({})|combine({item[0]: item[1]})}}'. Der undefinierte Fehler tritt auf, wenn eine Filterung verwendet oder keine Ergebnisse registriert werden. - S.K. Venkat


Sie müssen die Schleife in 2 aufteilen

---
- Gastgeber: localhost
  Aufgaben:
    - include_vars: Stapel
    - set_facts: roles = {{stacks.Roles | Teilt(' ')}}
    - Include: addhost.yml
      with_items: "{{Rollen}}"

und addhost.yml

- set_facts: Gruppenname = {{item}}
- set_facts: ips = {{stacks [Element] | split ('')}}
- local_action: add_host hostname = {{item}} Gruppenname = {{Gruppenname}}
  with_items: {{ips}}

3
2018-03-15 17:05





Nicht sicher wann Sie haben das hinzugefügt, aber zumindest für Wörterbücher / Hashes (NICHT Listen / Arrays) können Sie die Variable setzen hash_behaviour, so: hash_behaviour = merge in deiner ansible.cfg.

Ich habe einige Stunden gebraucht, um zufällig über diese Einstellung zu stolpern: S


0
2017-08-08 10:51



Dies ist sehr praktisch, aber achten Sie darauf, es auf der vorhandenen Codebasis e2e zu ermöglichen. kann einige Eier brechen. - Max Kovgan


Ansible ist ein Automatisierungssystem, und bezüglich der Konfigurationsdateiverwaltung unterscheidet es sich nicht sehr von apt. Der Grund mehr und mehr Software bietet die Möglichkeit, Konfigurations-Schnipsel von einem zu lesen conf.d Verzeichnis soll es ermöglichen, dass solche Automatisierungssysteme unterschiedliche Pakete / Rollen haben, um der Software eine Konfiguration hinzuzufügen. Ich glaube, dass es nicht die Philosophie von ist Ansiblezu tun, was Sie im Sinn haben, sondern stattdessen die conf.d Trick. Wenn die zu konfigurierende Software diese Funktionalität nicht bietet, liegt möglicherweise ein Problem vor.

Da Sie XML-Konfigurationsdateien erwähnen, nutze ich die Gelegenheit, etwas zu jammern. Es gibt einen Grund für die Unix-Tradition, Klartextkonfigurationsdateien zu verwenden. Binärkonfigurationsdateien eignen sich nicht gut für die Systemautomatisierung, so dass jede Art von Binärformat Ihnen Probleme bereiten wird und Sie wahrscheinlich ein Programm erstellen müssen, um die Konfiguration zu handhaben. (Wenn jemand denkt, dass XML ein reines Textformat ist, sollten die Gehirne untersucht werden.)

Jetzt zu deinem spezifischen PostgreSQL Problem. PostgreSQL unterstützt die conf.d Trick. Zuerst würde ich prüfen, ob shared_preload_libraries kann mehrfach angegeben werden. Ich habe in der Dokumentation keinen Hinweis darauf gefunden, aber ich würde es trotzdem versuchen. Wenn es nicht mehrfach angegeben werden kann, würde ich mein Problem erklären PostgreSQL Leute, falls sie Ideen haben; das ist ein PostgreSQL Ausgabe und nicht ein Ansible Problem. Wenn es keine Lösung gibt und ich die verschiedenen Rollen wirklich nicht zu einer zusammenführen könnte, würde ich ein System implementieren, um die Konfiguration auf dem verwalteten Host zu kompilieren. In diesem Fall würde ich wahrscheinlich ein Skript erstellen /usr/local/sbin/update_postgresql_config was würde kompilieren /etc/postgresql/postgresql.conf.jinja in /etc/postgresql/9.x/main/postgresql.conf. Das Skript würde die freigegebenen Preload-Bibliotheken von lesen /etc/postgresql/shared_preload_libraries.txt, eine Bibliothek pro Zeile, und stelle sie Jinja zur Verfügung.

Für Automatisierungssysteme ist dies nicht ungewöhnlich. Ein Beispiel ist das Debian exim4 Paket.


-4
2018-04-28 07:01



PostgreSQL unterstützt a conf.d Include-Mechanismus und verwendet glücklicherweise Klartextdateien. Es gibt jedoch einige Konfigurationsoptionen, bei denen mehrere Erweiterungen eine Meinung dazu haben können - z. B. "max_wal_senders um 10 erhöhen, von was auch immer es vorher war". - Craig Ringer
Es scheint, dass Sie sagen, dass die Anwendung geändert werden sollte, um Einschränkungen im Konfigurationsmanagementsystem zu umgehen, oder ich sollte auf wiederverwendbare Rollen verzichten. - Craig Ringer