Question

Our saltstack is based on hostnames (webN., dbN., etc.). But for various things I need IPs of those servers. For now I had them stored in pillars, but the number of places I need to sync grows.

I tried to use publish + network.ip_addrs, but that kinda sucks, because it needs to do the whole salt-roundtrip just to resolve a hostname. Also it's dependent on the minions responding. Therefore I'm looking for a way to resolve hostname to IP in templates.

I assume that I could write a module for it somehow, but my python skills are very limited.

Was it helpful?

Solution

You could use a custom grain. Create file _grains/fqdn_ip.py in the state tree directory:

import socket

def fqdn_ip():
    return {
        'fqdn_ip': socket.gethostbyname(socket.getfqdn())
    }

In template:

{{ grains.fqdn_ip }}

Another way is use dnsutil module (requires dig command on minion):

{{ salt['dnsutil.A']('host.name.tld')[0] }}

OTHER TIPS

I've see this: http://cnygaard.blogspot.com.es/2012/11/how-to-template-eth0-address-with.html

This is the easy way that I've found.

#init.sls:

...
...

/etc/swift/proxy-server.conf:              
   file:
     - managed                              
     - source: salt://swift/proxy-server.conf
     - template: jinja
     - context:
         proxy_ip: {{ salt['network.interfaces']()['eth0']['inet'][0]['address'] }}

And then:

#In proxy-server.conf

...

[filter:cache]
use = egg:swift#memcache
memcache_servers = {{ proxy_ip }}:11211

This is a very old post, but it is highly ranked in Google for getting the ipv4 address. As of salt 2015.5.8, the best way to get the primary ipv4 address is {{ grains['ipv4'][0] }}.

Reading through the ansible documentation, I found a much simpler solution. Here are my results.

enter the following into the template:

lookup hostname: {{ lookup('dig', 'google.ca.') }}

My jinja2 template:

# mytemplate.j2
## lookup directly
lookup hostname: {{ lookup('dig', 'google.ca.') }}

## in a variable
{% set fqdn = 'google.ca' %}
lookup hostname: {{ lookup('dig', fqdn) }}

Result:

# mytemplate.j2
## lookup directly
lookup hostname: 172.217.2.163

## in a variable
lookup hostname: 172.217.2.163

Currently - to aggregate a list of all ip addresses requires either salt-mine or interrogating all minions. I prefer salt-mine.

There is an accepted issue to extend the new roster system to maintain addresses of all minions, not just ssh based hosts. https://github.com/saltstack/salt/issues/7759

Just a reminder, you always can pass it from Flask app.

import os

host = os.uname()[1]

return render_template("template.html", host=host)

If you need to get IPs that are not available in grains, do not want to setup custom grains and need those IPs to be dynamically resolved in your pillars ( typically to setup the firewall, network interfaces, BGP to the host, etc. ) you can proceed as follow:

Let's say you have:

  • idrac-hostname.domain
  • management-hostname.domain
  • hostname.domain

Then you can just resolv them using the dig modules from SaltStack

{% set fqdn = salt['grains.get']('fqdn') %}
{% set idrac = 'idrac-' ~ fqdn %}

{% set idrac_ip = salt['dig.A'](idrac)[0] %}
{% set main_ip = salt['dig.A'](fqdn)[0] %}

Hope it helps

Ref: https://docs.saltproject.io/en/latest/ref/modules/all/salt.modules.dig.html

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top