yaml 格式的动态库存

yaml 格式的动态库存

背景

我通过 Terraform 管理域,它输出服务器 IP 地址。然后我有一个输出 YAML 清单的脚本(输出内容稍后发布)。

问题

当我运行ansible-inventory --inventory inventory.sh --graph它时总是以

@all:
  |--@stage:
  |--@ungrouped:
  |  |--18.66.1.28

我预计这台机器将处于小组赛阶段。

我发现静态库存和作为脚本输出的库存有不同的行为。

静态文件

如果您将其保存为静态文件并将其用作库存,它将起作用。

all:
  hosts:
    18.66.1.28
  children:
    stage:
      hosts:
        18.66.1.28:

输出:

  @all:
  |--@stage:
  |  |--18.66.1.28
  |--@ungrouped:

脚本

但如果你指定如下的 shell 脚本,它将不起作用

#!/bin/bash

echo "all:
  hosts:
    18.66.1.28
  children:
    stage:
      hosts:
        18.66.1.28:"

输出:

 [WARNING]:  * Failed to parse /tmp/inventory.sh with script plugin: You defined a group 'all' with bad data for the host list:  {u'hosts':
u'18.66.1.28', u'children': {u'stage': {u'hosts': {u'18.66.1.28': None}}}}

 [WARNING]:  * Failed to parse /tmp/inventory.sh with ini plugin: /tmp/inventory.sh:3: Error parsing host definition 'echo "all:': No closing
quotation

 [WARNING]: Unable to parse /tmp/inventory.sh as an inventory source

 [WARNING]: No inventory was parsed, only implicit localhost is available

YAML 输出

变体 1

all:
  hosts:
    - 18.66.1.28
  children:
    stage:
      hosts:
        - 18.66.1.28:

变体 2

all:
  hosts:
    - 18.66.1.28
  children:
    stage:
      hosts:
        18.66.1.28:

变体 3

all:
  hosts:
    - 18.66.1.28
  children:
    stage:
      hosts:
        - 18.66.1.28

答案1

简短回答

不要看https://docs.ansible.com/ansible/2.6/user_guide/intro_inventory.html但在https://docs.ansible.com/ansible/2.6/dev_guide/developing_inventory.html

长答案

Ansible 至少使用三种格式来存储清单。YAML、INI 和 JSON。INI 格式是完全独立的格式,具有自己的结构。YAML 和 JSON 本身允许创建几乎相同的数据结构。当我查看https://docs.ansible.com/ansible/2.6/user_guide/intro_inventory.html充满了 YAML 示例,使用 JSON 我只需更改符号即可生成与 YAML 相同的数据结构。问题是,脚本插件使用不同的数据结构,但它允许您同时使用 YAML 和 JSON 格式。

例子

静态库存

输入:

$ cat /tmp/inventory-static 
all:
  hosts:
    18.66.1.28
  children:
    stage:
      hosts:
        18.66.1.28:

输出

$ ansible-inventory --inventory /tmp/inventory-static --graph 
@all:
  |--@stage:
  |  |--18.66.1.28
  |--@ungrouped:

这是正确的格式和行为https://docs.ansible.com/ansible/2.6/user_guide/intro_inventory.html

脚本

输入:

$ cat /tmp/inventory.sh 
#!/bin/bash

echo "all:
  hosts:
    18.66.1.28
  children:
    stage:
      hosts:
        18.66.1.28:"

输出:

 $ ansible-inventory --inventory /tmp/inventory.sh --graph    
 [WARNING]:  * Failed to parse /tmp/inventory.sh with script plugin: You defined a group 'all' with bad data for the host list:  {u'hosts':
u'18.66.1.28', u'children': {u'stage': {u'hosts': {u'18.66.1.28': None}}}}

 [WARNING]:  * Failed to parse /tmp/inventory.sh with ini plugin: /tmp/inventory.sh:3: Error parsing host definition 'echo "all:': No closing
quotation

 [WARNING]: Unable to parse /tmp/inventory.sh as an inventory source

 [WARNING]: No inventory was parsed, only implicit localhost is available

这不是我所期望的。问题是脚本插件需要不同的数据结构。让我们尝试使用来自的数据结构https://docs.ansible.com/ansible/2.6/dev_guide/developing_inventory.html

输入:

$ cat /tmp/inventory.sh                                  
#!/bin/bash
echo "stage:
  hosts:
    - 18.66.1.28”

输出

$ ansible-inventory --inventory /tmp/inventory.sh --graph
@all:
  |--@stage:
  |  |--18.66.1.28
  |--@ungrouped:

是的,这是我预期的结果。机器在正确的组中,并且摄取插件没有任何抱怨。当然,根据“动态库存源”,脚本应该做的不仅仅是库存echo,它可能应该输出 JSON,这只是如何构造脚本库存的输出的演示。

我花了很长时间才弄清楚这一点,所以我希望通过写下这篇文章,能够帮助其他人。

答案2

主机名(您的变体 1)之前不应有破折号。

all:
  hosts:
    18.66.1.28
  children:
    stage:
      hosts:
        18.66.1.28:

$ ansible-inventory --inventory 库存 --graph

@all:
  |--@stage:
  |  |--18.66.1.28
  |--@ungrouped:

通过破折号你会看到很多警告。

all:
  hosts:
    - 18.66.1.28
  children:
    stage:
      hosts:
        - 18.66.1.28:

$ ansible-inventory --inventory 库存 --graph

 [WARNING]:  * Failed to parse inventory with yaml plugin:
 Invalid "hosts" entry for "all" group, requires a dictionary, found "<class 
 'ansible.parsing.yaml.objects.AnsibleSequence'>" instead.

 [WARNING]:  * Failed to parse inventory with ini plugin:
 inventory:3: Expected key=value host variable assignment, 
 got: 18.66.1.28

 [WARNING]: Unable to parse inventory as an inventory source

 [WARNING]: No inventory was parsed, only implicit localhost is available

...

引用自 man ansible-inventory

-i, --inventory, --inventory-file
    specify inventory host path or comma separated host list.
    --inventory-file is deprecated

如果脚本首先创建一个文件,那么一切就正确。

$ ./inventory.sh > /tmp/my_inventory.yml && ansible-inventory --inventory /tmp/my_inventory.yml --graph

@all:
  |--@stage:
  |  |--18.66.1.28
  |--@ungrouped:

相关内容