Ansible: Kann ich vars_files verwenden, wenn einige Dateien nicht existieren?

17

Das ist der Teil:

vars_files:
  - vars/vars.default.yml
  - vars/vars.yml

Wenn keine Datei vars/vars.ymlvorhanden ist, liegt ein Fehler vor.

ERROR: file could not read: /.../vars/vars.yml

Wie kann ich zusätzliche Variablen nur dann aus dieser Datei laden, wenn sie vorhanden sind? (ohne fehler)

Sergey
quelle

Antworten:

27

Es ist wirklich ganz einfach. Sie können Ihre verschiedenen vars_files-Elemente zu einem einzigen Tupel zusammenfassen. Ansible durchsucht jedes Tupel automatisch, bis es eine vorhandene Datei findet und lädt. Ex:

vars_files:
  - [ "vars/foo.yml", "vars/bar.yml", "vars/default.yml" ]
Garrett
quelle
4
Laut Ansible-Entwicklern lädt diese Lösung alle Dateien, nicht nur die zuerst gefundenen.
Tjanez
10

Laut Ansible-Entwicklern besteht der richtige Weg, dies zu lösen, darin, Folgendes zu verwenden:

vars_files_locs: ['../path/to/file1', '../path/to/file2', ...]

- include_vars: "{{ item }}"
  with_first_found: vars_files_locs

Außerdem sagen sie :

Mit dem obigen Befehl wird nur die erste gefundene Datei ordnungsgemäß geladen. Dies ist flexibler, als dies über das vars_filesSchlüsselwort language zu tun .

tjanez
quelle
"nur die erste Datei gefunden" - die Idee war, einige Variablen neu zu definieren, nicht alle
Sergey
@Sergey, wenn du nochmal deine Frage liest, sehe ich, dass das, was du wolltest, ein bisschen anders ist. Vielen Dank für den Hinweis. Ich werde die Antwort so lassen, wie sie ist, wenn jemand anderes sie nützlich findet.
Dienstag,
1
mit der Ausnahme, dass include_varsin der Aufgabe wird eine hohe Priorität von Variablen im Vergleich zu Rolle defaultsoder gebenvars
Alex F
2

Dieses Problem trat in einem Setup auf, in dem ich mehrere Bereitstellungsumgebungen (Live, Demo, Sandbox) auf demselben physischen Server erstellen musste (hier sind keine virtuellen Maschinen zulässig), und dann ein Skript zum Bereitstellen beliebiger SVN-Repos

Dies erforderte einen Verzeichnisbaum von (optionalen) variablen.yml-Dateien, die übereinander zusammengeführt wurden und keine Ausnahme auslösten, falls eine fehlte

Beginnen Sie, indem Sie das Zusammenführen von Variablen in Ansible aktivieren. Beachten Sie, dass dies nur eine flache Hash-Zusammenführung (1 Ebene tief) und keine vollständig rekursive, tiefe Zusammenführung bewirkt

ansible.cfg

[defaults]
hash_behaviour=merge ;; merge rather than replace dictionaries http://docs.ansible.com/ansible/intro_configuration.html###hash-behaviour

Ansible Verzeichnislayout

/group_vars
└── all.yml

/playbooks
├── boostrap.yml
├── demo.yml
├── live.yml
└── sandbox.yml

/roles/deploy/
├── files
├── tasks
│   ├── includes.yml
│   ├── main.yml
└── vars
    ├── main.yml
    ├── project_1.yml
    ├── project_2.yml
    ├── demo
    │   ├── project_1.yml
    │   ├── project_2.yml   
    │   └── main.yml
    ├── live
    │   ├── project_1.yml
    │   ├── project_2.yml   
    │   └── main.yml
    └── sandbox
        ├── project_1.yml
        ├── project_2.yml   
        └── main.yml

rolls / deploy / tasks / includes.yml

Dies ist die Hauptlogik für einen Verzeichnisbaum optionaler Variablendateien.

;; imports in this order:
;; - /roles/deploy/vars/main.yml
;; - /roles/deploy/vars/{{ project_name }}.yml
;; - /roles/deploy/vars/{{ project_name }}/main.yml
;; - /roles/deploy/vars/{{ project_name }}/{{ project_env }}.yml
- include_vars:
    dir: 'vars'
    files_matching: "{{ item }}"
    depth: 1
  with_items:
    - "main.yml"
    - "{{ project_name }}.yml"

- include_vars:
    dir: 'vars/{{ env_name }}'
    files_matching: "{{ item }}"
    depth: 1
  with_items:
    - "main.yml"
    - "{{ project_name }}.yml"

group_vars / all.yml

Konfigurieren Sie Standardvariablen für das Projekt und verschiedene Benutzer und Umgebungen

project_users:
    bootstrap:
        env:   bootstrap
        user:  ansible
        group: ansible
        mode:  755
        root:  /cs/ansible/
        home:  /cs/ansible/home/ansible/
        directories:
            - /cs/ansible/
            - /cs/ansible/home/

    live:
        env:   live
        user:  ansible-live
        group: ansible
        mode:  755
        root:  /cs/ansible/live/
        home:  /cs/ansible/home/ansible-live/

    demo:
        env:   demo
        user:  ansible-demo
        group: ansible
        mode:  755
        root:  /cs/ansible/demo/
        home:  /cs/ansible/home/ansible-demo/

    sandbox:
        env:   sandbox
        user:  ansible-sandbox
        group: ansible
        mode:  755
        root:  /cs/ansible/sandbox/
        home:  /cs/ansible/home/ansible-sandbox/    

project_env:  bootstrap
project_user: "{{ ansible_users[project_env] }}" ;; this will be retroactively updated if project_env is redefined later

role / deploy / vars / main.yml

Projektstandards

ansible_project:
  node_env:   development
  node_port:  4200
  nginx_port: 4400

role / deploy / vars / project_1.yml

Standardeinstellungen für project_1

ansible_project:
  node_port:  4201
  nginx_port: 4401

role / deploy / vars / live / main.yml

Standardeinstellungen für die Live-Umgebung überschreiben die Standardeinstellungen des Projekts

ansible_project:
  node_env: production

role / deploy / vars / live / project_1.yml

endgültige Überschreibungen für project_1 in der Live-Umgebung

ansible_project:
  nginx_port: 80

Spielbücher / demo.yml

Konfigurieren Sie separate Playbooks für jede Umgebung

- hosts: shared_server
  remote_user: ansible-demo
  vars:
    project_env: demo
  pre_tasks:
    - debug: "msg='{{ facter_gid }}@{{ facter_fqdn }} ({{ server_pseudonym }})'"
    - debug: var=project_ssh_user
  roles:
    - { role: deploy, project_name: project_1 }

WARNUNG: Da sich alle Umgebungen auf einem einzigen Host befinden, müssen alle Playbooks einzeln ausgeführt werden. Andernfalls versucht Ansible, alle Skripte als erster SSH-Anmeldebenutzer auszuführen und verwendet nur die Variablen für den ersten Benutzer. Wenn Sie alle Skripten nacheinander ausführen müssen, verwenden Sie xargs, um sie jeweils als separate Befehle auszuführen.

find ./playbooks/*.yml | xargs -L1 time ansible-playbook
James McGuigan
quelle
1
- hosts: all
  vars_files: vars/vars.default.yml
  vars:
    optional_vars_file: "{{ lookup('first_found', 'vars/vars.yml', errors='ignore') }}"
  tasks:
  - when: optional_vars_file is file
    include_vars: "{{ optional_vars_file }}"

Hinweis: Die Pfadtests (is file, is exists, ...) funktionieren nur mit absoluten Pfaden oder Pfaden relativ zum aktuellen Arbeitsverzeichnis, wenn der Befehl ansible-playbook ausgeführt wird. Dies ist der Grund, warum wir die Suche verwendet haben. Die Suche akzeptiert Pfade relativ zum Playbook-Verzeichnis und gibt den absoluten Pfad zurück, wenn die Datei vorhanden ist.

Ejez
quelle
0

Oder auf eine yaml Art:

- hosts: webservers
  vars:
    paths_to_vars_files:
      - vars/{{ ansible_hostname }}.yml
      - vars/default.yml
  tasks:
    - include_vars: "{{ item }}"
      with_first_found: "{{ paths_to_vars_files }}"

Das heißt, anstatt ein Array in eine Zeile mit eckigen Klammern zu schreiben, wie:

['path/to/file1', 'path/to/file2', ...]

Verwenden Sie die Methode yaml, um Array-Werte in mehrere Zeilen zu schreiben, z.

- path/to/file1
- path/to/file2

Wie bereits erwähnt, wird nach einer vars-Datei mit dem Namen gesucht {{ ansible_hostname }}.yml, und falls sie nicht vorhanden ist, wird sie verwendetdefault.yml

Donn Lee
quelle
Diese Antwort verwendet den gleichen Code wie diese, außer dass andere Daten verwendet werden. Nämlich {{ ansible_hostname }}.ymlDateiname statt ../path/to/file1. Was ist der Sinn? Man kann eine unbegrenzte Anzahl von Eingabedateinamen hinzufügen.
Techraf
@techraf: Ok, ich habe einige Erläuterungen / Erläuterungen hinzugefügt, warum eine neue Antwort eingereicht wurde. Das liegt daran, dass Serverfehler-Kommentare keine mehrzeiligen Codeausschnitte unterstützen, und ich habe nur darauf hingewiesen, dass Yaml-Arrays häufig (vorzugsweise?) In mehreren Zeilen geschrieben werden. Ich wäre auch in Ordnung, wenn die frühere Antwort bearbeitet und das mehrzeilige Array-Format angezeigt würde, da ich das öfter sehe. Dann kann meine Antwort gelöscht werden.
Donn Lee
Beide Notationen werden in Ansible-Dokumenten in einem Kapitel über YAML-Grundlagen angegeben . Die Tatsache, dass Sie eines öfter als das andere sehen, macht dies noch nicht zu einer neuen Antwort.
Techraf
0

Verschiedene Teile zusammensetzen ... include_vars mit einer when-Klausel, die wahr ist, wenn die Datei existiert. dh

vars:
  file_to_include: /path/to/file
tasks:
  - include_vars: "{{ file_to_include }}"
    when: file_to_include is exists
pedz
quelle
0

Neue Antwort basierend auf den neuesten Ansible-Versionen - im Grunde sollten Sie diese verwenden with_first_found, skip: trueum die Aufgabe zu überspringen, wenn keine Datei gefunden wird.

- name: Include vars file if one exists meeting our condition.
  include_vars: "{{ item }}"
  with_first_found:
    - files:
        - vars/{{ variable_here }}.yml
      skip: true

Dies macht es so, dass Sie keine Fallback-VARS-Datei in dieser Liste haben müssen.

Siehe verwandte: /programming//a/39544405/100134

Geerlingguy
quelle