-1

我需要一些帮助来理解为什么,当我为 Ansible 剧本创建一个 YAML 文件时,该文件完全反映了模块文档中指定的内容,当 Python 读取 YAML 时,列表和 list_items 没有被正确解析。

我的理解是,在阅读 Github 上有关 Ansible 模块的文档时,项目会显示在列中,以表示它们相对于它们上方和下方的项目的关系。此外,如果一个项目被定义为“ list / elements=dictionary ”,那么这意味着以下内容:

  1. 项目的键入必须通过添加冒号和空格来完成(这定义了“字典”项目)

  2. 下一行/后续行必须以相同的缩进级别(或更高级别)开始,并以连字符和空格开头(这表示“列表”项)

  3. 列表中项目的顺序必须严格遵守。

  4. 后续列表项必须与列表中的第一项处于同一缩进级别

  5. 如果列表中的任何给定子项是 ITSELF 另一个“ list / elements=dictionary ”项,则再次重复第 2 步。

(示例:取自cisco.ios.ios_ospfv2模块)所以如果“进程”的主要项目是由以下组成的“列表/元素=字典”:

  1. 区域(也是“列表/元素=字典”)
  2. 网络(也是“列表/元素=字典”)
  3. process_id(整数)

那么上述正确的 YAML 语法将是:

processes: 
- areas: 
  - area_id: 0 ##dictionary_item
  - authentication: ##dictionary_item
      message_digest: true ##boolean
- network: 
  - address: '10.1.1.0' ##string
  - area: '0' ##string
  - wildcard_bits: 0.0.0.255. ##integer
- process_id: 1

然而,即使我在启动 Playbook 时没有收到任何 YAML 错误,但我确实收到了一堆晦涩的 Python 回溯。但是,如果我将代码更改为 THIS(见下文),它就可以工作!

processes: 
- process_id: 1
  areas: 
  - area_id: '0'
    authentication: 
      message_digest: true
  network: 
    address: 0.0.0.0
    area: 0
    wildcard_bits: 255.255.255.255

我的问题:

  1. 如果 list_items 的顺序很重要,为什么当我遵循模块文档中指定的顺序时我的文件不起作用……但是当忽略该顺序时它确实起作用(根据文档,“process_id”不应该是第一个)模块)?
  2. 我知道并非每个 list_item 都需要以连字符空格开头。但我确实认为第一个 list_item 需要这个。那么为什么(在我的第一个示例中)当我用连字符表示“网络”下的子项时我的剧本失败了......但是当我从这个列表中删除所有连字符时,它确实有效?但是,“区域”下的第一个 list_item 确实需要连字符??

Python 错误

(很抱歉这篇长文……我不知道能比这更进一步)

4

3 回答 3

0

以下是对此 YAML 的一般解释:

processes: 
- process_id: 1
  areas: 
  - area_id: '0'
    authentication: 
      message_digest: true
  network: 
    address: 0.0.0.0
    area: 0
    wildcard_bits: 255.255.255.255
  • processes:你可能有 1 到 N 个进程,所以它是一个列表,在这种情况下,是一个字典列表。你应该期待这样的事情:
    processes:
      - foo: bar
        baz: qux
      - foo: some
        baz: thing
    
  • process_id: 是一个 int,你应该期望:
    processes:
      - foo: bar
        baz: qux
        # since you are in a dictionary, 
        # process_id can be anywhere in the dictionary, 
        # as the first, last, or anywhere in between key 
        process_id: 1 
      - foo: some
        baz: thing
        # since you are in a dictionary, 
        # process_id can be anywhere in the dictionary, 
        # as the first, last, or anywhere in between key 
        process_id: 2
    
    所以这是完全相同的 YAML
    processes:
      - process_id: 1
        # since you are in a dictionary, 
        # process_id can be anywhere in the dictionary, 
        # as the first, last, or anywhere in between key  
        foo: bar
        baz: qux
      - process_id: 2
        # since you are in a dictionary, 
        # process_id can be anywhere in the dictionary, 
        # as the first, last, or anywhere in between key 
        foo: some
        baz: thing 
    
  • areas: 是一个1到N区域的areas列表,在字典的key下,嵌套在一个list中,key的processes
    processes:
      - process_id: 1
        areas:
          - area_id: '0'
            authentication: 
              message_digest: true
          - area_id: '1'
            authentication: 
              message_digest: true
      - process_id: 2
        areas:
          - area_id: '0'
            authentication: 
              message_digest: true 
    
  • network: 是字典中的字典
    processes:
      - process_id: 1
        areas:
          - area_id: '0'
            authentication: 
              message_digest: true
          - area_id: '1'
            authentication: 
              message_digest: true
      - process_id: 2
        areas:
          - area_id: '0'
            authentication: 
              message_digest: true 
        network: 
          address: 0.0.0.0
          area: 0
          wildcard_bits: 255.255.255.255
    

所以总的来说,请注意 Ansible 如何在这里给你提示:areas它是多元化的,有充分的理由:因为它是一个区域列表。也一样processes。Whilenetwork是单数,因此,正如预期的那样,它将是字典而不是列表。


列表/元素=字典

意味着进程必须是一个列表,其中每个元素都是一个字典。

在 YAML 中,这是一个字典:

foo:
  some: bar
  property: bar
  of: bar
  the: bar
  dictionary: bar
  of: bar
  key: bar
  foo: bar

这是一个列表:

fruits:
  - banana
  - apple
  - pear
  - peach

那么字典列表将是:

- the:
    red: fox
    jump: over
- the:
    lazy: dog

请注意,因为这是一个列表,所以相同的键可以在列表的不同元素中复制,但不能在同一个字典中出现两次。


所以要回答你的第二个问题,你是正确的,在字典中键的顺序无关紧要:

the:
  red: fox
  jump: over

确实与字典完全相同

the:
  jump: over
  red: fox

但是,由于在这里您要列出应该是字典的内容,这就是您的问题所在。


在连字符 ( -) 上也要注意一点,因为这似乎让您感到烦恼:

如果您喜欢它,请像这样编写您的列表:

- 
  foo: bar
  bar: foo
- 
  baz: qux
  qux: baz

这严格等同于:

- foo: bar
  bar: foo

- baz: qux
  qux: baz

这将帮助您看到连字符确实界定了列表的新元素从那里开始的事实,现在您可以“压缩”它并将字典的键与“列表的新项目”定界符放在同一行( -),但您并非被迫这样做。


也许对于并行的面向对象编程语言,如果这对您有任何帮助,您应该考虑

  • 字典就像一个对象,它有多个属性,但所有属性实际上都定义了同一个对象
  • 列表是事物的集合,它可以是对象列表、整数列表,甚至是对象列表。

因此,当文档说list / elements=dictionary时,他们实际上希望您构建一个列表(或集合),其中所有元素都是字典(或对象)。


也许文档页面本身的布局比 GitHub 上的表格更容易阅读。
但是在那里,您可以清楚地看到config字典包含一个processes列表,该列表本身包含许多不同的字典,其中address_family, adjacency, ..., areas, network, ...

ios_ospfv2 模块中的参数表

于 2020-11-16T18:42:06.523 回答
0

更新:我之前使用的是 Ansible cisco.ios 集合版本 1.1.0(它要求在模块“ios_ospfv2”的 Python 代码中将“network”参数作为字典输入)。

升级到 cisco.ios 集合的 1.2.0 版后,“network”参数不再用作字典,需要改回列表(与此模块的文档匹配)。

因此,显然使用的 Ansible Collection 版本可能会改变模块内参数的定义方式。故事的道德启示?确保您使用的是您需要的任何 Collection 的最新版本。 确定最新的集合版本

于 2020-11-17T17:59:46.333 回答
0

谢谢大家的见解。我已经与其他人商议过,我认为这是该模块的文档错误问题。“网络”项目被记录为“列表/元素=字典”。

实际上,底层 Python 代码希望将其视为字典(而不是列表)。当添加为字典时,它工作正常。请查看我的链接,其中我提供了(不正确的)文档的屏幕截图以及当“network”配置为“list / elements=dictionary”时导致的 Python 错误。 在此处输入图像描述

于 2020-11-16T21:52:55.137 回答