2017-11-07 5 views
3

Jemand erwähnte Umgebungsvariablen. Können Sie das näher ausführen?Wie setze ich eine Ansible-Variable für alle Spiele/Hosts?

Dies scheint ein einfaches Problem, aber nicht in ansible. Es kommt immer wieder hoch. Vor allem in Fehlerbedingungen. Ich brauche eine globale Variable. Eine, die ich bei der Verarbeitung eines Hostspiels einstellen kann und dann zu einem späteren Zeitpunkt mit einem anderen Host überprüfe. Die Verzweigung wäre in Ansible so viel einfacher.

Der Gültigkeitsbereich der Variablen bezieht sich NUR auf den aktuellen ansible_hostname. Ja, wir haben group_vars/all.yml als Globals, aber wir können sie nicht in einem Spiel setzen. Wenn ich eine Variable setze, kann das Spiel/die Aufgabe eines anderen Hosts sie nicht sehen. Ich verstehe den Umfang der Variablen, aber ich möchte eine globale Variable einstellen, die in allen Playbook-Spielen gelesen werden kann. Die eigentliche Implementierung ist unwichtig, aber variabler Zugriff ist (wichtig).

Meine Frage: Gibt es eine Möglichkeit, eine Variable festzulegen, die überprüft werden kann, wenn eine andere Aufgabe auf einem anderen Host ausgeführt wird? Etwas wie setGlobalSpaceVar (myvar, wahr)? Ich weiß, dass es keine solche Methode gibt, aber ich suche nach einer Lösung. Umformulieren: Legen Sie eine Variable in einer Aufgabe für einen Host und später in einer anderen Aufgabe für einen anderen Host fest und lesen Sie diese Variable.

Der einzige Weg, an den ich denken kann, ist eine Datei auf dem Controller zu ändern, aber das scheint falsch.

Ein Beispiel

Im Folgenden bezieht sich auf Oracle-Backups und unsere lokale ausführbare Datei, aber ich bin es generic zu halten. Denn unten - Ja, ich kann run_once machen, aber das beantwortet meine Frage nicht. Dieses Problem mit variablem Zugriff tritt immer wieder in verschiedenen Kontexten auf.

Ich habe 4 xyz-Server. Ich habe 2 Programme, die ausgeführt werden müssen, aber nur auf 2 verschiedenen Maschinen. Ich weiß nicht was. Die Einstellungen können für verschiedene VM-Umgebungen geändert werden.

Unser ProgrammOne wird auf dem Server ausgeführt, der über ein Laufwerk E verfügt. Ich kann mithilfe von Ansible herausfinden, welcher Server über Laufwerk E verfügt, und das Spiel entsprechend ausführen, wenn ich eine Variable (driveE_machine) einstelle. Es gilt nur für diesen Host. Für die anderen 3 Computer wird driveE_machine nicht festgelegt. In einem späteren Spiel muss ich ein anderes Programm auf NUR einer der anderen 3 Maschinen ausführen. Das bedeutet, ich muss eine Variable setzen, die von den anderen 2 Hosts gelesen werden kann, die das 2. Programm nicht ausgeführt haben. Ich bin mir nicht sicher, wie es geht.

Inventar-Datei:

[xyz] 
serverxyz[1:4].private.mystuff 

Textbuch Beispiel:

--- 
- name: stackoverflow variable question 
    hosts: xyz 
    gather_facts: no 
    serial: 1 
    tasks: 
     - name: find out who has drive E 
     win_shell: dir e:\ 
     register: adminPage 
     ignore_errors: true 

     # This sets a variable that can only be read for that host 
     - name: set fact driveE_machine when rc is 0 
     set_fact: 
      driveE_machine: "{{inventory_hostname}}" 
     when: adminPage.rc == 0 

     - name: run program 1 
     include: tasks/program1.yml 
     when: driveE_machine is defined 

     # program2.yml executes program2 and needs to set some kind of variable 
     # so this include can only be executed once for the other 3 machines 
     # (not one that has driveE_machine defined and ??? 
     - name: run program 2 
     include: tasks/program2.yml 
     when: driveE_machine is undefined and ??? 
     # please don't say run_once: true - that won't solve my variable access question 

Gibt es eine Möglichkeit, eine Variable zu setzen, überprüft werden kann, wenn sie auf einen anderen Host eine Aufgabe ausgeführt wird?

+0

Ich bin mir ziemlich sicher, dass ansible dies nicht durch Design erlaubt - weil geteilter veränderbarer Zustand böse ist: https://stackoverflow.com/questions/19158339/why-are-global-variables-evil – stefreak

+0

@stefreak ja globals sind böse aber 1 Dies ist ein Framework, kein Programm. Wir müssen den Rahmen bearbeiten. 2. Ich brauche einen Weg, um mit verschiedenen Hosts in Ansible zu verzweigen und ohne eine Variable, das kann sehr schwierig werden. Diese Prämie ist geschlossen, aber niemand hat darauf geantwortet. –

Antwort

0

Nein sicher, was Sie wirklich wollen, aber Sie eine Tatsache, für jeden Host in einem Spiel mit einem einzigen geschleift Aufgabe (einige Simulation der globalen Variablen) einstellen:

playbook.yml

--- 
- hosts: mytest 
    gather_facts: no 
    vars: 
    tasks: 
    # Set myvar fact for every host in a play 
    - set_fact: 
     myvar: "{{ inventory_hostname }}" 
     delegate_to: "{{ item }}" 
     with_items: "{{ play_hosts }}" 
     run_once: yes 
    # Ensure that myvar is a name of the first host 
    - debug: 
     msg: "{{ myvar }}" 

Gastgeber
[mytest] 
aaa ansible_connection=local 
bbb ansible_connection=local 
ccc ansible_connection=local 

Ergebnis

PLAY [mytest] ****************** 
META: ran handlers 

TASK [set_fact] ****************** 
ok: [aaa -> aaa] => (item=aaa) => {"ansible_facts": {"myvar": "aaa"}, "ansible_facts_cacheable": false, "changed": false, "failed": false, "item": "aaa"} 
ok: [aaa -> bbb] => (item=bbb) => {"ansible_facts": {"myvar": "aaa"}, "ansible_facts_cacheable": false, "changed": false, "failed": false, "item": "bbb"} 
ok: [aaa -> ccc] => (item=ccc) => {"ansible_facts": {"myvar": "aaa"}, "ansible_facts_cacheable": false, "changed": false, "failed": false, "item": "ccc"} 

TASK [debug] ****************** 
ok: [aaa] => { 
    "msg": "aaa" 
} 
ok: [bbb] => { 
    "msg": "aaa" 
} 
ok: [ccc] => { 
    "msg": "aaa" 
} 
+0

Aber du benutzt 'run_once' ... das ist vom OP verboten! – techraf

+0

Ich glaube, dass es in der anderen Weise verwendet wird :) –

+0

Ich bin nicht speziell besorgt über run_once. Ich mache mir Sorgen über das Setzen/Lesen von Variablen –

0

Die einzige * Möglichkeit zum Erstellen einer globalen Bereichsvariable besteht darin, eine speicherinterne Bestandsliste zu erstellen, die Variablen zu übergeben und Tests für diese Bestandsliste auszuführen. Es scheint jedoch nicht erforderlich, das Problem zu lösen .

Ich denke, Sie vermissen die Tatsache, dass Werte mit register Fakten gespeichert sind, d. H. Ihre Werte für jeden Host getrennt gespeichert haben.

Sie müssen die Informationen, bei denen der Befehl erfolgreich war, nicht separat erstellen und speichern, da adminPage immer für jeden Host verfügbar ist, der die Aufgabe ausgeführt hat. Und sein Wert wird für jedes Ziel separat gespeichert.

Sie wollen wahrscheinlich den folgenden Code:

--- 
- name: stackoverflow variable question 
    hosts: xyz 
    gather_facts: no 
    serial: 1 
    tasks: 
    - name: find out who has drive E 
     win_shell: dir e:\ 
     register: adminPage 
     ignore_errors: true 

    - name: run program 1 
     include_tasks: tasks/program1.yml 
     when: adminPage.rc == 0 

    - name: run program 2 
     include_tasks: tasks/program2.yml 
     when: adminPage.rc != 0 
     run_once: true 

(Mitteilung auch include directive is being deprecated)


* Es gibt einige hackish Abhilfen, die verwendet werden können, zum Beispiel den Variablenwert zu speichern zu einer Datei auf einer Kontrollmaschine und lesen Sie es mit include_vars.

+0

Diese Lösung hat die run_once. Ich suche nach einer Möglichkeit, Variablen zu setzen –

+0

Ich kommentierte das Problem: Es heißt, ich wollte nicht die Implementierung, aber wie Variablen festgelegt werden. Ich habe auch gesagt, dass ich das run_once nicht wollte. –

+0

Sie haben die Antwort bearbeitet. Es änderte sich für mich und hatte am Ende einen Link. –

Verwandte Themen