Ansible - 默认/显式标签

时间:2015-03-01 03:54:34

标签: tags ansible ansible-playbook

我有一个包含并标记各种角色的剧本:

- name:  base
  hosts: "{{ host | default('localhost') }}"

roles: 

  - { role: apt,              tags: [ 'base', 'apt', 'ubuntu']}
  - { role: homebrew,         tags: [ 'base', 'homebrew', osx' ]}
  - { role: base16,           tags: [ 'base', 'base16', 'osx' ]}
  - { role: nodejs,           tags: [ 'base', 'nodejs' ]}
  - { role: tmux,             tags: [ 'base', 'tmux' ]}
  - { role: vim,              tags: [ 'base', 'vim' ]}
  - { role: virtualenv,       tags: [ 'base',  virtualenv', 'python' ]}
  - { role: homebrew_cask,    tags: [ 'desktop', 'homebrew_cask', osx' ]}
  - { role: gnome_terminator, tags: [ 'desktop', 'gnome_terminator', ubuntu' ]}

大多数任务都使用when子句来确定应该运行哪个操作系统,例如:

- name: install base packages
  when: ansible_distribution == 'MacOSX'
  sudo: no
  homebrew:
    name: "{{ item.name }}"
    state: latest
    install_options: "{{ item.install_options|default() }}"
  with_items: homebrew_packages

如果我在未指定任何标签的情况下运行ansible-playbook base.yml,则会运行所有任务。如果我指定了代码,例如ansible-playbook base.yml --tags='base',则仅指定标有base run的角色。

默认情况下(如果未指定任何代码),我只想运行使用'base'标记的角色,而标记为'desktop'的角色

设置默认的' os'也很不错。标签,基于当前的操作系统,避免在我在OSX上运行playbook时包含ubuntu的所有任务(反之亦然)。

任何想法,如果这是可能的,我怎么做?

6 个答案:

答案 0 :(得分:6)

不幸的是没有这样的功能。 Ansible中的标签处理目前非常有限。您无法设置默认标记,默认情况下也无法排除标记。

Google用户组中有一些主题,并且github上有关于此的功能请求。但还没有结果。到目前为止,常见的答案是,您应该创建一个shell脚本并将其放在您的剧本前面。然后,此脚本可以根据您的需要设置--tags--skip-tags。非常不愉快,但据我所知,现在唯一的选择。

答案 1 :(得分:2)

  

如果我在没有指定任何标签的情况下运行ansible-playbook base.yml,则所有任务都会运行。

是的,这非常危险。 如果您忘记添加' - tags = xxxxx'它可能会运行不需要的任务......

有一种解决方法,它很讨厌,但是当命令行中没有标记时,它会阻止运行你的任务。

你可以使用--extra-vars并在你的剧本中使用它,然后运行:

ansible-playbook base.yml -e'SOMEVAR=TRUE'

在你的剧本中:

- hosts: localhost
  tasks:
   - name: some task
     ping:
     tags:
      - sometag

   - name: Register SOMEVARANS
     set_fact: SOMEVARANS={{SOMEVAR | default('False')}}
     tags:
      - every_tag_you_know_since_there_is_no_ALL_option
      - sometag

   - debug: msg="{{SOMEVARANS}}"
     tags:
      - every_tag_you_know_since_there_is_no_ALL_option
      - sometag

   - debug: msg="run only with extravars SOMEVAR=True"
     when: SOMEVARANS
     tags:
      - every_tag_you_know_since_there_is_no_ALL_option
      - sometag

结果:

$ ansible-playbook -i /subsystem/ansible/etc/inventory-qa.ini  tags.yml

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

TASK: [some task] *************************************************************
ok: [localhost]

TASK: [Register SOMEVARANS] ***************************************************
ok: [localhost]

TASK: [debug msg="{{SOMEVARANS}}"] ********************************************
ok: [localhost] => {
    "msg": "False"
}

TASK: [debug msg="run only with extravars SOMEVAR=True"] **********************
skipping: [localhost]

PLAY RECAP ********************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0



 WITH 'SOMEVAR=True'
    $ ansible-playbook -i /subsystem/ansible/etc/inventory-qa.ini  tags.yml  -e 'SOMEVAR=True'

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

    TASK: [some task] *************************************************************
    ok: [localhost]

    TASK: [Register SOMEVARANS] ***************************************************
    ok: [localhost]

    TASK: [debug msg="{{SOMEVARANS}}"] ********************************************
    ok: [localhost] => {
        "msg": "True"
    }

    TASK: [debug msg="run only with extravars SOMEVAR=True"] **********************
    ok: [localhost] => {
        "msg": "run only with extravars SOMEVAR=True"
    }

    PLAY RECAP ********************************************************************
    localhost                  : ok=4    changed=0    unreachable=0    failed=0


ALL IN ONE :)
$ ansible-playbook -i /subsystem/ansible/etc/inventory-qa.ini  tags.yml  -e 'SOMEVAR=True'  --tags=sometag

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

TASK: [some task] *************************************************************
ok: [localhost]

TASK: [Register SOMEVARANS] ***************************************************
ok: [localhost]

TASK: [debug msg="{{SOMEVARANS}}"] ********************************************
ok: [localhost] => {
    "msg": "True"
}

TASK: [debug msg="run only with extravars SOMEVAR=True"] **********************
ok: [localhost] => {
    "msg": "run only with extravars SOMEVAR=True"
}

PLAY RECAP ********************************************************************
localhost                  : ok=4    changed=0    unreachable=0    failed=0

答案 2 :(得分:2)

我使用命令行变量覆盖(-e)来实现此目的:

$ ansible-playbook playbook.xml -e desktop=true

不是将desktop定义为标记,而是将其定义为默认值为false的变量。然后,对于要求desktop为true的角色,请使用when子句替换该标记。问题中贴出的剧本可能会改写如下:

- name:  base
  hosts: "{{ host | default('localhost') }}"

  # default value to prevent errors when not overridden
  vars:
    desktop: false

  roles:

    # no change to "base" roles
    - { role: apt, tags: [ 'base', 'apt', 'ubuntu'] }
    # ...

    # "desktop" roles get a "when" clause
    - role: homebrew_cask
      when: desktop | bool
      tags: [ 'homebrew_cask', 'osx' ]
    - role: gnome_terminator
      when: desktop | bool
      tags: [ 'gnome_terminator', ubuntu' ]

这可能只是现有答案之一的简化​​版本。如其他地方所述,除非明确指定某些内容,否则标签不是目前的答案,默认某些操作不会运行。另一方面,变量是完美的。

答案 3 :(得分:2)

从Ansible 2.5开始,有一个新功能可以解决这类情况。

  

永远不会有另一个特殊标记,这将阻止任务运行   除非明确要求使用标签。

Example:

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

因此,您的问题应按以下方式解决:

- name:  base
  hosts: "{{ host | default('localhost') }}"

roles: 

  - { role: apt,              tags: [ 'base', 'apt', 'ubuntu']}
  - { role: homebrew,         tags: [ 'base', 'homebrew', osx' ]}
  - { role: base16,           tags: [ 'base', 'base16', 'osx' ]}
  - { role: nodejs,           tags: [ 'base', 'nodejs' ]}
  - { role: tmux,             tags: [ 'base', 'tmux' ]}
  - { role: vim,              tags: [ 'base', 'vim' ]}
  - { role: virtualenv,       tags: [ 'base',  virtualenv', 'python' ]}
  - { role: homebrew_cask,    tags: [ 'never','desktop', 'homebrew_cask', osx' ]}
  - { role: gnome_terminator, tags: [ 'never','desktop', 'gnome_terminator', ubuntu' ]}

答案 4 :(得分:1)

  

标签还有另外3个特殊关键字,'标记','未标记'和'全部',它们分别只标记标记,仅标记为无标记和所有任务。   默认情况下,ansible运行就像指定了'-tags all'一样。

您可以在此处查看文档:{​​{3}}

答案 5 :(得分:1)

使用默认值的原因通常是:我想在最常见的用例中尽可能少地键入。所以我认为OP实际上想要的是:

是否有办法以尽可能少的参数运行'基础'任务。

正如其他人指出的那样,ansible中没有“默认”标签。但总有办法。

第一种方法就是使用脚本来包装它,就像 像这样写run.sh

ansible-playbook -t base base.yml

输入./run.sh而不是完整命令要短得多。

第二种方式是寻找纯ansible解决方案的人。你可以有两个剧本,如:

base.yml

- { role: apt,              tags: [ 'base', 'apt', 'ubuntu']}
- { role: homebrew,         tags: [ 'base', 'homebrew', osx' ]}
- { role: base16,           tags: [ 'base', 'base16', 'osx' ]}
- { role: nodejs,           tags: [ 'base', 'nodejs' ]}
- { role: tmux,             tags: [ 'base', 'tmux' ]}
- { role: vim,              tags: [ 'base', 'vim' ]}
- { role: virtualenv,       tags: [ 'base',  virtualenv', 'python' ]}

desktop.yml

- { role: homebrew_cask,    tags: [ 'desktop', 'homebrew_cask', osx' ]}
- { role: gnome_terminator, tags: [ 'desktop', 'gnome_terminator', ubuntu' ]}

对于仅基本任务,请运行ansible-playbook base.yml; 对于仅限桌面的任务,请运行ansible-playbook desktop.yml; 对于所有任务,请运行ansible-playbook base.yml desktop.yml
它比定义'默认'标签更容易出错。

OP还需要默认的OS标签。使用when

很容易实现
   - { role: some_role, when: "ansible_os_family == 'Debian'" } 

使用when,您无需在命令行中执行任何操作,ansible会检测类型并为您运行相应的任务。