Je récupère un fichier d'hôtes ansible via http.get qui ressemble à ceci:

[group1]
host1
host2

[group2]
host3
host4

Comment faire une itération à partir de chaque groupe et réduire les lignes suivantes jusqu'au groupe suivant en un hachage imbriqué comme celui-ci?

{ "group1" => ["host1", "1host2"], "group2" => ["host3", "host4"] }
2
oorahduc 20 avril 2017 à 01:53

3 réponses

Meilleure réponse

Analyse INI directe

Si vous ne voulez pas faire une analyse complète, vous pouvez traiter votre corpus comme un fichier INI avec des sections. Ces fichiers peuvent être délicats et présenter de nombreux cas extrêmes, surtout si vous ne pouvez pas définir rigoureusement la façon dont les sections sont séparées. Cependant, ce qui suit fonctionnera avec votre corpus spécifique.

# 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"]}

Il y a toutes sortes de façons dont cela peut échouer sur un fichier de type INI plus complexe, vous devrez peut-être faire une analyse plus complète de votre fichier si vous suivez cette voie. Vous pouvez également simplement enregistrer le résultat sous forme de fichier, puis analyser l'inventaire dans un hachage Ruby à l'aide de la CLI Ansible.

3
Todd A. Jacobs 20 avril 2017 à 01:30

Il existe une commande ansible-inventory. Un exemple pour

ansible-inventory  -i path/to/inventory --export --list

Un exemple de résultat est comme

{
    "all": {
        "children": [
            "db",
            "ungrouped",
            "web"
        ]
    },
    "db": {
        "hosts": [
            "demo_db"
        ]
    },
    "web": {
        "hosts": [
            "demo_app"
        ]
    }
}
0
Timothy Kovalev 10 mars 2020 à 18:25

Analyser l'inventaire dans Ruby Hash à partir de la sortie CLI d'Ansible

Vous pouvez analyser la sortie d'un inventaire Ansible comme (principalement) JSON. C'est en fait plus facile et plus fiable que d'analyser directement un fichier de type INI, bien que l'interface de ligne de commande Ansible encapsule les résultats souhaités dans une valeur groups de premier niveau.

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"]

Si vous n'avez vraiment besoin que des groupes commençant par la chaîne group, vous pouvez les extraire dynamiquement. Par exemple:

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
Todd A. Jacobs 20 avril 2017 à 00:26