Search code examples
jinja2salt-project

How do I use the IP addresses of machines matching a grain in a Salt State file


I'm creating a formula/state file that adds an iptables rule:

ipt_allow:
  iptables.append:
    - table: filter
    - chain: INPUT
    - jump: ACCEPT
    - match: state
    - connstate: 'NEW,ESTABLISHED'
    - dport: 6666
    - proto: tcp
    - source: 'ip1, ip2, ip3, ...'

I don't want to hard code the IP addresses in source. ip1, ip2, and ip3 are the IP addresses of minions that match the grain role:role1. That way, if I ever add more minions with the grain role1 down the road, they'll get added to the iptables rule once I rerun this state file. How do I do this?


Solution

  • Got it. This can be done using Salt mine functions.

    1. /srv/pillar/mines.sls:

      mine_functions:
        network.ip_addrs:
          - eth1
      

      This makes the network.ip_addrs available to the master and minions, specifically the eth1 interface.

    2. /srv/pillar/top.sls:

      base:
        '*':
          - mines
      

      This applies the pillar (hence the mine function) to all the minions.

    3. Now you can use the mine.get function in your state files to call that mine function. This is what I used in my case:

      {% for server, addrs in salt['mine.get']('role:role1', 'network.ip_addrs', expr_form='grain').items() %}
      ipt_allow_{{ server }}:
        iptables.append:
          - table: filter
          - chain: INPUT
          - jump: ACCEPT
          - match: state
          - connstate: 'NEW,ESTABLISHED'
          - dport: 6666
          - proto: tcp
          - source: {{ addrs[0] }}
      {% endfor %}
      

      Where:

      • salt['mine.get'] calls the mine.get function,
      • ('role:role1', 'network.ip_addrs', expr_form='grain').items() tells the function to match minions that have role1 as the value of role which is a grain (expr_form='grain') and get its network.ip_addrs.
      • The output is the matched minion id (I believe) and the result of network.ip_addrs, so we store that in server and addrs.
      • The for loop loops goes around creating a new ID every time using the value in {{ server }} and substituting the IP address in {{ addrs[0] }}.

    Links that helped: