虽然许多人可能喜欢ansible,但在我看来,它似乎与它相当混为一谈和有些多余的概念,如tags
,roles
,inventory/hosts files
,hostgroups
,playbooks
,tasks
"when" conditionals
确定最终将执行的内容存在相当大的挑战。这个问题的核心问题是tags
.
我的理解是,如果我有一个剧本,其中有一个包含标签列表的角色,这些标签将由所有包含的任务添加(继承)
例:
[----./playbook.yml----]
---
- hosts: all
roles:
- {role: role01, tags: ['tag01', 'tag02']}
- {role: role02, tags: ['tag01', 'tag03']}
意味着在./roles/role01/tasks/main.yml
中找到的所有任务都将隐式标记为tag01
和tag02
。确认这将是这个问题的答案的一部分
同样,./roles/role02/tasks/main.yml
中的所有任务都被标记为tag01
和tag03
,对吧?
现在这里的问题是,查看文件./roles/role01/tasks/main.yml
我看到此内容
[----./roles/role01/tasks/main.yml----]
---
- block:
- name: "upgrade all packages"
yum:
name: '*'
state: latest
tags:
- tag01
考虑到该角色仅从上面显示的./playbook.yml
行中引用,我看不出拥有tag01
有什么意义,因为它应该在给定的行中隐式标记:
- {role: role01, tags: ['tag01', 'tag02']}
另外,我完全感到不安的是,另一个block
概念,必须在这里使用?
问题的各个方面:
在- 角色
main.yml
中标记是多余的吗? - 为什么要使用块(考虑到无论如何只有一个任务)?
TL;博士:是的,在问题中解释的情况下(在 ansible 角色级别隐式标记,使得角色内部单个任务/块的标记变得不必要,因此是多余的)。
更长的信息:
可悲的是,Ansible经常招致过于复杂和扭曲的语法和风格。在这种情况下,它只是一个不必要的重复标记,再加上同样没有必要使用block
的语法元素(在 ansible playbook 中)。
ansible 在标记方面的行为是如何验证/测试的? => 带有 shell/bash sctipt:
我已经求助于这个 shell 脚本,它应该测试tags
在角色的隐式继承中的行为方式。
bash脚本将创建一个最小的ansible测试用例,它 包含两个角色role1
和role2
,都是逐字副本 除了名字(所以能够告诉他们公寓)和 有 2 个任务:
task(A)
未显式标记task(B)
被明确标记为"tag01"。
必要的 ansibleplaybook.yml
和主机/清单文件inventory.ini
也是 在脚本中创建:
#!/bin/bash
#make a temporary directory for test
TEMPDIR="$(mktemp -d)"
#change to temporary directory
cd "$TEMPDIR"
# create ansible hosts file "./inventory.ini"
# only host we need is the the local box (to be simple disregard any ssh overhead)
cat > inventory.ini <<'EOF'
[hosts]
localhost ansible_connection=local
EOF
# create ansilble role "role1"
# (to keep it simple, we have minimal role with only a tasks entry)
mkdir -p roles/role1/tasks
# (the content for the tasks/main.yml file are two tasks, with one task
# namely task(A) not being explicitly and the task(B) being explicitly
# tagged)
cat > roles/role1/tasks/main.yml <<'EOF'
---
# tasks file for role1 and role2
- name: "task(A) tagged not explicitly 'tag01'"
debug:
msg: "debug-msg: this is "task(A) tag explicitly 'tag01'" {{ role_name }} ."
- name: "task(B) tagged explicitly 'tag01'"
debug:
msg: "debug-msg: this is "task(B) tagged explicitly 'tag01'" {{ role_name }} ."
tags:
- tag01
EOF
# create ansible role "role2" as a verbatim copy of "role1"
cp -r roles/role1 roles/role2
# now create an ansible playbook that uses these two ansible roles
# (note that for the role "role1" we used "implicit tagging"
cat > playbook.yml <<'EOF'
---
- hosts: all
roles:
- role: "role1"
tags:
- "tag01"
- role: "role2"
EOF
# show the test setup
find .
# TEST 1:
# run "playbook.yml" one time "as is" ( i.e. no using of tags -> "all tasks"
# should be run)
echo "TEST1" | tee TEST1
ansible-playbook -i inventory.ini playbook.yml | tee -a TEST1
# TEST 2:
# run "playbook.yml" with --tags command line options ( meaning this time
# we limit the task to be run to only those that have the specific tag)
echo "TEST2" | tee TEST2
ansible-playbook -i inventory.ini --tags 'tag01' playbook.yml | tee -a TEST2
# TEST 3:
# run "playbook.yml" with --skip-tags command line options ( meaning this time
# we limit the task to be run all, but those to tags to be "skipped")
echo "TEST3" | tee TEST3
ansible-playbook -i inventory.ini --skip-tags 'tag01' playbook.yml | tee -a TEST3
# show path of temporary directory
echo "TEMPDIR is $TEMPDIR"
运行此 shell 脚本后,它基本上会产生三个结果
- 测试 1 "TEST1",
ansible-playbook -i inventory.ini playbook.yml
:无标记用法 => 任何隐式或显式标记都不起作用 运行两个角色的所有任务role1
和role2
:
测试1 播放 [全部] ****** 任务 [收集事实] ****** 确定:[本地主机] 任务 [角色 1 : 任务 (A) 未明确标记为"tag01"] ****** 确定: [本地主机] => { "msg": "debug-msg: 这是任务 (A) 标记显式 'tag01'\" role1 ." } 任务 [角色 1:任务 (B) 显式标记为"tag01"] ****** 确定: [本地主机] => { "msg": "debug-msg: 这是 \"任务 (B) 显式标记为 'tag01'\" role1 ." } 任务 [角色 2 : 任务 (A) 未明确标记为"tag01"] ****** 确定: [本地主机] => { "msg": "debug-msg: 这是 \"task(A) 标记显式 'tag01'\" role2 ." } 任务 [角色 2 : 任务 (B) 显式标记为 'tag01'] ****** 确定: [本地主机] => { "msg": "debug-msg: 这是 \"任务 (B) 显式标记为 'tag01'\" role2 ." } 播放回顾 ****** 本地主机:确定=5 已更改=0 无法访问=0 失败=0
- 测试 2 "TEST2",
ansible-playbook -i inventory.ini --tags 'tag01' playbook.yml
:使用标签 =>隐式和显式标记很重要。因为tag01
设置为在role
运行包含的任务任务 (A) 和task(B)
的级别进行role1
。相比之下,对于没有隐式继承标记的role2
,仅运行task(B)
。输出显示:
测试2 播放 [全部] ****** 任务 [收集事实] ****** 确定:[本地主机] 任务 [角色 1 : 任务 (A) 未明确标记为"tag01"] ****** 确定: [本地主机] => {"msg": "debug-msg: 这是任务 (A) 标记显式 'tag01'\" role1 ." } 任务 [角色 1:任务 (B) 显式标记为"tag01"] ****** 确定: [本地主机] => { "msg": "debug-msg: 这是 \"任务 (B) 显式标记为 'tag01'\" role1 ." } 任务 [角色 2 : 任务 (B) 显式标记为 'tag01'] ****** 确定: [本地主机] => { "msg": "debug-msg: 这是 \"任务 (B) 显式标记为 'tag01'\" role2 ." } 播放回顾 ****** 本地主机 : 确定=4 已更改=0 无法访问=0 失败=0
- 最后,测试 3 "TEST3" 反转所有内容
--skip-tags
其中隐式标记role1
导致跳过整个角色。对于ansible-playbook -i inventory.ini --skip-tags 'tag01' playbook.yml
,我们得到以下结果:
测试3 播放 [全部] ****** 任务 [收集事实] ****** 确定:[本地主机] 任务 [角色 2 : 任务 (A) 未明确标记为"tag01"] ****** 确定: [本地主机] => { "msg": "debug-msg: 这是 \"task(A) 标记显式 'tag01'\" role2 ." } 播放回顾 ****** 本地主机 : 确定=2 已更改=0 无法访问=0 失败=0 总之
,为了接近问题的主题,角色中包含的任务的 a 标签是多余的,如果该role
是 (a) 已经在playbook
中标记了自己,因此使其所有任务隐式继承任务,并且 b) 这是使用该角色的唯一playbook
(情况确实如此)这里)。
虽然输出可以通过执行此处提供的 shell 脚本来生成,但出于礼貌和完整,它的输出是:
.
./playbook.yml
./roles
./roles/role2
./roles/role2/tasks
./roles/role2/tasks/main.yml
./roles/role1
./roles/role1/tasks
./roles/role1/tasks/main.yml
./inventory.ini
TEST1
PLAY [all] **************************************************************************
TASK [Gathering Facts] **************************************************************************
ok: [localhost]
TASK [role1 : task(A) tagged not explicitly 'tag01'] **************************************************************************
ok: [localhost] => {
"msg": "debug-msg: this is "task(A) tag explicitly 'tag01'" role1 ."
}
TASK [role1 : task(B) tagged explicitly 'tag01'] **************************************************************************
ok: [localhost] => {
"msg": "debug-msg: this is "task(B) tagged explicitly 'tag01'" role1 ."
}
TASK [role2 : task(A) tagged not explicitly 'tag01'] **************************************************************************
ok: [localhost] => {
"msg": "debug-msg: this is "task(A) tag explicitly 'tag01'" role2 ."
}
TASK [role2 : task(B) tagged explicitly 'tag01'] **************************************************************************
ok: [localhost] => {
"msg": "debug-msg: this is "task(B) tagged explicitly 'tag01'" role2 ."
}
PLAY RECAP **************************************************************************
localhost : ok=5 changed=0 unreachable=0 failed=0
TEST2
PLAY [all] **************************************************************************
TASK [Gathering Facts] **************************************************************************
ok: [localhost]
TASK [role1 : task(A) tagged not explicitly 'tag01'] **************************************************************************
ok: [localhost] => {
"msg": "debug-msg: this is "task(A) tag explicitly 'tag01'" role1 ."
}
TASK [role1 : task(B) tagged explicitly 'tag01'] **************************************************************************
ok: [localhost] => {
"msg": "debug-msg: this is "task(B) tagged explicitly 'tag01'" role1 ."
}
TASK [role2 : task(B) tagged explicitly 'tag01'] **************************************************************************
ok: [localhost] => {
"msg": "debug-msg: this is "task(B) tagged explicitly 'tag01'" role2 ."
}
PLAY RECAP **************************************************************************
localhost : ok=4 changed=0 unreachable=0 failed=0
TEST3
PLAY [all] **************************************************************************
TASK [Gathering Facts] **************************************************************************
ok: [localhost]
TASK [role2 : task(A) tagged not explicitly 'tag01'] **************************************************************************
ok: [localhost] => {
"msg": "debug-msg: this is "task(A) tag explicitly 'tag01'" role2 ."
}
PLAY RECAP **************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0
TEMPDIR is /tmp/tmp.cPE6a4gGiG