Ansible: выполнять задачу, только если указан тег

75

Ansible теги могут использоваться для запуска только подмножества задач / ролей. Это означает, что по умолчанию все задачи выполняются, и мы можем только предотвратить выполнение некоторых задач.

Можно ли ограничить выполнение задачи только тогда, когда указан тег «foo»? Можем ли мы использовать текущие теги в whenразделе задачи?

Таха Джахангир
источник
2
Похоже, вам нужна какая-то установка задачи, например limit_to_tags: foo, которой нет, и я не думаю, что это возможно сейчас. У будущей реализации также должен быть план относительно того, использовать ли теги AND или OR вместе.
рБоп
Взгляните на мой ответ в «Ansible - По умолчанию / Явные теги» stackoverflow.com/questions/28789912/…
sirkubax

Ответы:

38

Ansible 2.5 поставляется со специальными тегами neverи always. Тег neverможно использовать именно для этой цели. Например:

tasks:
  - debug: msg='{{ showmevar}}'
    tags: [ 'never', 'debug' ]

В этом примере задача будет запускаться только тогда, когда тег debug(или never) явно запрашивается. [Ссылка на ансамбль документов]

Таха Джахангир
источник
20

Хотя это обходное решение, оно работает.

Внутри списка задач зарегистрируйте переменную при нормальном выполнении. Затем добавьте условие when, которое проверяет эту переменную в тегированной задаче.

- shell: /bin/true
  register: normal_task_list

- name: Only run when tag is specified
  shell: /bin/echo "Only running because of specified tag"
  when: normal_task_list is not defined
  tags: specified
Крис Чипман
источник
Вы также можете использовать untaggedдля этого:- set_fact: untagged_run=true tags: untagged
Pyzo
Можете ли вы объяснить немного больше об этом? Пример из реального мира?
Quintin Par
17

У меня недостаточно репутации, чтобы сказать или прокомментировать ответ, предлагающий использовать переменные командной строки ( --extra-vars), но у меня есть это, чтобы добавить к нему:

Предостережение в этом методе заключается в том, что воспроизведение будет с ошибкой и завершится ошибкой, если вы не определите эту дополнительную переменную.

Вы можете предотвратить сбой воспроизведения при отсутствии --extra-varsопределения, определив значение по умолчанию в самой книге:

---
- hosts: ...
# ↓↓↓
  vars:
    thorough: false
# ↑↑↑
  tasks:
  - name: apt - install nfs-common only when thorough is true
    when: thorough | bool
    apt:
      cache_valid_time: 86400
      force: yes
      pkg:
        - nfs-common

Переопределение через via --extra-varsбудет по-прежнему работать, потому что переменные, определенные в командной строке, имеют приоритет над всеми другими определениями.

В результате игра запускается без ошибок, если thoroughона не изменена trueна командную строку.

Алекс Питерс
источник
5
То же самое может быть достигнуто с помощью thorough | default('no') | bool.
Costi Ciudatu
2
Или, when: thorough is defined and thoroughесли вы предпочитаете этот синтаксис
KCD
Спасибо, люблю is defined andсинтаксис больше. больше, чем множество труб, которые я не чувствую, интуитивно понятны.
Элайджа Линн
10

Вы можете использовать условные выражения для защиты от случайно запускаемых задач, которые в противном случае выполнялись бы, если бы вы не указали тег. Предостережение этому методу состоит в том, что воспроизведение будет давать ошибку и завершится ошибкой, если вы не определите эту дополнительную переменную.

Используя аргумент extra-vars, вы можете запустить условное условие.

Из ansible-playbook --помощь:

 -e EXTRA_VARS, --extra-vars=EXTRA_VARS
    set additional variables as key=value or YAML/JSON

Пример:

ansible-playbook test.yaml -e "thorough=true"

test.yaml:

...
- name: apt - install nfs-common only when thorough is true
  apt:
    cache_valid_time: 86400
    force: yes
    pkg:
    - nfs-common
  when: thorough | default(False)
...
Ava
источник
2
Чтобы избежать ошибки, если вы не определите «тщательный», просто используйте thorough | default("false") | match("true"). По умолчанию не должно быть false, просто ничего не совпадает true, но это улучшает читаемость.
Том Уилсон
4

Проверка переменной 'tags' не работает в Ansible 2.1.1.0. Смотрите ниже для теста. У меня есть другая идея, чтобы выполнить задачу, только когда тег определен, работая для Ansible 1.9.X и 2.XY:

- set_fact: foo=true
  tags: bar
- set_fact: foo=false
- name: do something when 'bar' tag is defined
  debug: var=foo
  when: foo
  tags: bar

При этом при запуске playbook без каких-либо тегов переменная 'foo' будет установлена ​​в true, а затем в false, поэтому ничего не выполняется. Если вы добавите тег 'bar', будет применен только первый параметр, поэтому переменная 'foo' будет иметь значение true, тогда ваша задача будет выполнена. Наслаждайтесь!


А вот тест на переменную 'tags' в Ansible 2.1.1.0:

Вот книга игр:

- hosts: localhost
  connection: local
  tasks:
    - name: display tags variable
      debug: var=tags
      tags: foo

    - name: do something only when tag 'foo' is provided
      debug: var=tag
      when: tags is defined
      tags: foo

И вот вывод:

$ ansible-playbook --version ; ansible-playbook ./test.yml -t foo
ansible-playbook 2.1.1.0
  config file = /home/nootal/projects/ivy/src/ansible/ansible.cfg
  configured module search path = Default w/o overrides

PLAY [localhost] ***************************************************************

TASK [display tags variable] ***************************************************
ok: [localhost] => {
    "tags": "VARIABLE IS NOT DEFINED!"
}

TASK [do something only when tag 'foo' is provided] ****************************

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0   
nootal
источник
2

Да. Запуск ansible-playbook с этим --tags fooфлагом обеспечит выполнение только тех задач, которые помечены foo. Например, предположим, что у нас есть playbook с именем example.yml:

tasks:

  - yum: name={{ item }} state=installed
    with_items:
       - httpd
       - memcached
    tags:
       - packages

  - name: some other task
    ..
    tags:
      - some other tag

Бег:

ansible-playbook example.yml --tags "packages"

Убедитесь, что выполняется только задание yum.

Так что на самом деле вам не нужно использовать теги в секции when для условного выполнения задачи. Обратите внимание, что в зависимости от сложности ваших книг / ролей вам может понадобиться комбинация --tags и --skip-tags, чтобы контролировать, какие задачи будут выполняться. Например, если включаемая задача помечена как «foo», а какая-то задача во включенной пьесе помечена как «bar», и вы запускаете

ansible-playbook --tags "foo"

Внутренняя задача (помеченная только как 'bar') будет выполнена. Чтобы избежать выполнения всех внутренних задач, помеченных как «bar», вам нужно будет выполнить следующую команду

ansible-playbook --tags foo --skip-tags bar
Шахар
источник
7
Это не так: «Задание тега в задаче означает, что только когда этот тег будет явно передан команде ansible-playbook, эта задача будет выполнена».
Гимболенд
1
Во-вторых, утверждение не соответствует действительности.
Chris
10
да, вы можете добиться такого поведения, гарантируя, что вы всегда будете использовать правильные ansible-playbookпараметры, но я думаю, что OP запрашивает способ аннотировать задачу, чтобы она не выполнялась, если в ansible-playbookкоманде явно не добавлен конкретный тег .
рБоп
4
Да, это не ответ на вопрос ОП.
Аллен Люс
все действия с тегами / без тегов выполняются, если вы не указали тег. Теги не могут исключать действие для запуска, только включить. Здесь нет логики предикатов, кроме аддитивного фильтра.
bbaassssiiee
1

Существует специальный тег «никогда» , который будет препятствовать выполнению задачи, если тег не запрошен специально.

tasks:
  - debug: msg='{{ showmevar}}'
    tags: [ 'never', 'debug' ]
xtoznaxto
источник
Уже упоминалось в ответе выше: serverfault.com/a/907329/105928
Таха Джахангир
0

когда предложение не может оценить наличие тегов. В качестве обходного пути я использую переменные и теги вместе для запуска задач, специфичных для этого тега / переменной.

Пример: представьте себе книгу с книгами и инвентарь

# инвентарь
[DEV]
192.168.1.1

# site.yml
- хосты: dev
  роли:
    - {роль: обычная}

и в общем / tasks / main.yml

# role / common / tasks / main.yaml
- имя: установить ссылки
  apt: name = состояние ссылок = присутствует

- включить: uninstall.yml
  когда: uninstall_links определено
  теги:
    - удалить

# role / common / tasks / uninstall.yml
- имя: удалить ссылки
  apt: name = состояние ссылок = отсутствует

При таком подходе вы используете тег для выбора только задач в uninstall.yml, но вам также нужно установить переменную 'uninstall_links' в какое-либо значение, чтобы включить ее. Так что если вы запустите playbook без каких-либо параметров, по умолчанию будет запущена задача установки. Чтобы удалить, вы можете установить тэг 'uninstall' для вашей книги воспроизведения (или cmdline) и ДОЛЖНЫ установить переменную. Если вы не установите тег, он будет запускать все (устанавливать и удалять) в указанном порядке, что хорошо для тестирования всего процесса.

Как все запустить (установит и удалит):

$ ansible-playbook -i inventory site.yml -l dev -s -k -e "uninstall_links=true"

Как запустить только тег «удалить» в группе разработчиков

$ ansible-playbook -i inventory site.yml -l dev -s -k -e "uninstall_links=true" -t uninstall

Следовательно, переменные и теги также могут находиться в файлах site.yml / инвентаризации, что позволяет вам зафиксировать в своем SCM и записать свое намерение.

Андерсон Гуларт
источник
0

Ноотал прав, мой подход не работает - проигнорируйте его :( Теперь я использую «когда: myvar определен» и переключатель командной строки «-e» myvar = X »для выполнения задач только по явному запросу.

Еще проще (хотя бы с ansible 2.1.1.0):

- name: do something only when tag 'foo' is provided
  when: tags is defined
  tags: foo

-> будет выполняться, только если были предоставлены теги И теги включают "foo"

DrPsychick
источник
0

На Ansible 2.3.2.0, вот мое решение проблемы:

---
- hosts: localhost
  gather_facts: no
  vars:
    in_tag: yes
  tasks:
    - set_fact: in_tag=no
    - fail:
        msg: "recently_added is set and you're using blah tag"
      when: ( in_tag | bool )
      tags:
        - blah
    - debug:
        msg: "always remember"

Он начинается с установки in_tagна Trueтогда, когда есть, set_factкоторый устанавливает его обратно, Falseкогда вы не указываете ни один tagsиз ansible-playbook.

Когда вы указываете теги, in_tagостается Trueи failзадача запускается.

PS: вы можете добавить логику для любых задач, которые вы хотите

PS2: вы также можете расширить логику и жестко закодировать все имеющиеся у вас теги и, конечно, set_fact: in_tag_blah=Trueв сочетании с ними tags: ["blah"].

tehmoon
источник