Ansible: Definieren Sie Variablen in der vars-Datei bedingt, wenn eine bestimmte Bedingung erfüllt ist

19

Abhängig vom Wert (True / False) einer in group_vars definierten Variablen versuche ich, einige Variablen in einer vars-Datei zu definieren. Ihr Wert hängt vom Wert der Gruppenvariablen ab.

Meine aktuelle var-Datei sieht folgendermaßen aus:

{% if my_group_var %}
test:
   var1: value
   var2: value
   ...
   varn: value
{% else %}
test:
   var1: other_value
   var2: other_value
   ...
   varn: other_value
{% endif %}

Für jede meiner Rollen verwende ich eine Variable, die in dieser Datei definiert ist.

Mein Test-Playbook sieht wie folgt aus:

- name: blabla
  hosts: blabla
  vars_files:
     - <path>/test_vars.yml
  roles: blabla 

Der Fehler, den ich nach dem Ausführen des Playbooks erhalte, ist:

{% if my_group_var %}
 ^ here

exception type: <class 'yaml.scanner.ScannerError'>
exception: while scanning for the next token
found character that cannot start any token
  in "<unicode string>"

Mache ich hier etwas dummes oder wird das nicht mal unterstützt? Ich habe versucht, einen anderen Weg zu finden, um diese Vars zu definieren (ich habe viele davon), aber ich habe es nicht geschafft, hier etwas Funktionales zu finden. Irgendwelche Vorschläge?

pandoJohn
quelle
Wo kommen diese Vars zum Einsatz? Dies kann unnötig sein, wenn Sie sie nur als Teil eines templateModulaufrufs verwenden.
84104
Wenn testes gruppenabhängig ist, sollte es in group_vars platziert werden.
Konstantin Suvorov
Leider ist der Test nicht gruppenabhängig. Wie in der Beschreibung erwähnt, hängt der Test vom Wert einer Variablen group_var ab.
PandoJohn

Antworten:

11

Ich glaube nicht, dass Sie das können. Normalerweise erstelle ich separate Dateien, um bedingte Variablensammlungen zu speichern und benutze eine whenKlausel, um sie unter einer bestimmten Bedingung einzuschließen:

- include_vars: test_environment_vars.yml
  when: global_platform == "test"

- include_vars: staging_environment_vars.yml
  when: global_platform == "staging"

- include_vars: prod_environment_vars.yml
  when: 
    - global_platform != "test" 
    - global_platform != "staging" 
HBruijn
quelle
2
Das wollte ich vermeiden. Ich möchte keine Include-Variablen verwenden oder 2 zusätzliche Variablendateien für meine Aufgaben definieren.
pandoJohn
Ich verstehe es nicht. Wenn include_vars mit condition verwendet werden kann, warum kann Variable nicht mit condition definiert werden?
GP92
9

Mit Ansible kann eine der folgenden Formen eine Variable bedingt definieren:

    test:
      var1: "{% if my_group_var %}value{% else %}other_value{% endif %}"
      var2: "{{'value' if (my_group_var) else 'other_value'}}"

Durch Kombination der obigen Syntax mit vars lookup können wir komplexe Variablen laden (in diesem Fall auflisten):

test_value_when_my_group_var_is_true:
   var1: value
   var2: value

test_value_when_my_group_var_is_false:
   var1: other_value
   var2: other_value

test: "{{ lookup('vars','test_value_when_my_group_var_is_true') if (my_group_var) else lookup('vars','test_value_when_my_group_var_is_false')}}"

Es gibt eine andere Möglichkeit, das bedingte Laden von Bäumen mit vars lookup durchzuführen. Dieser Weg ist praktisch, wenn Sie eine Falllogik implementieren müssen (dh die Bedingungsvariable hat mehr als zwei mögliche Werte):

test_value_when_my_group_var_is_foo:
   var1: value
   var2: value

test_value_when_my_group_var_is_bar:
   var1: other_value
   var2: other_value

test_value_when_my_group_var_is_baz:
   var1: yet_another_value
   var2: yet_another_value

test: "{{ lookup('vars','test_value_when_my_group_var_is_' + my_group_var) }}"
Vladimir
quelle
2

Trotzdem wäre es schön, ich fürchte, dass dein Weg nicht möglich ist (oder ich weiß nicht, wie es richtig ist).

Ich würde vorschlagen, zuerst die vars-Datei aus der jinja-Vorlage vorzubereiten und sie dann in include_vars einzuschließen. Siehe das Beispiel-Playbook:

---
- name: -Test-
  hosts: local
  vars:
    my_group_var: False
#    my_group_var: True

  tasks:

  - name: Prepare vars file from template.
    template: src=/tmp/vars.yaml.j2
              dest=/tmp/vars.yaml

  - name: Include vars
    include_vars: "/tmp/vars.yaml"

Der Inhalt der Beispiel-Jinja-Vorlage /tmp/vars.yaml.j2 ist:

{% if my_group_var %}                                                                                                                                                                                             
test:                                                                                                                                                                                                             
   var1: value                                                                                                                                                                                                    
   var2: value                                                                                                                                                                                                    
{% else %}                                                                                                                                                                                                        
test:                                                                                                                                                                                                             
   var1: other_value                                                                                                                                                                                              
   var2: other_value                                                                                                                                                                                              
{% endif %}
Jaroslav Kucera
quelle
Ich mag das, aber das Problem ist, dass nach dem Generieren der .yml-Datei aus der jinja-Vorlage diese nicht für die nachfolgenden Aufgaben aus meinem Playbook verfügbar ist.
PandoJohn
Warum? Als ich versuchte , den Test mit Textbuch Debug - Aufgabe zu verlängern - debug: var=testich sehen kann, dass es definiert beide test.var1und test.var2mit den erwarteten Werten. Sie sollten also in der Lage sein, diese Variablen in anderen Aufgaben des Playbooks zu verwenden.
Jaroslav Kucera
0

AFAIK, das, was Sie versuchen, ist für Jinja2-Vorlagen und nicht für yml-Dateien. Aus der Dokumentation :

ansible erlaubt Jinja2-Schleifen und Bedingungen in Vorlagen, aber in Playbooks verwenden wir sie nicht.

Sie können eine separate .yml-Datei mit einer Wiedergabe vorbereiten, die die benötigten Variablen mit Hilfe der when-Klauseln einrichtet und diese dann in Ihr Haupt-Wiedergabebuch importiert (oder einschließt). Auf diese Weise können Sie alle Variablen in einer einzigen Datei bedingt definieren.

ODER: Verwenden Sie Rollen. Ich denke, Rollen sind der adäquateste Ansatz, um Ihr Problem zu lösen.

Niglesias
quelle
0

Am Ende habe ich 2 separate var-Dateien erstellt - nennen wir sie type_a.ymlund type_b.yml- und ich habe eine Gruppenvariable definiert, die angibt, welche Datei verwendet werden soll - so etwas wie type_of_file: a. So sieht mein Playbook jetzt aus:

- name: blabla
  hosts: blabla
  vars_files:
     - <path>/type_{{ type_of_file }}.yml
  roles: blabla

Danke für alle Antworten. Ich finde sie wirklich hilfreich.

pandoJohn
quelle
0

Ich hoffe, dass der folgende Ausschnitt (aus der Ansible-Dokumentation ) eine sinnvolle Ergänzung zu den nützlichen Beiträgen anderer oben ist.

- name: Show value of 'variablename'
  debug: msg="{{ lookup('vars', 'variabl' + myvar)}}"
  vars:
    variablename: hello
    myvar: ename
Peter Smallwood
quelle