Search code examples
salt-project

Saltstack retrieve IP address using mine.get


Am trying to create a template where it will retrieve the IP address of consul servers as DNS using mine.get. On command line it seems to work fine, but when used in the template context its not returning anything

Here is my setup

In /srv/pillar I added mines.sls and modified top.sls as following

mines.sls

mine_functions:
  network.ip_addrs: []

top.sls

base:
  '*':
    - mines

After refreshing pillars and using mine.send and mine.update, I could query from saltmaster server the IP addresses for consul

sudo salt 'redis*' mine.get 'consul*' network.ip_addrs
redis-001-stage.c.project-gce.internal:
    ----------
    consul-001-adm.c.project-gce.internal:
        - 192.16.0.1
    consul-002-adm.c.project-gce.internal:
        - 192.16.0.2

I tried to apply the same principle in a state file using templates

# Resolver Configuration
resolv-file:
  file.managed:
    - name: /etc/resolv.conf
    - user: root
    - group: root
    - mode: '0644'
    - source: salt://resolver/files/resolv.conf
    - template: jinja
    - defaults:
        nameservers: {{ salt['mine.get']('*', 'network.ip_addrs', 'eth1').items() }}

and in resolve.conf

{%- for nameserver in nameservers %}
nameserver {{ nameserver }}
{%- endfor %}

but the nameservers always coming up empty, can someone advise please?


Solution

  • You've been passing the interface name eth1 as the third parameter to mine.get, but this parameter is used for the matching type you want to have for the first parameter.

    Leave it out and you'll retrieve a list of the IP addresses. Once this returns values, I didn't manage to pass the full list of addresses to the jinja template. Instead I evaluated the mine.get inside the resolv.conf template.

    This got me working:

    resolv-file:
      file.managed:
        - name: /tmp/resolv.conf
        - source: salt://resolv.conf
        - template: jinja
    

    and then

    {%- for server, addr in salt['mine.get']('*', 'network.ip_addrs').items() %}
    nameserver {{ addr[0] }} # {{ server }}
    {%- endfor %}
    

    By the way: you could also choose to run a consul agent locally and forward the DNS requests specific to consul to your local consul agent (that in turn resolves them from the service directory). Using dnsmasq and Network Manager this might look like this script I uploaded to Github.