我有一个包含并标记各种角色的剧本:
- 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的所有任务(反之亦然)。
任何想法,如果这是可能的,我怎么可能这样做?
不幸的是没有这样的功能。 Ansible中的标签处理目前非常有限。您无法设置默认标记,也不能默认排除标记。
Google用户组中有一些主题,并且github上有关于此的功能请求。但还没有结果。到目前为止,常见的答案是,您应该创建一个shell脚本并将其放在您的剧本前面。然后,此脚本可以根据您的需要设置--tags
和--skip-tags
。非常不愉快,但据我所知,现在唯一的选择。
从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' ]}
如果我在没有指定任何标签的情况下运行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
我使用命令行变量覆盖(-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个特殊关键字用于标记,“标记”,“未标记”和“全部”,它们分别只标记标记,仅标记无标记和所有任务。默认情况下,ansible运行就像指定了'-tags all'一样。
你可以在这里查看文档:http://docs.ansible.com/ansible/playbooks_tags.html#special-tags
使用默认值的原因通常是:我想在最常见的用例中尽可能少地键入。所以我认为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会检测类型并为您运行相应的任务。