Назад | Перейти на главную страницу

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

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

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

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

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

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

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

Внутри списка задач зарегистрируйте переменную при нормальном выполнении. Затем добавьте условие 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

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

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

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

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

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

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

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

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

Из ansible-playbook --help:

 -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)
...

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

- 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' будет истинной, тогда ваша задача будет выполнена. Наслаждайтесь!


И вот тест о переменной '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   

Есть специальный тег - "никогда", что предотвратит запуск задачи, если не будет специально запрошен тег.

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

Да. Запуск ansible-playbook с --tags foo флаг гарантирует, что только задачи, помеченные foo выполнены. Например, предположим, что у нас есть учебник под названием 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', вам нужно будет выполнить следующую команду

ansible-playbook --tags foo --skip-tags bar

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

tasks:
  - debug: msg='{{ showmevar}}'
    tags: [ 'debug' ]
    when: "'debug' in ansible_run_tags"

Это использует магическая переменная ansible_run_tags который содержит список тегов, переданных через аргумент CLI --tags (или синонимично -t) и имеет эффект выполнения вышеуказанной задачи если и только если тег debug дано.

Кажется, эта волшебная переменная была введена в ansible 2.5

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

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

# inventory
[dev]
192.168.1.1

# site.yml
- hosts: dev
  roles:
    - { role: common }

and in common/tasks/main.yml

# roles/common/tasks/main.yaml
- name: Install links
  apt: name=links state=present

- include: uninstall.yml
  when: uninstall_links is defined
  tags:
    - uninstall

# roles/common/tasks/uninstall.yml
- name: Uninstall links
  apt: name=links state=absent

При таком подходе вы используете тег для выбора только задач в uninstall.yml, но вам также необходимо установить переменную «uninstall_links» на что-нибудь, чтобы включить ее. Поэтому, если вы запустите playbook без каких-либо параметров, он по умолчанию запустит задачу установки. Для удаления вы можете установить тег «uninstall» для своей playbook (или 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 / inventory, что позволит вам выполнить фиксацию в SCM и записать свое намерение.

nootal прав, мой подход не работает - игнорировать это :( Теперь я использую "when: myvar is defined" и переключатель командной строки "-e" myvar = X "для выполнения задач только по явному запросу.

Еще проще (по крайней мере, с доступным 2.1.1.0):

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

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

На 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"] конечно.

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

Это правильный ответ, но людей часто смущает то, как заставить Ansible Добавить этот тег, потому что если вы поместите --tags debug в командной строке, затем только то, что выполняется, - это задачи отладки. Решение --tags all,debug например

ansible-playbook play.yaml --tags all,debug

В Ansible docs по тегам есть эта строка:

По умолчанию Ansible запускается так, как если бы были указаны --tags all.