Ansible:仅在指定标签后才执行任务


76

Ansible标签只能用于运行任务/角色的子集。这意味着默认情况下将执行所有任务,并且我们只能阻止某些任务执行。

是否可以在指定了“ foo”标签的情况下将任务限制为可以执行?我们可以在when任务部分使用当前标签吗?


2
听起来您需要的是一些任务设置,例如limit_to_tags:foo,该设置不存在,我认为目前无法实现。未来的实现还需要制定一个计划,以将这些标记进行AND或OR运算。
dgh

在“ Ansible-默认/显式标签” stackoverflow.com/questions/28789912/…中
sirkubax

Answers:



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

您能解释一下吗?一个真实的例子?
昆丁票面值

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

--extra-vars因为在命令行上定义的变量优先于所有其他定义,所以覆盖via 仍将起作用。

结果是,当thoroughtrue在命令行上更改为时,播放将正确运行。


5
使用可以实现相同的效果thorough | default('no') | bool
Costi Ciudatu

2
或者,when: thorough is defined and thorough如果您更喜欢该语法
KCD

谢谢,is defined and更喜欢语法。不仅仅是我不觉得很直观的多个管道。
伊利亚·林恩

10

您可以使用条件语句来防止意外运行的任务,如果您未指定标签,这些任务将被执行。该方法的警告是,如果您未定义该额外变量,则播放将出错并失败。

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

2
如果您未定义“彻底”,为避免发生错误,请使用thorough | default("false") | match("true")。默认值不必是false,只要不匹配即可true,但是它提高了可读性。
汤姆·威尔逊

4

在Ansible 2.1.1.0中,无法检查'tags'变量。请参阅下面的测试。我还有另一种想法,仅在定义了标签且对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

这样,在运行没有任何标签的剧本时,“ foo”变量将设置为true,然后设置为false,因此不会执行任何操作。如果添加'bar'标签,则仅将应用第一个设置,因此'foo'变量将为true,则将执行任务。请享用!


这是有关Ansible 2.1.1.0中'tags'变量的测试:

这是剧本:

- 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   

2

是。使用该--tags foo标志运行ansible-playbook 将确保仅执行带有标记的任务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”)将被执行。为了避免执行所有标记为“ bar”的内部任务,您将必须执行以下命令

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

7
事实并非如此:“在任务上指定标签意味着仅当将该标签显式传递给ansible-playbook命令时,该任务才会执行。”
gimboland

1
其次,声明不正确。
克里斯(Chris)

10
是的,可以通过确保始终使用正确的ansible-playbook选项来实现此行为,但是我认为OP正在要求一种对任务进行注释的方法,以便除非在ansible-playbook命令中显式添加了特定标记,否则该任务就不会执行。
dgh

4
是的,这不能回答OP的问题。
艾伦·卢斯

当您未指定标签时,所有带标签/未带标签的操作都会运行。标签不能排除要运行的动作,而只能包括。除加法过滤器外,没有谓词逻辑。
bbaassssiiee


0

when子句无法评估标签的存在。作为一种解决方法,我将变量和标签一起使用以运行特定于该标签/变量的任务。

例如:想像一下剧本和广告资源

#库存
[开发]
192.168.1.1

#site.yml
-主持人:dev
  角色:
    -{角色:普通}

并在common / tasks / main.yml中

#角色/通用/任务/main.yaml
-名称:安装链接
  apt:名称=链接状态=存在

-包括:uninstall.yml
  时间:定义了uninstall_links
  标签:
    - 卸载

#角色/普通/任务/uninstall.yml
-名称:卸载链接
  apt:名称=链接状态=不存在

通过这种方法,您可以使用标记仅选择uninstall.yml中的任务,但是还需要将“ uninstall_links”变量设置为某种变量以启用它。因此,如果您在没有任何参数的情况下运行剧本,则默认情况下,它将运行安装任务。要卸载,您可以将标签“ 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 / inventory文件中,从而使您能够提交到SCM中并记录您的意图。


0

nootal是正确的,我的方法行不通 -忽略它:(我现在使用“ when:定义了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”时执行


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然后在没有指定from 时set_fact将其重新设置为Falseon 。tagsansible-playbook

当您指定标签时,将in_tag停留在True并且fail任务运行。

PS:您可以将逻辑添加到所需的任何任务中

PS2:您当然也可以set_fact: in_tag_blah=True结合使用tags: ["blah"],扩展逻辑并对所有标签进行硬编码。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.