Ansible:在角色执行时应用标签

问题描述

我试图明确地了解在 Ansible 中如何在角色执行中应用标签

我阅读了 https://docs.ansible.com/ansible/latest/user_guide/playbooks_tags.html#adding-tags-to-roles 上的文档并尝试了测试角色

 ~/ansible/roles/internal/test/tasks > cat tag-foo.yml
---
- import_tasks: tag-foo.yml
  tags:
    - foo
    - foo2

- import_tasks: tag-bar.yml
  tags:
    - bar

- import_tasks: always.yml
  tags:
    - always

- import_tasks: never.yml
  tags:
    - never
    - nevermind

 ~/ansible/roles/internal/test/tasks > cat tag-foo.yml
---
- name: This is tag 'foo'
  debug:
    msg: This is tag 'foo'

 ~/ansible/roles/internal/test/tasks > cat tag-bar.yml
---
- name: This is tag 'bar'
  debug:
    msg: This is tag 'bar'

 ~/ansible/roles/internal/test/tasks > cat always.yml
---
- name: This is tag 'always'
  debug:
    msg: This is tag 'always'

 ~/ansible/roles/internal/test/tasks > cat never.yml
---
- name: This is tag 'never'
  debug:
    msg: This is tag 'never'

我创建了一个测试剧本文件

 ~/ansible > cat plays/test.yml
- hosts: all

  tasks:
    - name: Execute test role with all tags
      import_role:
        name: test
      tags: foo2

    - name: Execute test role with tag 'foo'
      import_role:
        name: test
      tags:
        - foo

我不明白的是,如果我使用 foo 标签执行剧本,角色会两次执行,而不仅仅是一次只执行 tag-foo.ymltag-always.yml

 ~/ansible > ansible-playbook -i test.ini plays/test.yml -l test.domain.local -t foo

PLAY [all] ********************************************************************************************************************************************

TASK [Gathering Facts] ********************************************************************************************************************************
ok: [test.domain.local]

TASK [test : This is tag 'foo'] ***********************************************************************************************************************
ok: [test.domain.local] => {
    "msg": "This is tag 'foo'"
}

TASK [test : This is tag 'always'] ********************************************************************************************************************
ok: [test.domain.local] => {
    "msg": "This is tag 'always'"
}

TASK [test : This is tag 'foo'] ***********************************************************************************************************************
ok: [test.domain.local] => {
    "msg": "This is tag 'foo'"
}

TASK [test : This is tag 'bar'] ***********************************************************************************************************************
ok: [test.domain.local] => {
    "msg": "This is tag 'bar'"
}

TASK [test : This is tag 'always'] ********************************************************************************************************************
ok: [test.domain.local] => {
    "msg": "This is tag 'always'"
}

TASK [test : This is tag 'never'] *********************************************************************************************************************
ok: [test.domain.local] => {
    "msg": "This is tag 'never'"
}

PLAY RECAP ********************************************************************************************************************************************
test.domain.local           : ok=7    changed=0    unreachable=0    Failed=0    skipped=0    rescued=0    ignored=0

我想要的是从单个 import_role 语句中强制标记,而不必在 ansible-playbook 命令中指定它。

编辑:我尝试将 import_role 语句替换为 include_role 到剧本中,添加 apply 选项以应用 foo 标签

- name: Execute test role with tag 'foo'
  include_role:
    name: test
    apply:
      tags:
        - foo

我将角色的 import_tasks 文件中的 main.yml 语句替换为 include_tasks

---
- include_tasks: tag-foo.yml
  tags:
    - foo
    - foo2

- include_tasks: tag-bar.yml
  tags:
    - bar

- include_tasks: always.yml
  tags:
    - always

- include_tasks: never.yml
  tags:
    - never
    - nevermind

但不幸的是没有任何改变:'bar' 任务仍然被执行:

 ~/ansible > ansible-playbook -i test.ini plays/test.yml -l test.domain.local

PLAY [all] ********************************************************************************************************************************************

TASK [Gathering Facts] ********************************************************************************************************************************
ok: [test.domain.local]

TASK [Execute test role with tag 'foo'] ***************************************************************************************************************

TASK [test : include_tasks] ***************************************************************************************************************************
included: /Users/me/ansible/roles/internal/test/tasks/tag-foo.yml for test.domain.local

TASK [test : This is tag 'foo'] ***********************************************************************************************************************
ok: [test.domain.local] => {
    "msg": "This is tag 'foo'"
}

TASK [test : include_tasks] ***************************************************************************************************************************
included: /Users/me/ansible/roles/internal/test/tasks/tag-bar.yml for test.domain.local

TASK [test : This is tag 'bar'] ***********************************************************************************************************************
ok: [test.domain.local] => {
    "msg": "This is tag 'bar'"
}

TASK [test : include_tasks] ***************************************************************************************************************************
included: /Users/me/ansible/roles/internal/test/tasks/always.yml for test.domain.local

TASK [test : This is tag 'always'] ********************************************************************************************************************
ok: [test.domain.local] => {
    "msg": "This is tag 'always'"
}

PLAY RECAP ********************************************************************************************************************************************
test.domain.local           : ok=7    changed=0    unreachable=0    Failed=0    skipped=0    rescued=0    ignored=0

解决方法

通过使用 import_role,它是静态重用,标签不会限制导入,而是添加到导入角色的每个任务中。

要使用标记来限制角色的执行,您应该使用带有 include_role 的动态重用。

更多关于导入 vs 的文档包括:https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse.html#re-using-files-and-roles

Tags 机制是通过 CLI 设置的。 如果你想通过 playbook 定义不同的角色行为,varswhen 是更好的选择:

- include_role: my_role
  vars:
     only_foo: True

# in my_role:
- debug:
     msg: Only on foo
  when: only_foo