Odpowiedzi:
To naprawdę bardzo proste. Możesz zgnieść różne elementy vars_files w jedną krotkę, a Ansible automatycznie przejrzy każdy z nich, dopóki nie znajdzie pliku, który istnieje i załaduje go. Dawny:
vars_files:
- [ "vars/foo.yml", "vars/bar.yml", "vars/default.yml" ]
Według ansibl twórców The właściwy sposób na rozwiązanie tego problemu jest użycie coś takiego:
vars_files_locs: ['../path/to/file1', '../path/to/file2', ...]
- include_vars: "{{ item }}"
with_first_found: vars_files_locs
Ponadto mówią :
Powyższe poprawnie załaduje tylko pierwszy znaleziony plik i jest bardziej elastyczne niż próba zrobienia tego za pomocą
vars_files
słowa kluczowego language.
include_vars
w zadaniu da wysoki priorytet zmiennym w porównaniu do roli defaults
lubvars
Napotkałem ten problem w konfiguracji, w której musiałem utworzyć wiele środowisk wdrażania (na żywo, demo, piaskownicy) na tym samym serwerze fizycznym (tutaj niedozwolone maszyny wirtualne), a następnie skrypt do wdrożenia dowolnych repozytoriów svn
Wymagało to drzewa katalogów (opcjonalnych) plików zmiennych.yml, które połączyłyby się jeden na drugim i nie zgłaszałyby wyjątku, jeśli go brakuje
Zacznij od umożliwienia łączenia zmiennych w ansible - zwróć uwagę, że powoduje to płytkie scalanie skrótów (głębokość 1 poziomu) i niepełne rekurencyjne scalanie głębokie
[defaults]
hash_behaviour=merge ;; merge rather than replace dictionaries http://docs.ansible.com/ansible/intro_configuration.html###hash-behaviour
/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
Jest to główna logika drzewa katalogów opcjonalnych plików zmiennych.
;; 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"
Skonfiguruj zmienne domyślne dla projektu oraz różnych użytkowników i środowisk
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
ustawienia domyślne projektu
ansible_project:
node_env: development
node_port: 4200
nginx_port: 4400
domyślne dla projektu_1
ansible_project:
node_port: 4201
nginx_port: 4401
wartości domyślne dla środowiska na żywo, przesłania wartości domyślne projektu
ansible_project:
node_env: production
końcowe przesłonięcia projektu_1 w środowisku na żywo
ansible_project:
nginx_port: 80
Skonfiguruj osobne podręczniki dla każdego środowiska
- 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 }
OSTRZEŻENIE: Ponieważ wszystkie środowiska działają na jednym hoście, wszystkie podręczniki muszą być uruchamiane indywidualnie, w przeciwnym razie Ansible zepsuje próbę uruchomienia wszystkich skryptów jako pierwszy użytkownik logowania ssh i użyje zmiennych tylko dla pierwszego użytkownika. Jeśli musisz uruchomić wszystkie skrypty sekwencyjnie, użyj xargs, aby uruchomić je osobno.
find ./playbooks/*.yml | xargs -L1 time ansible-playbook
- 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 }}"
Uwaga: Testy ścieżek (plik, istnieje, ...) działają tylko z bezwzględnymi ścieżkami lub ścieżkami względem bieżącego katalogu roboczego podczas uruchamiania polecenia ansible-playbook. To jest powód, dla którego użyliśmy wyszukiwania. wyszukiwanie akceptuje ścieżki względem katalogu podręcznika i zwraca bezwzględną ścieżkę, gdy plik istnieje.
Lub w bardziej yamlowy sposób:
- 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 }}"
Oznacza to, że zamiast pisać tablicę w jednym wierszu za pomocą nawiasów kwadratowych, na przykład:
['path/to/file1', 'path/to/file2', ...]
Użyj yamlowego sposobu zapisywania wartości tablic w wielu wierszach, takich jak:
- path/to/file1
- path/to/file2
Jak wspomniano, szuka pliku vars o nazwie {{ ansible_hostname }}.yml
, a jeśli nie istnieje, używadefault.yml
Nowa odpowiedź oparta na najnowszych wersjach Ansible - w zasadzie powinieneś użyć with_first_found
wraz z, skip: true
aby pominąć zadanie, jeśli nie znaleziono pliku.
- name: Include vars file if one exists meeting our condition.
include_vars: "{{ item }}"
with_first_found:
- files:
- vars/{{ variable_here }}.yml
skip: true
To sprawia, że nie musisz mieć pliku rezerwowego na tej liście.
Zobacz powiązane: /programming//a/39544405/100134