Замініть розміщення змінної програми відтворення Ansible з командного рядка


110

Це фрагмент ігрової книги, який я використовую ( server.yml):

- name: Determine Remote User
  hosts: web
  gather_facts: false
  roles:
    - { role: remote-user, tags: [remote-user, always] }

Мій файл хостів має різні групи серверів, наприклад

[web]
x.x.x.x

[droplets]
x.x.x.x

Тепер я хочу , щоб виконати ansible-playbook -i hosts/<env> server.ymlі перевизначити hosts: webз server.ymlзапустити цей збірник п'єс для [droplets].

Чи можу я просто переосмислити як одноразову річ, не редагуючи server.ymlбезпосередньо?

Дякую.

Відповіді:


128

Я не думаю, що Ansible надає цю функцію, якою вона повинна бути. Ось що ви можете зробити:

hosts: "{{ variable_host | default('web') }}"

і ви можете переходити variable_hostз командного рядка або з файлу vars, наприклад:

ansible-playbook server.yml --extra-vars "variable_host=newtarget(s)"

3
Потрібна невелика корекція. Це повинно бутиhosts: "{{ variable_host | default('web')}}"
SPM

16
Ось зауваження, яке, на мою думку, завершить відповідь для чутливих новачків, які шукають це рішення: Приклад:ansible-playbook server.yml --extra-vars "variable_host=newtarget(s)"
Frobbit

1
Коли (тобто в якому порядку) робить анзібль розбору змінних Змінні в , як group_vars/allвидається , бути розібраний після по hosts:лінії п'єс. Однак змінні в vars:і змінні в vars_files:синтаксичному рівні аналізуються перед hosts:рядком? ПРИМІТКА Я не прошу про перевагу.
Феліпе Альварес

2
Ви також можете використовувати -eзамість цього --extra-vars.
іменник

Подивіться інші відповіді для отримання більш детальної інформації
Anand Varkey Philips

63

Для всіх, хто може прийти шукати рішення.
Слухати книгу

- hosts: '{{ host }}'
  tasks:
  - debug: msg="Host is {{ ansible_fqdn }}"

Інвентар

[web]
x.x.x.x

[droplets]
x.x.x.x

Команда: ansible-playbook deplyment.yml -i hosts --extra-vars "host=droplets" Отже, ви можете вказати назву групи в додатковій варі


2
Зверніть увагу, будьте обережні з назви вар. Я тестував це, використовуючи play_hostsі не отримуючи очікуваних результатів, бо забув, що play_hostsце внутрішня відповідна вар для всіх хостів у поточній грі.
Райан Фішер

Я припускаю, що за замовчуванням слід встановити відповідь вище.
каказ

19

Це трохи пізно, але я думаю, ви могли б скористатися --limit or -l команду для обмеження шаблону на конкретніших хостах. (версія 2.3.2.0)

Можна було - hosts: all (or group) tasks: - some_task

а потім ansible-playbook playbook.yml -l some_more_strict_host_or_pattern і використовуйте --list-hostsпрапор, щоб побачити, на яких хостах буде застосована ця конфігурація.


3
Я дуже новачок у службовій відповідальності, але вважаю це дуже ефективним рішенням, набагато більш компактним, ніж інші. Чому це було знято?
Алессандро Дентелла

16
Це небезпечно. Якщо хтось забуде на limitсписок хостів, на які постраждали, іграшка може завдати великої шкоди.
Олександр Щеблікін

3
Я вважаю, що використовувати так --extra-vars "variable_host=newtarget(s)"само, як прийняте рішення, настільки ж небезпечно і складніше рішення. Він використовує хости за замовчуванням, webякі можна застосувати і тут all. Ви можете використовувати сувору групу хостів за замовчуванням, щоб уникнути помилки та використовувати --list-hostsпрапор, щоб чітко розуміти, на яких хостів ви впливаєте.
Джонатан Хамель

3
Рішення з додатковими параметрами дозволяє вказати порожню групу (або неіснуючу) як значення за замовчуванням. Тож якщо ви забудете надати змінну за допомогою командного рядка, нічого поганого не станеться. Рішення з опцією "--limit" є більш небезпечним, оскільки програвач не може використовувати порожню групу як значення за замовчуванням для хостів. Варіант "--llmit" застосовується до значень хостів, отже, він буде застосований до порожніх груп і забезпечить порожній результат. Таким чином, ВИ ВЖЕ використовувати "все" або інший не порожній хост як значення за замовчуванням. А коли-небудь ви забудете надати аргумент "--limit", і програму буде застосовано до всіх хостів.
Григорій Петухов

4
Це має поєднуватися з відповіддю @ TmTron, щоб зрозуміти випадок, коли абонент не в --limitзмозі надати (інакше це вплине на всіх можливих хостів, що може бути не такою поведінкою, яку ви хочете)
ncoghlan

14

Ми використовуємо просту невдалу задачу, щоб змусити користувача вказати відповідь опцію граничного рівня , щоб ми не виконувались на всіх хостах за замовчуванням / аварією.

Найпростіший спосіб я знайшов це:

---
- name: Force limit
  # 'all' is okay here, because the fail task will force the user to specify a limit on the command line, using -l or --limit
  hosts: 'all'

  tasks:
  - name: checking limit arg
    fail:
      msg: "you must use -l or --limit - when you really want to use all hosts, use -l 'all'"
    when: ansible_limit is not defined
    run_once: true

Тепер ми повинні використовувати -l(= --limitваріант) під час запуску ігрової книги, наприклад

ansible-playbook playbook.yml -l www.example.com

Обмеження опції, документи :

Обмеження до одного або декількох хостів Це потрібно, коли потрібно запустити програму "Книга" проти групи хостів, але лише проти одного або декількох членів цієї групи.

Обмежити до одного хоста

ansible-playbook playbooks/PLAYBOOK_NAME.yml --limit "host1"

Обмежити до кількох хостів

ansible-playbook playbooks/PLAYBOOK_NAME.yml --limit "host1,host2"

Негативний ліміт.
ПРИМІТКА: Одиничні лапки ОБОВ'ЯЗКОВО використовуватися для запобігання удару між інтерполяцією.

ansible-playbook playbooks/PLAYBOOK_NAME.yml --limit 'all:!host1'

Обмежити для приймаючої групи

ansible-playbook playbooks/PLAYBOOK_NAME.yml --limit 'group1'


7

Я використовую інший підхід, який не потребує інвентаризації, і працює з цією простою командою:

ansible-playbook site.yml -e working_host=myhost

Для цього вам потрібна книга з двома п’єсами:

  • Перша гра запускається на localhost і додає хост (із заданої змінної) у відому групу в запасному інвентарі
  • друга відома група проходить на цій відомій групі

Робочий приклад (скопіюйте його та запустіть його за допомогою попередньої команди):

- hosts: localhost
  connection: local
  tasks:
  - add_host:
      name: "{{ working_host }}"
      groups: working_group
    changed_when: false

- hosts: working_group
  gather_facts: false
  tasks:
  - debug:
      msg: "I'm on {{ ansible_host }}"

Я використовую ansible 2.4.3 та 2.3.3


7

Я змінив моє значення за замовчуванням на відсутність хоста і маю чек, щоб його зловити. Таким чином, користувач або крон змушений надавати єдиний хост або групу тощо. Мені подобається логіка з коментаря від @wallydrag. Theempty_group містить хостів в інвентарі.

- господарі: "{{varia_host | default ('empty_group')}}"

Потім додайте перевірку в завдання:

   завдання:
   - ім'я: Fail script, якщо необхідний параметр varia_host відсутній
     невдача:
       msg: "Вам потрібно додати --extra-vars = 'varia_host ='"
     коли: (змінний_хост не визначений) або (змінний_хост == "")

5

Щойно натрапив на цей гугл для пошуку рішення. Власне, у відповіді 2.5. Ви можете вказати свій інвентарний файл за допомогою --inventoryтакого:ansible --inventory configs/hosts --list-hosts all


Я вважаю, що це найправильніша відповідь у Рік Господа нашого 2019. Із Відповідь 2,8,4-х:-i INVENTORY, --inventory=INVENTORY, --inventory-file=INVENTORY specify inventory host path or comma separated host list. --inventory-file is deprecated
pyansharp

3

Якщо ви хочете виконати завдання, пов’язане з хостом, але на іншому хості, спробуйте delegate_to .

У вашому випадку вам слід делегувати своєму локальному хосту (відповідальному майстру) та ansible-playbookкоманді виклику


2

Я використовую ansible 2.5 (саме 2.5.3), і здається, що файл vars завантажується до того, як буде виконаний парам хостів. Таким чином, ви можете встановити хост у файл vars.yml і просто записати hosts: {{ host_var }}у свою програму

Наприклад, у моєму playbook.yml:

---
- hosts: "{{ host_name }}"
  become: yes
  vars_files:
    - vars/project.yml
  tasks:
    ... 

І всередині vars / project.yml:

---

# general
host_name: your-fancy-host-name

0

Ось круте рішення, яке я придумав, щоб безпечно вказати хостів через --limitопцію. У цьому прикладі відтворення закінчиться, якщо програму було виконано без жодних хостів, вказаних через --limitопцію.

Це було перевірено на версії Ansible 2.7.10

---
- name: Playbook will fail if hosts not specified via --limit option.
  # Hosts must be set via limit. 
  hosts: "{{ play_hosts }}"
  connection: local
  gather_facts: false
  tasks:
  - set_fact:
      inventory_hosts: []
  - set_fact:
      inventory_hosts: "{{inventory_hosts + [item]}}"
    with_items: "{{hostvars.keys()|list}}"

  - meta: end_play
    when: "(play_hosts|length) == (inventory_hosts|length)"

  - debug:
      msg: "About to execute tasks/roles for {{inventory_hostname}}"

0

Іншим рішенням є використання спеціальної змінної, ansible_limitяка є вмістом параметра --limitCLI для поточного виконання Ansible.

- hosts: "{{ ansible_limit | default(omit) }}"

Якщо --limitпараметр опущено, то Ansible видає попередження, але нічого не робить, оскільки жоден хост не відповідає.

[WARNING]: Could not match supplied host pattern, ignoring: None

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