Есть ли способ принудительно выполнить команды ansible-playbook
, ansible-variable
и т. д. С опцией --limit
(иначе отрицать это)?
Я обнаружил, что в кластере он может легко запускать playbook для всех узлов, если вы по ошибке запускаете его без ограничений, я бы хотел предотвратить его от доступных пользователей.
Это прямо противоположно той задаче, которую я недавно решил. Моей целью было обнаружить наличие --limit
и пропустить некоторые игры.
https://medium.com/opsops/how-to-detect-if-ansible-is-run-with-limit-5ddb8d3bd145
В вашем случае вы можете проверить это в игре и потерпеть неудачу, если он "полный":
- hosts: all
gather_facts: no
tasks:
- set_fact:
full_run: '{{play_hosts == groups.all}}'
- fail:
msg: 'Use --limit, Luke!'
when: full_run
Вы, конечно, можете использовать другую группу вместо all
(измените ее в строках hosts
и set_fact
).
Используйте переменную ansible_limit
(добавлена в ansible 2.5). Вы можете проверить это так:
tasks:
- fail:
msg: "you must use -l or --limit"
when: ansible_limit is not defined
run_once: true
добавление строки - name: Check limit
над fail:
позволяет избежать задачи «сбой», которая немного менее пугает случайного наблюдателя. Не забудьте удалить -
из - fail:
, если вы решите это сделать.
Я сделал это в задаче:
$ cat exit-if-no-limit.yml
---
- name: Verifying that a limit is set
fail:
msg: 'This playbook cannot be run with no limit'
run_once: true
when: ansible_limit is not defined
- debug:
msg: Limit is {{ ansible_limit }}, let's continue
run_once: true
when: ansible_limit is defined
Которые я включаю в свои playbooks, когда мне нужно запретить их запуск на всех хостах:
- include_role:
name: myrole
tasks_from: "{{ item }}.yml"
loop:
- exit-if-no-limit
- something
- something_else
При необходимости легко использовать повторно. Это работает так:
TASK [myrole: Verifying that a limit is set]
fatal: [ahost]: FAILED! => {"changed": false, "msg": "This playbook cannot be run with no limit"}
или
TASK [myrole: debug]
ok: [anotherhost] => {
"msg": "Limit is anotherhost, let's continue"
}
Это можно сделать с помощью модуль утверждения.
Мне нравится делать это в отдельной игре, в начале игры, с отключенным сбором фактов. Таким образом, playbook мгновенно выйдет из строя, если предел не указан.
- hosts: all
gather_facts: no
tasks:
- name: assert limit
run_once: yes
assert:
that:
- 'ansible_limit is defined'
fail_msg: Playbook must be run with a limit (normally staging or production)
quiet: yes
Когда лимит не установлен, вы получаете:
$ ansible-playbook site.yaml
PLAY [all] *********************************************************************
TASK [assert limit] ************************************************************
fatal: [host1.example.net]: FAILED! => {"assertion": "ansible_limit is defined", "changed": false, "evaluated_to": false, "msg": "Playbook must be run with a limit (normally staging or production)"}
NO MORE HOSTS LEFT *************************************************************
PLAY RECAP *********************************************************************
host1.example.com : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
А когда установлен лимит, вы получаете:
$ ansible-playbook -l staging site.yaml
PLAY [all] *********************************************************************
TASK [assert limit] ************************************************************
ok: [host1.example.com]
PLAY [all] *********************************************************************
[... etc ...]
Функционально это очень похоже на использование модуля fail
, защищенного when
. Разница в том, что сама задача assert
отвечает за проверку утверждений, поэтому, если утверждения проходят, задача завершается успешно. При использовании модуля fail
, если условие when
не выполняется, задача пропускается.
Это работает (так +1), но при запуске с ограничением раздражающе отображается «пропуск [myfirsthost]». Я пробовал добавить
delegate_to: localhost
, но, похоже, это не помогло. Я признаю, что это косметика. Кто-нибудь знает, как это исправить?