Ruby:将一个ansible hosts文件转换为嵌套数组

时间:2017-04-19 22:53:28

标签: ruby parsing

我通过http.get检索ansible主机文件,如下所示:

[group1]
host1
host2

[group2]
host3
host4

如何从每个组开始迭代,然后折叠以下行,直到下一个组成为这样的嵌套哈希?

{ "group1" => ["host1", "1host2"], "group2" => ["host3", "host4"] }

3 个答案:

答案 0 :(得分:2)

直接INI解析

如果您不想进行完整解析,可以将语料库视为包含节的INI文件。这样的文件可能很棘手并且有许多边缘情况,特别是如果您不能严格定义部分的分隔方式。但是,以下内容适用于您的特定语料库。

# Read the file.
ini = File.read '/tmp/example.ini'

# Split the file into sections. Assumes only one blank line between
# sections.
sections = ini.scan /^\[.*?(?:\n\n|\z)/m

# Return an array of hashes, then merge them. Use the first element
# from each split as the hash key.
hash = sections.map do |section| 
  array = section.split
  key   = array.shift.delete '[]'
  { key => array }
end.reduce({}, :merge)

#=> {"group1"=>["host1", "host2"], "group2"=>["host3", "host4"]}

在更复杂的类似INI的文件中,有多种方法可能会失败,因此如果你走这条路,你可能需要对文件进行更全面的解析。或者,您可以将结果保存为文件,然后parse the inventory into a Ruby hash using the Ansible CLI

答案 1 :(得分:1)

从Ansible的CLI输出中将库存分解为Ruby Hash

您可以将Ansible inventory的输出解析为(主要)JSON。这实际上比直接解析类似INI的文件更容易,更可靠,尽管Ansible CLI将您想要的结果包装在顶级groups值中。

require 'json'

output = %x(ansible localhost -i /tmp/example.ini -m debug -a 'var=groups')
json   = JSON.parse(output.sub /^.*=>/, '')

json['groups']
#=> {"all"=>["host1", "host2", "host3", "host4"], "group1"=>["host1", "host2"], "group2"=>["host3", "host4"], "ungrouped"=>["localhost"]}

json['groups']['group1']
#=> ["host1", "host2"]

# Use Hash#dig on recent Rubies to simplify lookups.
json.dig 'groups', 'group2'
#=> ["host3", "host4"]

如果确实只需要以字符串group开头的组,则可以动态提取它们。例如:

json['groups'].keys.select { |k| k.start_with? 'group' }.map do |key|
  { key => json['groups'][key] }
end.reduce({}, :merge)
#=> {"group1"=>["host1", "host2"], "group2"=>["host3", "host4"]}

答案 2 :(得分:1)

有一个ansible-inventory命令。

的一个例子
ansible-inventory  -i path/to/inventory --export --list

示例结果就像

{
    "all": {
        "children": [
            "db",
            "ungrouped",
            "web"
        ]
    },
    "db": {
        "hosts": [
            "demo_db"
        ]
    },
    "web": {
        "hosts": [
            "demo_app"
        ]
    }
}