# generate ascii graph of topology based on inventory

**URL:** <https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669>\
**Category:** Ansible Developer\
**Created:** [February 27, 2014, 8:28pm UTC](https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669 "2014-02-27T20:28:09Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Trevor\_Hartman](https://avatars.discourse-cdn.com/v4/letter/t/f9ae1b/32.png) [@Trevor\_Hartman](https://forum.ansible.com/u/Trevor_Hartman)\
**Post date:** [February 27, 2014, 8:28pm UTC](https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669/1 "2014-02-27T20:28:09Z")

</div>

I think it’d be useful/interesting to generate an ascii graph of topology based on the configured inventory. Assuming this doesn’t exist already, if I contributed this feature, what are the chances it’d be accepted?

---

<div class="post-metadata">

**Author:** ![Serge\_van\_Ginderacht](https://avatars.discourse-cdn.com/v4/letter/s/b782af/32.png) [@Serge\_van\_Ginderacht](https://forum.ansible.com/u/Serge_van_Ginderacht)\
**Post date:** [February 27, 2014, 8:43pm UTC](https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669/2 "2014-02-27T20:43:37Z")

</div>

​I'm not totally sure what you mean by such a graph, given how Ansible  
inventory can be multiple "trees"​ of group etc.?

Do you have some POC, or more info on what you want to do, and also, why?

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Serge

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [February 27, 2014, 8:56pm UTC](https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669/3 "2014-02-27T20:56:47Z")

</div>

Totally, that would be cool.

We’d definitely take it as an examples/ script.

It would probably be best if it generated something in “dot” format and maybe it shells out to graphviz “dot” when done.

GraphViz tends to suck if you have a lot of hosts so an option to maybe print the hosts or not (or just show the counts) might be relevant.

You could use the inventory API to surf this and should be able to work with dynamic inventory scripts as well.

–Michael

---

<div class="post-metadata">

**Author:** ![Trevor\_Hartman](https://avatars.discourse-cdn.com/v4/letter/t/f9ae1b/32.png) [@Trevor\_Hartman](https://forum.ansible.com/u/Trevor_Hartman)\
**Post date:** [February 27, 2014, 9:01pm UTC](https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669/4 "2014-02-27T21:01:41Z")

</div>

> I’m not totally sure what you mean by such a graph, given how Ansible inventory can be multiple “trees” of group etc.?

You’re right, it would be a set of trees.

Rough example I made on [asciiflow.com](http://asciiflow.com):

[zookeepers]

---

<div class="post-metadata">

**Author:** ![Trevor\_Hartman](https://avatars.discourse-cdn.com/v4/letter/t/f9ae1b/32.png) [@Trevor\_Hartman](https://forum.ansible.com/u/Trevor_Hartman)\
**Post date:** [February 27, 2014, 9:11pm UTC](https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669/5 "2014-02-27T21:11:03Z")

</div>

> Should I PR against [https://github.com/ansible/ansible-examples](https://github.com/ansible/ansible-examples)?

Nevermind, I see [https://github.com/ansible/ansible/tree/devel/examples/scripts](https://github.com/ansible/ansible/tree/devel/examples/scripts)

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [February 27, 2014, 9:12pm UTC](https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669/6 "2014-02-27T21:12:52Z")

</div>

Actually it can be a graph and is not just a series of trees, which is why we actually nixed the YAML inventory plugin a while back, because YAML is treeish 🙂

Two groups can have the same kid, etc!

---

<div class="post-metadata">

**Author:** ![Serge\_van\_Ginderacht](https://avatars.discourse-cdn.com/v4/letter/s/b782af/32.png) [@Serge\_van\_Ginderacht](https://forum.ansible.com/u/Serge_van_Ginderacht)\
**Post date:** [February 27, 2014, 9:31pm UTC](https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669/7 "2014-02-27T21:31:02Z")

</div>

​I once started on that idea​, but didn't get through to it. I got as far  
as to this script:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[https://github.com/ginsys/ansible-plugins/blob/devel/bin/ansible-vars](https://github.com/ginsys/ansible-plugins/blob/devel/bin/ansible-vars)

more specifically the output of

&nbsp;&nbsp;&nbsp;&nbsp;ansible-vars --list-groups

I definitely look forward to your ideas!

&nbsp;&nbsp;&nbsp;Serge

---

<div class="post-metadata">

**Author:** ![anatoly\_techtonik](https://avatars.discourse-cdn.com/v4/letter/a/c67d28/32.png) [@anatoly\_techtonik](https://forum.ansible.com/u/anatoly_techtonik)\
**Post date:** [March 4, 2014, 10:32am UTC](https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669/8 "2014-03-04T10:32:31Z")

</div>

Idea - [http://blockdiag.com/en/nwdiag/index.html](http://blockdiag.com/en/nwdiag/index.html) - no graphviz needed.

Is there and export of hosts/groups in some graph format already?  
I have some viz is JavaScript:  
[http://techtonik.bitbucket.org/graphs/index.html](http://techtonik.bitbucket.org/graphs/index.html)

and for simple graphs it is possible to support parsing a CSV of edges.

---

<div class="post-metadata">

**Author:** ![Serge\_van\_Ginderacht](https://avatars.discourse-cdn.com/v4/letter/s/b782af/32.png) [@Serge\_van\_Ginderacht](https://forum.ansible.com/u/Serge_van_Ginderacht)\
**Post date:** [March 4, 2014, 10:58am UTC](https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669/9 "2014-03-04T10:58:30Z")

</div>

​No, the way Inventory objects are modelled, you just have hosts and a list  
groups they are member of​, but the parent child relation between groups is  
not kept.  
You''ll have to dig in the Inventory code to understand how to extract this.

---

<div class="post-metadata">

**Author:** ![anatoly\_techtonik](https://avatars.discourse-cdn.com/v4/letter/a/c67d28/32.png) [@anatoly\_techtonik](https://forum.ansible.com/u/anatoly_techtonik)\
**Post date:** [March 4, 2014, 12:27pm UTC](https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669/10 "2014-03-04T12:27:36Z")

</div>

Is that it?

group2 \<---- host ---\> group1

What other kind of parent-child relationship order is needed?

---

<div class="post-metadata">

**Author:** ![Serge\_van\_Ginderacht](https://avatars.discourse-cdn.com/v4/letter/s/b782af/32.png) [@Serge\_van\_Ginderacht](https://forum.ansible.com/u/Serge_van_Ginderacht)\
**Post date:** [March 4, 2014, 12:31pm UTC](https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669/11 "2014-03-04T12:31:10Z")

</div>

​I'm not sure what you mean here?

A host can be member of a group; a group can be member of another group,  
etc.​

---

<div class="post-metadata">

**Author:** ![anatoly\_techtonik](https://avatars.discourse-cdn.com/v4/letter/a/c67d28/32.png) [@anatoly\_techtonik](https://forum.ansible.com/u/anatoly_techtonik)\
**Post date:** [March 4, 2014, 12:31pm UTC](https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669/12 "2014-03-04T12:31:40Z")

</div>

So, information about subgroups is not available, right?  
[http://docs.ansible.com/intro\_inventory.html#groups-of-groups-and-group-variables](http://docs.ansible.com/intro_inventory.html#groups-of-groups-and-group-variables)

So this is not parsed:

[atlanta]  
host1  
host2

[raleigh]  
host2  
host3

[southeast:children]  
atlanta  
raleigh

And it is impossible to build:

host3 ---\> raleigh ---\> southeast \<--- atlanta \<--- host1  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\<---- host2------\>

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [March 4, 2014, 12:33pm UTC](https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669/13 "2014-03-04T12:33:24Z")

</div>

Unless I’m mistaken, which I shouldn’t be as I wrote the code, this isn’t actually the case.

[https://github.com/ansible/ansible/blob/devel/lib/ansible/inventory/group.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/inventory/group.py)

There is “parent\_group” information kept on every group object, which is also what “get\_ancestors” returns.

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [March 4, 2014, 12:34pm UTC](https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669/14 "2014-03-04T12:34:01Z")

</div>

It’s available and quite possible.

---

<div class="post-metadata">

**Author:** ![Serge\_van\_Ginderacht](https://avatars.discourse-cdn.com/v4/letter/s/b782af/32.png) [@Serge\_van\_Ginderacht](https://forum.ansible.com/u/Serge_van_Ginderacht)\
**Post date:** [March 4, 2014, 1:12pm UTC](https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669/15 "2014-03-04T13:12:56Z")

</div>

B​ut, keep in mind that 'parent\_group' is a flat list of \*all\* ancestors,  
not only the direct parent above of which a group is a child​, which would  
make it hard for the op to reconstruct the full tree relation of groups.

For the OP's example, for

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parents = group.get\_ancestors()

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print '%s (depth %s): parents: %s' % (group.name,  
group.depth, ['%s (depth %s)' % (x.name, x.depth) for x in parents])

you get this

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;all (depth 0): parents:   
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;atlanta (depth 2): parents: ['southeast (depth 1)', 'all (depth 0)']  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raleigh (depth 2): parents: ['southeast (depth 1)', 'all (depth 0)']  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;southeast (depth 1): parents: ['all (depth 0)']

​So you have to take into account the depth value of each group.  
Also, for larger, complex trees, sourced from different inventory files or  
scripts spread over different directories, this depth value is sometimes  
wrong.

&nbsp;&nbsp;&nbsp;&nbsp;Serge​

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [March 4, 2014, 1:20pm UTC](https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669/16 "2014-03-04T13:20:10Z")

</div>

Curious. A bit of an artifact of the needs of the system to just feed input into Ansible, for sure.

Seems like it would be easier to just should fix the glitch in the object so the group object remembers it’s direct parents in that case.

That way everybody can make use of it.

---

<div class="post-metadata">

**Author:** ![Serge\_van\_Ginderacht](https://avatars.discourse-cdn.com/v4/letter/s/b782af/32.png) [@Serge\_van\_Ginderacht](https://forum.ansible.com/u/Serge_van_Ginderacht)\
**Post date:** [March 4, 2014, 1:36pm UTC](https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669/17 "2014-03-04T13:36:54Z")

</div>

​That's a very big +1 from me.

&nbsp;&nbsp;Serge​

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [March 4, 2014, 1:39pm UTC](https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669/18 "2014-03-04T13:39:33Z")

</div>

Somebody send in a patch 🙂

---

<div class="post-metadata">

**Author:** ![Serge\_van\_Ginderacht](https://avatars.discourse-cdn.com/v4/letter/s/b782af/32.png) [@Serge\_van\_Ginderacht](https://forum.ansible.com/u/Serge_van_Ginderacht)\
**Post date:** [March 5, 2014, 6:06pm UTC](https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669/19 "2014-03-05T18:06:44Z")

</div>

I dug into the code, and got some feedback for you

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [March 6, 2014, 1:41am UTC](https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669/20 "2014-03-06T01:41:07Z")

</div>

> I dug into the code, and got some feedback for you
> 
> > > There is "parent\_group" information kept on every group object, which is  
> > > also what "get\_ancestors" returns.
> 
> Actually,  
> you are right that  
> parent\_group contains the direct parents,  
> but  
> get\_ancestors will also return all grandparents.

This part seems good.

> Except when using the dir.py, where parent\_group is filled from  
> group.get\_ancestors instead of group.parent\_groups  
> , which is a bug there
> 
> Got a patch for that in  
> my  
> queue.

Excellent!

> But, keep in mind that 'parent\_group' is a flat list of \*all\*
> 
> > ancestors, not only the direct parent above of which a group is a child,  
> > which would make it hard for the op to reconstruct the full tree relation  
> > of groups.
> 
> So this remark is actually based on a bug when using a directory as the  
> inventory. Easy fix.
> 
> Anothe  
> r  
> thing I noticed, is that ini.py and script.py both will add every single  
> group - regardless of it's location in the 'tree' - to the default 'all'  
> group, which is also shown in my previous example, where the all group is  
> listed in parent\_groups of every group:
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;all (depth 0): parents:
> 
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;atlanta (depth 2): parents: ['southeast (de
> > 
> > pth 1)', 'all (depth 0)']  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raleigh (depth 2): parents: ['southeast (depth 1)', 'all (depth 0)']  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;southeast (depth 1): parents: ['all (depth 0)']
> 
> How I t  
> h  
> ink of it, is actually only groups with depth == 1 should be (direct)  
> child's of the all group. Resolving all groups and hosts for a group  
> and host  
> is done elsewhere.

yeah that seems suboptimal and weird in the code, but also not causing of  
damage. Fine if we fix as it will make classes displaying the inventory  
more sensical (as this was trying to do about the graph)

> I  
> made  
> a patch to update that in the ini code, still need to do that for the  
> script code.
> 
> And whilst at this, I had a look at the calculation of the depth  
> parameter, and improved it by updating it for every grandchild, when  
> updating a new child group.
> 
> I also noticed groups and hosts sometimes get duplicated in certain object  
> lists, and added some checks for that too.
> 
> From the op's example, I now get a much cleaner output:
> 
> serge@goldorak:~$ ansible-vars -i h --list-groups --list-hosts  
> (0) all . . . . . . . . . . . . . . . . . . . . . .( parents: )  
> + (1) ungrouped . . . . . . . . . . . . . . . . . .( parents: all(0) )  
> + (1) southeast . . . . . . . . . . . . . . . . . .( parents: all(0) )  
> ++ (2) atlanta . . . . . . . . . . . . . . . . . .( parents: southeast(1) )  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ [host1,host2]  
> ++ (2) raleigh . . . . . . . . . . . . . . . . . .( parents: southeast(1) )  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_ [host2,host3]
> 
> (whereas previously you would also see hosts in eg the southeast group)  
> From here it will be far simpler to do some kind of tree-ish output.

Yay! (Yep, it is technically a graph, FWIW... but tree-ish would be  
appropriate for something that is not quite a tree 🙂 )

> Still need to do dome more tests, and check the scripts behaviour.  
> Will do a PR later.
> 
> If someone's sees a problem so far, please y  
> ell 🙂 Especially I'd like feedback about the option to (not) put  
> \*every\* group as a direct child of the parent.

We should fix this and I don't think it will hurt anything, as long as the  
tests for inventory still pass and all that good stuff.

> In the mean time I'm happy I got this tree as I always wanted it.

Happy Little Trees!

(Not sure if you get Bob Ross reruns in Europe)

[Next page](https://forum.ansible.com/t/generate-ascii-graph-of-topology-based-on-inventory/14669.md?page=2)
