# Aggregating role facts

**URL:** <https://forum.ansible.com/t/aggregating-role-facts/13859>\
**Category:** Ansible Project\
**Created:** [November 7, 2013, 6:48am UTC](https://forum.ansible.com/t/aggregating-role-facts/13859 "2013-11-07T06:48:22Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Stephen\_Gargan](https://avatars.discourse-cdn.com/v4/letter/s/c67d28/32.png) [@Stephen\_Gargan](https://forum.ansible.com/u/Stephen_Gargan)\
**Post date:** [November 7, 2013, 6:48am UTC](https://forum.ansible.com/t/aggregating-role-facts/13859/1 "2013-11-07T06:48:22Z")

</div>

I’ve a pattern that I want to apply and I’m wondering what the best practice might be for this. I have a situation where I apply a number of roles to a host and each have a number of facts or variables that I’d like to use in a final role, typically to generate a unified config for the host.

Say I’m applying a number of roles say a, b, c that are all distinct, but each exposes a set of metrics in a uniform way. As each gets played, I’d like to add facts about the metrics for the role in such a way that I can iterate over them in a final role d to generate some aggregate config to expose all the metrics.

I have a number of situations that I’d like to apply this pattern so if there is a standard way to do this I’d love to hear it.

If not, I have been mulling over extending the set\_fact module to allow something like the following  
Say each role could add a dictionary of values to an aggregate collection, aggregated\_facts, so that in d I could do

{% for addedFactsForRole in aggregated\_facts %}  
// processing facts for key addedFactsForRole.key  
{% for addedFact in addedFactsForRole.facts %}  
// process addedFact.name  
// process addedFact.value  
{% endfor %}  
{% endfor %}

I have used group variables to do something similar, but this tends to get crufty as it means replicating the data in every site that I use the role and I like to be able to have very generic roles that I can reuse in different sites. If the list could dynamically built like this it would be arguably more cohesive as now I could define all of the data for the role, within the role, and still have the ability to override it at the site level with group vars.

I’m thinking the task definition might look something like this.

name: Add metrics to metrics aggregate  
add\_fact: group=host\_metrics key=$role\_key fact=$item  
with\_items: $list\_of\_metrics

In the case above the list\_of\_metrics could be a list of single entries or a list of json blobs. I don’t want to go re-inventing the wheel, this seems like a common enough scenario so I’m very curious how folks tackle it, before I go about putting this together.

Thanks in advance,

Steve.

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan2](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@Michael\_DeHaan2](https://forum.ansible.com/u/Michael_DeHaan2)\
**Post date:** [November 10, 2013, 9:23pm UTC](https://forum.ansible.com/t/aggregating-role-facts/13859/2 "2013-11-10T21:23:53Z")

</div>

Not sure what a role fact is. Role variables I’d assume?

“Say I’m applying a number of roles say a, b, c that are all distinct, but each exposes a set of metrics in a uniform way.”

This seems very very abstract. What is a non-distinct role? What is a metric?

---

<div class="post-metadata">

**Author:** ![Stephen\_Gargan](https://avatars.discourse-cdn.com/v4/letter/s/c67d28/32.png) [@Stephen\_Gargan](https://forum.ansible.com/u/Stephen_Gargan)\
**Post date:** [November 11, 2013, 1:54am UTC](https://forum.ansible.com/t/aggregating-role-facts/13859/3 "2013-11-11T01:54:57Z")

</div>

> Not sure what a role fact is. Role variables I’d assume?

Yes they are essentially variables. I just want to be able to aggregate them under a common variable name as each role is executed so that in final role execution I can use all the aggregated variables in a template.

“Say I’m applying a number of roles say a, b, c that are all distinct, but each exposes a set of metrics in a uniform way.”

This seems very very abstract. What is a non-distinct role? What is a metric?

What I meant is that they are all different e.g. if they were java, A could be tomcat, B could be jboss, C could be a custom JVM process, but they all would expose ‘metrics’ or other data uniformly using JMX. My role D would take the aggregated ‘metrics’ specified by A, B, & C and create a config (in this case for jmxtrans) to forward them to graphite.

A better example might be ports, A exposes 8080, B 9090, C 1234. They would add these ports to a an aggregate variable “exposed\_ports” that a firewall role D would use to create an aggregate firewall config. These exposed ports would be useful as ‘facts’ for the host as it is something that other hosts might interested in.

I know at the site level I can make a variable

exposed\_ports:

- 8080
- 9090
- 1234

But i’d prefer to have the role add their ports dynamically as each role is applied so that If a role doesn’t get played its ports don’t get exposed.

I’ve put together an add\_fact module similar to what I described above. I’m just tiding up the templating and will post a fuller example that illustrates what I’m thinking.

thanks,

Steve.

---

<div class="post-metadata">

**Author:** ![Stephen\_Gargan](https://avatars.discourse-cdn.com/v4/letter/s/c67d28/32.png) [@Stephen\_Gargan](https://forum.ansible.com/u/Stephen_Gargan)\
**Post date:** [November 11, 2013, 6:14pm UTC](https://forum.ansible.com/t/aggregating-role-facts/13859/4 "2013-11-11T18:14:41Z")

</div>

Michael,

I’ve put together an implementation for an add\_facts command a couple of examples that show what it might be useful for here [https://github.com/sgargan/ansible-add-facts-examples](https://github.com/sgargan/ansible-add-facts-examples). I think it explains the intention of the command a little better and gives a concrete example of the pattern I was attempting to explain above. I’m interested to hear what your thoughts are.

thanks,

Steve.

---

<div class="post-metadata">

**Author:** ![Ned\_McClain](https://avatars.discourse-cdn.com/v4/letter/n/9de0a6/32.png) [@Ned\_McClain](https://forum.ansible.com/u/Ned_McClain)\
**Post date:** [July 31, 2014, 12:51am UTC](https://forum.ansible.com/t/aggregating-role-facts/13859/5 "2014-07-31T00:51:37Z")

</div>

Stephen,

I also desperately need a set\_facts that works with with\_items. Have you had any response to these excellent use-case examples?

Ned.

---

<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:** [July 31, 2014, 10:41pm UTC](https://forum.ansible.com/t/aggregating-role-facts/13859/6 "2014-07-31T22:41:40Z")

</div>

So that’s a very old thread you’ve replied to, can you paste an example of what you are wishing to do?

---

<div class="post-metadata">

**Author:** ![Ned\_McClain](https://avatars.discourse-cdn.com/v4/letter/n/9de0a6/32.png) [@Ned\_McClain](https://forum.ansible.com/u/Ned_McClain)\
**Post date:** [July 31, 2014, 10:53pm UTC](https://forum.ansible.com/t/aggregating-role-facts/13859/7 "2014-07-31T22:53:36Z")

</div>

Definitely - I desire to have different roles append firewall rules (strings) to a single fact dictionary. The final role will apply those generic rules to the appropriate iptables/ufw/ec2 security group based on the host’s OS and cloud provider. Allowing each role to append their own rules to the fact is a highly compostable solution. It abstracts role-provided firewall rules from the host OS and hosting environments those roles are applied to.

I stumbled across Steven’s super-detailed example that described the use case(s) very clearly:  
[https://github.com/sgargan/ansible-add-facts-examples](https://github.com/sgargan/ansible-add-facts-examples)

To me, the current outcome of using “set\_fact” along with “with\_items” very much defies the “Principle of least surprise”. I was sure surprised.

Note this request is in NO WAY for new “programming language” functionality in Ansible - this is simply a request to make “set\_fact” work in the least surprising way when used with “with\_items”.

Thanks for considering this,

Ned.

---

<div class="post-metadata">

**Author:** ![Stephen\_Gargan](https://avatars.discourse-cdn.com/v4/letter/s/c67d28/32.png) [@Stephen\_Gargan](https://forum.ansible.com/u/Stephen_Gargan)\
**Post date:** [July 31, 2014, 11:02pm UTC](https://forum.ansible.com/t/aggregating-role-facts/13859/8 "2014-07-31T23:02:25Z")

</div>

Ned,

There are better patterns for sharing data that what I’d originally suggested. As your system grows this approach gets untenable. If you need to share data variable files are a far more flexible solution.

As Michael says, if you post another thread explaining of what you’re trying to we’ll gladly help you out.

Thanks,

Steve.

---

<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:** [July 31, 2014, 11:52pm UTC](https://forum.ansible.com/t/aggregating-role-facts/13859/9 "2014-07-31T23:52:58Z")

</div>

I’m open to making set\_fact work with with\_items (pull request welcome).

not having tested it recently - I’m actually surprised it didn’t 🙂

---

<div class="post-metadata">

**Author:** ![Ned\_McClain](https://avatars.discourse-cdn.com/v4/letter/n/9de0a6/32.png) [@Ned\_McClain](https://forum.ansible.com/u/Ned_McClain)\
**Post date:** [August 1, 2014, 4:00pm UTC](https://forum.ansible.com/t/aggregating-role-facts/13859/10 "2014-08-01T16:00:21Z")

</div>

Michael, Stephen,

I appreciate you taking the time to respond to this old thread, and for your thoughts, and for all your hard work on Ansible.

I will work on a PR for this.

Ned.

---

<div class="post-metadata">

**Author:** ![Stephen\_Gargan](https://avatars.discourse-cdn.com/v4/letter/s/c67d28/32.png) [@Stephen\_Gargan](https://forum.ansible.com/u/Stephen_Gargan)\
**Post date:** [August 1, 2014, 6:23pm UTC](https://forum.ansible.com/t/aggregating-role-facts/13859/11 "2014-08-01T18:23:23Z")

</div>

Can’t take any credit, I’m just a very content user is all. Good luck with your PR.
