Search code examples
jinja2salt-project

Get minions IP inside a salt template filtered by grains


I found this answer here that tells how to get the IP of another minions inside a template but i can't get host.fqdn or host.ip. When I use host I get the full domain name and not the IP. When I ran it on console it gets the ips, but inside the template it does return a str object

Unable to manage file: Jinja variable 'str object' has no attribute 'fqdn'

I tried this one here but this one didn't even show a result.

I want to be able to build a hosts file. Each minion have some roles set as grains, like this:

roles:
  - backend
  - cdn
  - ...

I want to be able to get all roles:backend and not roles:cdn. But when I added this line to my publish.publish I get this error:

Unable to manage file: Jinja error: 'NoneType' object is not iterable

I don't know what I am doing wrong, I added the peer publish on master but it doesn't work. I've read the docs and they don't help me find the problem.

EDIT Versions report

   $ salt-minion --versions-report
                 Salt: 2015.5.3
               Python: 2.7.6 (default, Mar 22 2014, 22:59:56)
               Jinja2: 2.7.2
             M2Crypto: 0.21.1
       msgpack-python: 0.3.0
         msgpack-pure: Not Installed
             pycrypto: 2.6.1
              libnacl: Not Installed
               PyYAML: 3.10
                ioflo: Not Installed
                PyZMQ: 14.0.1
                 RAET: Not Installed
                  ZMQ: 4.0.4
                 Mako: Not Installed
              Tornado: Not Installed
Debian source package: 2015.5.3+ds-1trusty1

EDIT 2 the sls snippet

{% for host in salt['publish.publish']('roles:backend', 'network.ip_addrs', 'eth0', 'grain') %}
  server {{ host.ip }}; # {{ host.fqdn }}
{% endfor %}

Solution

  • Found the solution:

    Inside a minion config add this piece of code:

    mine_interval: 2
    mine_functions:
      network.ip_addrs:
        - eth1 # or any other eth-n you might want
    

    To match all backends and not the load_balancers we need a compound matcher

    G@roles:backend and not G@roles:load_balancer
    

    After that just put it all together in the template using salt.mine

    {%- for server, addrs in salt['mine.get']('G@roles:backend and not G@roles:load_balancer', 'network.ip_addrs', 'compound').items() %}
      # {{ server }}
      server {{ addrs|last }};
    {%- endfor %}