使用阵列样式检查主机属性时可能出现错误



我有一个site.yml剧本,当我使用这个配置时:

- hosts: target
  tags:
    - setup_target
  tasks:
    - name: See some data
      debug: msg={{ hostvars[inventory_hostname][ansible_lsb].codename }}

可靠地向我报告一个错误:

PLAY [target] ***************************************************************** 
GATHERING FACTS *************************************************************** 
ok: [target]
TASK: [See some data] ********************************************************* 
fatal: [target] => One or more undefined variables: dict object has no element {u'release': u'14.04', u'major_release': u'14', u'codename': u'trusty', u'id': u'Ubuntu', u'description': u'Ubuntu 14.04.1 LTS'}
FATAL: all hosts have already failed -- aborting
PLAY RECAP ******************************************************************** 
           to retry, use: --limit @/home/robe/site.retry
target                     : ok=1    changed=0    unreachable=1    failed=0  

但如果我使用点样式,比如:

---
# The main playbook to deploy
# setup our database
- hosts: target
  tags:
    - setup_target
  tasks:
    - name: See some data
      debug: msg={{ hostvars[inventory_hostname].ansible_lsb.codename }}

输出正常:

PLAY [target] ***************************************************************** 
GATHERING FACTS *************************************************************** 
ok: [target]
TASK: [See some data] ********************************************************* 
ok: [target] => {
    "msg": "trusty"
}
PLAY RECAP ******************************************************************** 
target                     : ok=2    changed=0    unreachable=0    failed=0 

那么,有什么不同呢?对我来说,两者是平等的?

那么,有什么不同呢?对我来说,两者是平等的?

这归结为dicts/hashes在Python中的工作方式,以及它们在jinja2和Ansible中的工作情况。

如果您有一个名为data的dict,并且您想要foo元素的值,您可以这样访问它:

data["foo"]

如果省略引号,则需要一个名为foo的变量。

data[foo] # does not work (so far)

jinja2还允许您使用点样式:

data.foo

让我们假设"foo"元素的值是数字42。这些都是真的:

data["foo"] = 42
data[foo] # does not work
data.foo = 42

现在,如果您有一个名为foo的变量,该怎么办?在下面的例子中,我们将考虑键"foo"的值仍然是42,而"bar"将是13。

foo = "bar"
data["foo"] = 42
data[bar] = 13
data.foo = 42

要将其转换为原始情况,请记住inventory_hostnameansible_lsb都是变量,而不是字符串。更令人困惑的是,ansible_lsb是一本字典。这意味着你原来的括号样式扩展如下:

hostvars["inventory_hostname"][{u'release': u'14.04', u'major_release': u'14', u'codename': u'trusty', u'id': u'Ubuntu', u'description': u'Ubuntu 14.04.1 LTS'}]["codename"]

哎呀。作为dict的关键的dict进入了递归的同类相食龟。

以下是你的"点状"风格。

hostvars["inventory_hostname"]["ansible_lsb"]["codename"]

这个也可以稍微翻译一下,让它稍微清晰一点:

lsb = hostvars["inventory_hostname"]["ansible_lsb"]
lsb["codename"]

这显然是你想要的。

相关内容