Ansible template data structure for dnsmasq.conf?

Hi,

I’m currently writing an Ansible role for automatically setting up Dnsmasq on my routerboard running Rocky Linux.

Here’s the actual dnsmasq.conf which I setup manually:

# /etc/dnsmasq.conf
domain-needed
bogus-priv
interface=enp2s0
dhcp-range=192.168.2.100,192.168.2.200,24h
local=/microlinux.lan/
domain=microlinux.lan
expand-hosts
#server=208.67.222.123
#server=208.67.220.123
#server=8.8.8.8
#server=8.8.4.4
server=1.1.1.1
server=1.0.0.1
no-resolv
log-facility=/var/log/dnsmasq.log
address=/proxy.microlinux.lan/192.168.2.1
address=/rocky-el8.microlinux.lan/192.168.2.10
dhcp-host=50:65:F3:4E:DA:77,alphamule,192.168.2.2
dhcp-host=B0:83:FE:90:4D:64,sandbox,192.168.2.3
dhcp-host=68:54:5A:B2:D0:81,dell-xps,192.168.2.4
dhcp-host=D0:37:45:24:61:BD,44:37:E6:DA:44:72,gustave,192.168.2.5
dhcp-host=3C:DC:BC:00:FB:97,smartphone-nico,192.168.2.6
dhcp-host=AC:AF:B9:D6:93:FA,smartphone-clothilde,192.168.2.7
dhcp-host=52:54:00:00:00:01,testbox-el8,192.168.2.10
dhcp-host=52:54:00:00:00:02,testbox-el9,192.168.2.11
dhcp-host=D4:85:64:B2:B2:1B,oldmule,192.168.2.249
dhcp-host=00:22:64:8A:4C:C2,nestor,192.168.2.250
dhcp-host=00:0D:B9:4B:5B:5C,squidbox,192.168.2.251
dhcp-host=10:62:E5:D4:95:60,hp-officejet,192.168.2.252
dhcp-host=00:11:32:26:63:A5,nas,192.168.2.253

And here’s the corresponding /etc/hosts file:

# /etc/hosts
127.0.0.1     localhost.localdomain localhost
192.168.2.1   proxy.microlinux.lan  proxy
192.168.2.2   alphamule
192.168.2.3   sandbox
192.168.2.4   dell-xps
192.168.2.5   gustave
192.168.2.6   smartphone-nico
192.168.2.7   smartphone-clothilde
192.168.2.10  testbox-el8
192.168.2.11  testbox-el9
192.168.2.249 oldmule
192.168.2.250 nestor
192.168.2.251 squidbox
192.168.2.252 hp-officejet
192.168.2.253 nas
192.168.2.254 wifi

For now my playbook for Ansible looks like this:

    - name: Configure hosts file
      ansible.builtin.template:
        src: hosts.j2
        dest: /etc/hosts

    - name: Install Dnsmasq
      ansible.builtin.dnf:
        name: dnsmasq
        state: present

    - name: Enable and start Dnsmasq
      ansible.builtin.service:
        name: dnsmasq
        enabled: true
        state: started

    - name: Configure Dnsmasq
      ansible.builtin.template:
        src: dnsmasq.conf.j2
        dest: /etc/dnsmasq.conf
      notify: Restart Dnsmasq

    - meta: flush_handlers

Here’s the hosts.j2 file:

# /etc/hosts
127.0.0.1 localhost.localdomain localhost
{{address_lan}} {{hostname}}.{{domain_lan}} {{hostname}}

And here’s the dnsmasq.conf.j2 file (using a different network for testing purposes):

# /etc/dnsmasq.conf
domain-needed
bogus-priv
interface={{interface_lan}}
dhcp-range=192.168.3.100,192.168.3.200,24h
local=/{{domain_lan}}/
domain={{domain_lan}}
expand-hosts
server={{dns1}}
server={{dns2}}
no-resolv
log-facility=/var/log/dnsmasq.log
address=/{{hostname}}.{{domain_lan}}/{{address_lan}}

As you can see in the example above, I have a series of clients (sandbox, dell-xps, gustave and so on) each with a corresponding local IP address as well as a MAC address.

Note that the client gustave has two MAC addresses since it can connect by wired interface or by wireless.

Now I could very well hardcode all these clients into my dnsmasq.conf.j2 and hosts.j2 templates.

There’s a slight redundancy here, due to the fact that Dnsmasq needs hostnames in /etc/hosts.

But I think a more elegant solution would be to use variables. And now I wonder how the data structure could look like here. I bluntly admit I’m not very proficient with nested dictionaries, nested lists, lists of dictionaries and dictionaries of lists etc.

How could I write a data structure for these client machines to put in my template ?

Cheers,

Niki

You are looking for list of dictionaries .

Your data structure could look like:

static_dhcp_leases:
  - mac: "50:65:F3:4E:DA:77"
    hostname: alphamule
    ip: 192.168.2.2
  - mac: "B0:83:FE:90:4D:64"
    hostname: sandbox
    ip: 192.168.2.3

Then you could use for loop to generate the result:

{% for lease in static_dhcp_leases %}
dhcp-host={{ lease.mac }},{{ lease.hostname }},{{ lease.ip }}
{% endfor %}
2 Likes

Thank you very much !