Câu trả lời:
Nó thực sự khá đơn giản. Bạn có thể nén các mục vars_files khác nhau của mình vào một tuple duy nhất và Ansible sẽ tự động đi qua từng mục cho đến khi tìm thấy một tệp tồn tại và tải nó. Ví dụ:
vars_files:
- [ "vars/foo.yml", "vars/bar.yml", "vars/default.yml" ]
Theo các nhà phát triển Ansible , cách thích hợp để giải quyết vấn đề này là sử dụng một cái gì đó như:
vars_files_locs: ['../path/to/file1', '../path/to/file2', ...]
- include_vars: "{{ item }}"
with_first_found: vars_files_locs
Hơn nữa, họ nói :
Ở trên sẽ chỉ tải đúng tệp đầu tiên được tìm thấy và linh hoạt hơn so với cố gắng thực hiện việc này thông qua
vars_files
từ khóa ngôn ngữ.
include_vars
trong nhiệm vụ sẽ có độ ưu tiên cao của các biến so với vai trò defaults
hoặcvars
Tôi đã gặp sự cố này trong một thiết lập khi tôi cần tạo nhiều môi trường triển khai (trực tiếp, bản demo, hộp cát) cho cùng một máy chủ vật lý (không cho phép máy ảo ở đây), và sau đó một tập lệnh để triển khai repos svn tùy ý
Điều này đòi hỏi một cây thư mục gồm các tệp biến.yml (tùy chọn), sẽ hợp nhất ontop của nhau và không ném ngoại lệ nếu có bất kỳ trường hợp nào bị thiếu
Bắt đầu bằng cách cho phép hợp nhất biến trong ansible - lưu ý rằng điều này không hợp nhất băm nông (sâu 1 cấp) và không hợp nhất đệ quy sâu
[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
Đây là logic chính cho cây thư mục gồm các tệp biến tùy chọn.
;; 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"
Cấu hình các biến mặc định cho dự án và nhiều người dùng và môi trường khác nhau
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
mặc định dự án
ansible_project:
node_env: development
node_port: 4200
nginx_port: 4400
mặc định cho dự án_1
ansible_project:
node_port: 4201
nginx_port: 4401
mặc định cho môi trường sống, ghi đè mặc định của dự án
ansible_project:
node_env: production
ghi đè cuối cùng cho dự án_1 trong môi trường sống
ansible_project:
nginx_port: 80
Cấu hình Playbook riêng cho từng môi trường
- 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 }
CẢNH BÁO: Bởi vì tất cả các môi trường sống trên một máy chủ duy nhất, tất cả các playbook phải được chạy riêng lẻ, nếu không Ansible sẽ cố gắng chạy tất cả các tập lệnh với tư cách là người dùng đăng nhập ssh đầu tiên và chỉ sử dụng các biến cho người dùng đầu tiên. Nếu bạn cần chạy tất cả các tập lệnh một cách tuần tự, thì hãy sử dụng xargs để chạy từng tập lệnh dưới dạng các lệnh riêng biệt.
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 }}"
Lưu ý: Các kiểm tra đường dẫn (là tệp, tồn tại, ...) chỉ hoạt động với các đường dẫn hoặc đường dẫn tuyệt đối liên quan đến thư mục làm việc hiện tại khi chạy lệnh ansible-playbook. Đây là lý do chúng tôi sử dụng tra cứu. tra cứu chấp nhận các đường dẫn liên quan đến thư mục playbook và trả về đường dẫn tuyệt đối khi tệp tồn tại.
Hoặc theo một cách yaml hơn:
- 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 }}"
Đó là, thay vì viết một mảng trên một dòng bằng dấu ngoặc vuông, như:
['path/to/file1', 'path/to/file2', ...]
Sử dụng cách yaml để viết các giá trị mảng trên nhiều dòng, như:
- path/to/file1
- path/to/file2
Như đã đề cập, điều này tìm kiếm một tệp vars có tên {{ ansible_hostname }}.yml
và nếu nó không tồn tại sử dụngdefault.yml
Câu trả lời mới dựa trên các phiên bản Ansible mới nhất về cơ bản, bạn nên sử dụng with_first_found
, cùng với skip: true
việc bỏ qua nhiệm vụ nếu không tìm thấy tệp nào.
- name: Include vars file if one exists meeting our condition.
include_vars: "{{ item }}"
with_first_found:
- files:
- vars/{{ variable_here }}.yml
skip: true
Điều này làm cho nó để bạn không phải có một tệp vars dự phòng trong danh sách đó.
Xem liên quan: /programming//a/39544405/100134