Відповідь: Чи можна використовувати vars_files, коли деякі файли не існують


17

Ось та частина:

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

Якщо файл vars/vars.ymlне існує - ось помилка.

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

Як я можу завантажити додаткові змінні з цього файлу, лише якщо він існує? (без помилок)

Відповіді:


27

Насправді це дуже просто. Ви можете розрізати різні елементи vars_files в один кордон, і Ansible автоматично проходитиме кожен з них, поки не знайде файл, який існує, і не завантажить його. Наприклад:

vars_files:
  - [ "vars/foo.yml", "vars/bar.yml", "vars/default.yml" ]

4
За словами розробників Ansible , це рішення завантажить усі файли, а не лише перший знайдений.
tjanez

10

За словами розробників Ansible , правильним способом вирішити це є використання чогось такого типу:

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

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

Крім того, вони кажуть :

Вищенаведене буде правильно завантажувати лише перший знайдений файл і є більш гнучким, ніж намагатися зробити це за допомогою vars_filesмовного ключового слова.


"знайдено лише перший файл" - ідея полягала в тому, щоб переосмислити деякі змінні, не всі з них
Сергій

@Sergey, читаючи ще раз своє запитання, я бачу, що те, що ти хотів, трохи інше. Дякуємо, що вказали на це. Я залишу відповідь так, як якщо хтось вважає її корисною.
Тянь

1
за винятком того, що include_varsв завданні буде надано високий пріоритет змінних порівняно з роллю defaultsабоvars
Алекс F

2

Я зіткнувся з цією проблемою в налаштуваннях, де мені потрібно було створити кілька середовищ розгортання (в прямому ефірі, демо, пісочниці) на одному фізичному сервері (тут не дозволено віртуальних машин), а потім сценарій для розгортання довільних svn repos

Для цього потрібне дерево каталогів (необов'язково) файлів varia.yml, яке б злилося на вершині один одного і не викидало виняток, якщо таке взагалі відсутнє

Почніть з включення змінного злиття в ansible - зауважте, що це неглибоке злиття хешу (глибина 1 рівня) і не повністю рекурсивне глибоке злиття

ansible.cfg

[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

ролі / розгортання / завдання / включає.імл

Це основна логіка дерева директорій необов'язкових змінних файлів.

;; 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

Налаштування змінних за замовчуванням для проекту та різних користувачів та середовищ

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

ролі / розгорнути / vars / main.yml

за замовчуванням проекту

ansible_project:
  node_env:   development
  node_port:  4200
  nginx_port: 4400

ролі / розгорнути / vars / project_1.yml

за замовчуванням для проекту_1

ansible_project:
  node_port:  4201
  nginx_port: 4401

ролі / розгорнути / vars / live / main.yml

за замовчуванням для живого середовища, замінює параметри за замовчуванням для проекту

ansible_project:
  node_env: production

ролі / розгорнути / vars / live / project_1.yml

остаточні зміни для проекту_1 у прямому середовищі

ansible_project:
  nginx_port: 80

ігрові книги / demo.yml

Налаштуйте окремі ігрові книги для кожного середовища

- 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 }

ПОПЕРЕДЖЕННЯ: Оскільки всі середовища живуть на одному хості, всі ігрові книги повинні запускатися окремо, інакше Ansible спробує запустити всі сценарії як перший користувач ssh для входу та використовуватиме змінні лише для першого користувача. Якщо вам потрібно запустити всі сценарії послідовно, використовуйте xargs, щоб запустити їх кожен як окремі команди.

find ./playbooks/*.yml | xargs -L1 time ansible-playbook

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 }}"

Примітка. Тестові контури (файлові, існують, ...) працюють лише з абсолютними шляхами або шляхами відносно поточного робочого каталогу під час виконання команди ansible-playbook. З цієї причини ми використовували пошук. пошук приймає шляхи відносно каталогу ігрової книги та повертає абсолютний шлях, коли файл існує.


0

Або більш ямл-способом:

- 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 }}"

Тобто замість того, щоб записувати масив на одному рядку з квадратними дужками, наприклад:

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

Використовуйте yaml спосіб запису значень масиву в кілька рядків, наприклад:

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

Як вже згадувалося, це шукає файл з назвою vars {{ ansible_hostname }}.yml, а якщо він не існує, використовуєтьсяdefault.yml


Ця відповідь використовує той самий код, що і цей, за винятком того, що він використовує інші дані. А саме {{ ansible_hostname }}.ymlім'я файлу замість ../path/to/file1. У чому справа? Можна додати необмежену кількість імен вхідних файлів.
techraf

@techraf: Гаразд, я додав деякі пояснення / посилення щодо того, чому була подана нова відповідь. Це тому, що коментарі на сервері за замовчуванням не підтримують багаторядкові фрагменти коду, і я просто зазначав, що ямлові масиви часто (бажано?) Записуються в декількох рядках. Я також був би добре, якщо попередня відповідь була відредагована і показано формат багаторядкового масиву, як я це бачу частіше. Тоді мою відповідь можна буде видалити.
Донн Лі

Обидві позначення вказані в документах Ansible в главі Основи YAML . Той факт, що ви бачите одного частіше за інших, ще не робить це новою відповіддю.
techraf

0

Складання різних фрагментів разом ... include_vars з пропозицією, коли є правдою, коли файл існує. тобто

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

0

Нова відповідь, заснована на останніх версіях Ansible - в основному, ви повинні використовувати with_first_found, а також skip: trueпропустити завдання, якщо файл не знайдений.

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

Це робить його таким, що вам не доведеться мати резервний файл vars у цьому списку.

Дивіться пов’язані з цим: /programming//a/39544405/100134

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.