Jawaban:
Cukup sederhana kok. Anda dapat memeras item vars_files yang berbeda ke dalam satu tuple dan Ansible akan secara otomatis melewati masing-masing item hingga menemukan file yang ada dan memuatnya. Ex:
vars_files:
- [ "vars/foo.yml", "vars/bar.yml", "vars/default.yml" ]
Menurut pengembang Ansible , cara yang tepat untuk menyelesaikan ini adalah dengan menggunakan sesuatu seperti:
vars_files_locs: ['../path/to/file1', '../path/to/file2', ...]
- include_vars: "{{ item }}"
with_first_found: vars_files_locs
Lebih jauh, mereka mengatakan :
Di atas hanya akan memuat file pertama yang ditemukan dengan benar, dan lebih fleksibel daripada mencoba melakukan ini melalui
vars_files
kata kunci bahasa.
include_vars
dalam tugas akan memberikan prioritas yang lebih tinggi dari variabel dibandingkan dengan peran defaults
atauvars
Saya mengalami masalah ini dalam pengaturan di mana saya perlu membuat beberapa lingkungan penempatan (hidup, demo, kotak pasir) ke server fisik yang sama (tidak diizinkan mesin virtual di sini), dan kemudian skrip untuk menggunakan repo svn sewenang-wenang
Ini membutuhkan susunan direktori dari file variabel.yml (opsional), yang akan menggabungkan satu sama lain dan tidak melempar pengecualian jika ada di mana ada yang hilang
Mulailah dengan mengaktifkan penggabungan variabel dalam kemungkinan - perhatikan bahwa penggabungan hash dangkal ini (kedalaman 1 level) dan penggabungan mendalam tidak sepenuhnya rekursif
[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
Ini adalah logika utama untuk pohon direktori dari file variabel opsional.
;; 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"
Konfigurasikan variabel default untuk proyek dan berbagai pengguna dan lingkungan
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
standar proyek
ansible_project:
node_env: development
node_port: 4200
nginx_port: 4400
default untuk project_1
ansible_project:
node_port: 4201
nginx_port: 4401
default untuk lingkungan hidup, menimpa default proyek
ansible_project:
node_env: production
penggantian akhir untuk project_1 di lingkungan langsung
ansible_project:
nginx_port: 80
Konfigurasikan buku pedoman terpisah untuk setiap lingkungan
- 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 }
PERINGATAN: Karena semua lingkungan hidup pada satu host, semua playbook harus dijalankan secara terpisah, jika tidak, Ansible akan mencoba menjalankan semua skrip sebagai pengguna login ssh pertama dan hanya menggunakan variabel untuk pengguna pertama. Jika Anda perlu menjalankan semua skrip secara berurutan, maka gunakan xargs untuk menjalankannya masing-masing sebagai perintah terpisah.
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 }}"
Catatan: Tes jalur (adalah file, ada, ...) hanya berfungsi dengan jalur absolut atau jalur relatif ke direktori kerja saat ini ketika menjalankan perintah playbook yang mungkin. Ini adalah alasan kami menggunakan pencarian. pencarian menerima jalur relatif ke direktori playbook dan mengembalikan jalur absolut ketika file ada.
Atau dengan cara yang lebih yaml:
- 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 }}"
Artinya, alih-alih menulis array pada satu baris dengan tanda kurung, seperti:
['path/to/file1', 'path/to/file2', ...]
Gunakan cara yaml untuk menulis nilai array pada banyak baris, seperti:
- path/to/file1
- path/to/file2
Seperti disebutkan ini mencari file vars bernama {{ ansible_hostname }}.yml
, dan jika tidak ada gunanyadefault.yml
Jawaban baru berdasarkan pada versi Ansible terbaru — pada dasarnya, Anda harus menggunakan with_first_found
, bersama skip: true
untuk melewati tugas jika tidak ada file yang ditemukan.
- name: Include vars file if one exists meeting our condition.
include_vars: "{{ item }}"
with_first_found:
- files:
- vars/{{ variable_here }}.yml
skip: true
Ini membuatnya jadi Anda tidak perlu memiliki file vars cadangan dalam daftar itu.
Lihat yang terkait: /programming//a/39544405/100134