Frederico Martins
Frederico Martins

Reputation: 1101

Parsing Ansible Inventory Hosts Pattern

I'm currently working with Ansible inventory hosts and my script needs to parse them in order to complete some tasks.

The issue here is converting the string patterns to an array or a string that can be iterated over, for example:

x="mymachine[1:2]cluster[1:2]"
for host in `parse_ansible_hosts $x`; do
    echo $host

Which should print:

mymachine1cluster1
mymachine1cluster2
mymachine2cluster1
mymachine2cluster2

Is there a way to accomplish this via regex or similar? The syntax cannot be changed, since it parses directly from ansible inventory.

Upvotes: 0

Views: 1003

Answers (3)

user594138
user594138

Reputation:

If I understand you correctly, you want a hostname generator. If this is correct, and the pattern is as simple as your example, bash already has you covered:

$ for host in mymachine{1,2}cluster{1,2}; do
> echo $host
> done
mymachine1cluster1
mymachine1cluster2
mymachine2cluster1
mymachine2cluster2

Ranges are supported, too:

$ for host in mymachine{1..3}cluster{1..3}; do echo $host; done
mymachine1cluster1
mymachine1cluster2
mymachine1cluster3
mymachine2cluster1
mymachine2cluster2
mymachine2cluster3
mymachine3cluster1
mymachine3cluster2
mymachine3cluster3

To get from your example pattern to shell-expansion might be one of the seldom cases where an eval is safe to use -- use this only if the pattern source is safe and trusted, not e.g. a web-interface:

$ x="mymachine[1:2]cluster[1:2]"
$ for host in $(eval \
        echo $(sed 's/\[/{/g' <<<${x} | \
                sed 's/]/}/g' | \
                sed 's/:/,/g' )); do
    echo $host
done
mymachine1cluster1
mymachine1cluster2
mymachine2cluster1
mymachine2cluster2 

For ranges this would read

$ for host in $(eval \
        echo $(sed 's/\[/{/g' <<<${x} | \
                sed 's/]/}/g' | \
                sed 's/:/../g' )); do
    echo $host
done

Nota Bene:

If you have the possibility to use other tools like python or ruby, there are 'reverse regexp' implementations available. E.g. 'regex-examples' as ruby-gem:

irb(main):003:0> require 'regexp-examples'
=> true
irb(main):004:0> /a[bc]/.examples()
=> ["ab", "ac"]
irb(main):005:0> /mymachine[12]cluster[12]/.examples()
=> ["mymachine1cluster1", "mymachine1cluster2", "mymachine2cluster1", "mymachine2cluster2"]

Upvotes: 1

Baptiste Mille-Mathias
Baptiste Mille-Mathias

Reputation: 2179

I'm sure the ansible Classes when it is installed on your host are publicy available so you could use them as ansible do to parse the inventory. I think the interesting parts are in https://github.com/ansible/ansible/tree/devel/lib/ansible/inventory

Upvotes: 0

Kent
Kent

Reputation: 195259

if your machine/cluster count < 10, replace the : by - in your x variable, it would be the regex to use.

Upvotes: 0

Related Questions