[PYTHON] [Kleine Geschichte] Zwei Möglichkeiten zum korrekten Zusammenführen von Ansible- und verschachtelten Diktatvariablen

Wie füge ich Variablen mit Ansible zusammen?

Ansible verwendet Jinja2 für den Filter von Variablen.

Möchten Sie manchmal Variablen einschließlich Wörterbücher vertiefen? Heute werde ich zwei Möglichkeiten vorstellen, um eine tiefe Verschmelzung von Variablen mit Ansible zu realisieren. Was anders ist, ist, dass die Methode für Ansible 2.0 und höher und darunter unterschiedlich ist.

Für Ansible-Version "> = 2.0"

Seit Ansible 2.0 wurde ein neuer ** Mähdrescherfilter ** implementiert. http://docs.ansible.com/ansible/playbooks_filters.html#combining-hashes-dictionaries

test.yml


- hosts: localhost
  gather_facts: no
  vars:
    dict:
      foo:
        bar: 1
    dict2:
      foo:
        baz: 2
      qux: 2
    # combining hashes/dictionaries (new in version 2.0)
    dict_combine: "{{ dict | combine(dict2, recursive=True) }}"
  tasks:
    - debug:
        var: dict_combine

Wenn Sie die oben genannten Schritte ausführen, erhalten Sie die folgenden Ergebnisse.

$ ansible-playbook -i localhost, test.yml

PLAY [localhost] ***************************************************************

TASK [debug] *******************************************************************
ok: [localhost] => {
    "dict_combine": {
        "foo": {
            "bar": 1,
            "baz": 2
        },
        "qux": 2
    }
}

Es ist sehr praktisch. Der Inhalt von dict-> foo wird ordnungsgemäß zusammengeführt. Das Weglassen von "rekursiv" ist übrigens nur eine Zusammenführung von Updates.

recursive=false


$ ansible-playbook -i localhost, test.yml

PLAY [localhost] ***************************************************************

TASK [debug] *******************************************************************
ok: [localhost] => {
    "dict_combine": {
        "foo": {
            "baz": 2
        },
        "qux": 2
    }
}

Übrigens könnte die Funktion zum Kombinieren, die rekursiv weglässt, wie folgt realisiert werden, indem update () auch in der Version vor Ansible 2.0 verwendet wird.

test.yml


- hosts: localhost
  gather_facts: no
  vars:
    dict:
      foo:
        bar: 1
    dict2:
      foo:
        baz: 2
      qux: 2
    # **[Note]**
    # jinja2 'do' tag need expression-statement extension
    # please set below to [default] section in ansible.cfg
    # jinja2_extensions=jinja2.ext.do
    dict_update: |
      {% do dict.update(dict2) %}
      {{ dict }}
  tasks:
    - debug:
        var: dict_update

Für Ansible-Version "<2.0"

Wenn Sie Ansible 1.X aus verschiedenen Gründen verwenden müssen, ist dies etwas unpraktisch, da Sie Combine nicht verwenden können. Natürlich können Sie den in 2.0 implementierten Quellteil des Mähdreschers importieren, aber da dies eine große Sache ist, möchte ich mein eigenes Filter-Plugin erstellen. http://docs.ansible.com/ansible/developing_plugins.html#filter-plugins

Um das Plugin zu verwenden, geben Sie den Pfad (filter_plugins =) in ansible.cfg ein oder legen Sie die benutzerdefinierte Datei direkt im Plugin-Verzeichnis von ansible selbst ab. Sie wird gelesen, wenn ansible ausgeführt wird.

/path-to/ansible/filter_plugins/dict_merge.py


from copy import deepcopy


def dict_merge(a, b):
    if not isinstance(b, dict):
        return b
    result = deepcopy(a)
    for k, v in b.iteritems():
        if k in result and isinstance(result[k], dict):
                result[k] = dict_merge(result[k], v)
        else:
            result[k] = deepcopy(v)
    return result


class FilterModule(object):
    def filters(self):
        return {'dict_merge': dict_merge}

Damit ist die Plug-In-Erstellung abgeschlossen. Es ist einfacher als du denkst. Lass es uns testen.

test.yml


- hosts: localhost
  gather_facts: no
  vars:
    dict:
      foo:
        bar: 1
    dict2:
      foo:
        baz: 2
      qux: 2
    # custom filter plugin
    dict_merged: "{{ dict | dict_merge(dict2) }}"
  tasks:
    - debug:
        var: dict_merged

Das Ausführungsergebnis ist wie folgt.

$ ansible-playbook -i localhost, test.yml

PLAY [localhost] ***************************************************************

TASK [debug] *******************************************************************
ok: [localhost] => {
    "dict_merged": {
        "foo": {
            "bar": 1,
            "baz": 2
        },
        "qux": 2
    }
}

Ich konnte das gleiche Ergebnis wie Mähdrescher erzielen. Natürlich verschmilzt es auch tiefere Diktate.

  1. Wenn Sie Deep Merge schnell im X-System verwenden möchten, gibt es eine solche Möglichkeit. Warum also nicht in Betracht ziehen?

Andere

Zusätzlich zum Filter-Plug-In verfügt Ansible über mehrere Plug-Ins, die Sie selbst erstellen können. http://docs.ansible.com/ansible/developing_plugins.html

Lookup- und Callback-Plug-Ins sind relativ informativ und enthalten Informationen zu Personen, die verschiedene Aufgaben ausführen.

Let's enjoy your Ansible life!

Recommended Posts

[Kleine Geschichte] Zwei Möglichkeiten zum korrekten Zusammenführen von Ansible- und verschachtelten Diktatvariablen
Zwei Möglichkeiten, Ansible portabel zu machen