简体   繁体   English

Ansible 动态清单脚本 - 奇怪的行为

[英]Ansible dynamic inventory script - odd behaviour

I'm trying to create a basic dynamic inventory script for ansible based on JSON output.我正在尝试基于 JSON 输出为 ansible 创建一个基本的动态清单脚本。 I'm new to jq but I've hit an issue where the dynamic script on ansible v2.9.14 & 2.9.15 doesn't like the output, but if I send the output to a file and then run Ansible against the output in the file, ansible works.我是 jq 的新手,但我遇到了一个问题,即 ansible v2.9.14 和 2.9.15 上的动态脚本不喜欢输出,但是如果我将输出发送到文件然后针对输出运行 Ansible该文件,ansible 作品。

This is what happens:这是发生的事情:

dynamic inventory script output:动态清单脚本输出:

{
  "all": {
      "hosts": {
"ip-172-31-39-30.eu-west-1.compute.internal": null,
"ip-172-31-44-224.eu-west-1.compute.internal": null,
"ip-172-31-42-6.eu-west-1.compute.internal": null,
"ip-172-31-32-68.eu-west-1.compute.internal": null,
    }
  }
}

Ansible run and error: Ansible 运行和错误:

$ ansible -i ./dynamic1.sh all -m ping -u ubuntu
[WARNING]:  * Failed to parse /home/ubuntu/dynamic1.sh with script plugin: failed to parse executable inventory script results from /home/ubuntu/dynamic1.sh:
Expecting property name enclosed in double quotes: line 8 column 5 (char 242)
[WARNING]:  * Failed to parse /home/ubuntu/dynamic1.sh with ini plugin: /home/ubuntu/dynamic1.sh:2: Expected key=value host variable assignment, got: {
[WARNING]: Unable to parse /home/ubuntu/dynamic1.sh as an inventory source
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

Now, if I output the dynamic script to a file, then run ansible again, it works:现在,如果我将动态脚本输出到一个文件,然后再次运行 ansible,它会起作用:

$ ./dynamic1.sh > output.json

$ cat output.json
{
  "all": {
      "hosts": {
"ip-172-31-39-30.eu-west-1.compute.internal": null,
"ip-172-31-44-224.eu-west-1.compute.internal": null,
"ip-172-31-42-6.eu-west-1.compute.internal": null,
"ip-172-31-32-68.eu-west-1.compute.internal": null,
    }
  }
}

$ ansible -i output.json all -m ping -u ubuntu
[DEPRECATION WARNING]: Distribution Ubuntu 16.04 on host ip-172-31-42-6.eu-west-1.compute.internal should use /usr/bin/python3, but is using /usr/bin/python for
backward compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See
https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information. This feature will be removed in version 2.12. Deprecation
warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
ip-172-31-42-6.eu-west-1.compute.internal | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
ip-172-31-39-30.eu-west-1.compute.internal | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
ip-172-31-32-68.eu-west-1.compute.internal | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}
ip-172-31-44-224.eu-west-1.compute.internal | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python3"
    },
    "changed": false,
    "ping": "pong"
}

So it works...所以它有效...

This is the contents of dynamic1.sh.这是dynamic1.sh的内容。 I know there will be better ways to do this but I just need a list of servers based on a matching variable in the JSON output that ansible can use.我知道会有更好的方法来做到这一点,但我只需要一个基于 JSON 输出中 ansible 可以使用的匹配变量的服务器列表。

$ cat dynamic1.sh
#!/bin/bash
echo "{"
echo "  \"all\": {"
echo "      \"hosts\": {"
curl --silent -X GET https://url.com/api/servers -H "Authorization: Token $token" -H "Content-Type: text/json"  -H "Accept:application/json" | jq -r '.Result.servers[] | select(.ansible_local.local.local_facts.instance_type | tostring | contains("t2.micro")) | (.ansible_fqdn+"\": null,")' | sed 's/^/"/g'
echo "    }"
echo "  }"
echo "}"

Can anyone give me any help on why ansible accepts the file but not the output of the script?任何人都可以帮助我解释为什么 ansible 接受文件而不是脚本的输出?

In contrary to the Ansible inventory format , the inventory plugin script.py expects the attribute hosts to be a list (eg hosts:[ host1, host2, host3 ] ) not a dictionary (eg hosts:{ host, host2, host3 } ).Ansible 清单格式相反,清单插件script.py期望属性hosts是一个列表(例如hosts:[ host1, host2, host3 ] )而不是字典(例如hosts:{ host, host2, host3 } )。


Inventory plugin yaml.py works with dictionaries of hosts清单插件yaml.py与主机字典一起使用

The JSON (or YAML, because JSON is a subset of YAML) inventory works fine JSON(或 YAML,因为 JSON 是 YAML 的子集)清单工作正常

shell> cat hosts.json
{
    "all": {
        "hosts": {
            "ip-172-31-39-30.eu-west-1.compute.internal",
            "ip-172-31-44-224.eu-west-1.compute.internal",
            "ip-172-31-42-6.eu-west-1.compute.internal",
            "ip-172-31-32-68.eu-west-1.compute.internal"
        }
    }
}
shell> ansible-inventory -i hosts.json --list -vvv
...
Parsed /scratch/tmp/hosts.json inventory source with yaml plugin
{
    "_meta": {
        "hostvars": {}
    },
    "all": {
        "children": [
            "ungrouped"
        ]
    },
    "ungrouped": {
        "hosts": [
            "ip-172-31-32-68.eu-west-1.compute.internal",
            "ip-172-31-39-30.eu-west-1.compute.internal",
            "ip-172-31-42-6.eu-west-1.compute.internal",
            "ip-172-31-44-224.eu-west-1.compute.internal"
        ]
    }
}

But, the same file provided by the script will fail但是,脚本提供的相同文件将失败

shell> cat hosts.sh 
#!/bin/bash
cat hosts.json
shell> ansible-inventory -i hosts.sh --list -vvv
...
Parsed /scratch/tmp/hosts.sh inventory source with script plugin

[WARNING]: Failed to parse /scratch/tmp/hosts.sh with script plugin: You defined a group 'all' with bad data for the host list: {'hosts': {'ip-172-31-39-30.eu- west-1.compute.internal': None, 'ip-172-31-44-224.eu-west-1.compute.internal': None, 'ip-172-31-42-6.eu-west-1.compute.internal': None, 'ip-172-31-32-68.eu- west-1.compute.internal': None}} ... [警告]:无法使用脚本插件解析 /scratch/tmp/hosts.sh:您为主机列表定义了一个包含错误数据的组“all”:{'hosts': {'ip-172-31-39-30 .eu-west-1.compute.internal':无,'ip-172-31-44-224.eu-west-1.compute.internal':无,'ip-172-31-42-6.eu -west-1.compute.internal':无,'ip-172-31-32-68.eu-west-1.compute.internal':无}} ...

{
    "_meta": {
        "hostvars": {}
    },
    "all": {
        "children": [
            "ungrouped"
        ]
    }
}

Inventory plugin script.py works with lists of hosts库存插件script.py适用于主机列表

The inventory plugin script.py works as expected when the attribute hosts is a list当属性 hosts 是一个列表时,清单插件script.py按预期工作

shell> cat hosts.json
{
    "all": {
        "hosts": [
            "ip-172-31-39-30.eu-west-1.compute.internal",
            "ip-172-31-44-224.eu-west-1.compute.internal",
            "ip-172-31-42-6.eu-west-1.compute.internal",
            "ip-172-31-32-68.eu-west-1.compute.internal"
        ]
    }
}
shell> ansible-inventory -i hosts.sh --list -vvv
...
Parsed /scratch/tmp/hosts.sh inventory source with script plugin
{
    "_meta": {
       ...
    },
    "all": {
        "children": [
            "ungrouped"
        ]
    },
    "ungrouped": {
        "hosts": [
            "ip-172-31-32-68.eu-west-1.compute.internal",
            "ip-172-31-39-30.eu-west-1.compute.internal",
            "ip-172-31-42-6.eu-west-1.compute.internal",
            "ip-172-31-44-224.eu-west-1.compute.internal"
        ]
    }
}

Notes笔记

  • The script hosts.sh is not implemented properly and serves the purpose of this example only.脚本hosts.sh未正确实现,仅用于此示例的目的。 Quoting from script.py :script.py引用:

description: - The source provided must be an executable that returns Ansible inventory JSON - The source must accept C(--list) and C(--host ) as arguments.描述: - 提供的源必须是返回 Ansible 清单 JSON 的可执行文件 - 源必须接受 C(--list) 和 C(--host ) 作为参数。 C(--host) will only be used if no C(_meta) key is present. C(--host) 仅在不存在 C(_meta) 键时使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Ubuntu bash awk奇怪的行为 - Ubuntu bash awk odd behaviour 使用Ansible Tower中的事实进行过滤器清单的语法是什么? - What's the syntax for filter inventory using facts in Ansible Tower? 使用ec2.py进行动态库存 - Using ec2.py for dynamic inventory 试图在python中为ansible创建一个动态主机文件 - Trying to make a dynamic host file for ansible in python 使用 Ansible 通过 Python 脚本获取系统信息 - Get system information with a Python script using Ansible 在Gnome Scheduler中运行Bash脚本时出现奇怪的Bash错误 - Odd Bash Error When Running Bash Script In Gnome Scheduler 同一shell脚本在不同的Linux发行版上具有不同的行为 - Same shell script has different behaviour on different Linux distributions 使用 Ansible 获取 Azure 密钥保管库机密 - 我如何在 Ansible 脚本中告诉 azure_preview_modules 安装了正确的 Ansible? - Get Azure key vault secret using Ansible - how can I tell azure_preview_modules in Ansible script where the correct Ansible is installed? 如何在php(ubuntu)上模拟on_script_close,如.net on_form_close行为? - how to simulate on_script_close on php(ubuntu), like the .net on_form_close behaviour? 如何制作脚本来下载带有动态链接的文件? - how can i make a script to download files with dynamic links?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM