#!/usr/bin/python3 import pathlib from typing import List, Union from ansible.module_utils.generic import SYSTEMD_NETWORK_CONFIG as SYSTEMD_PATH from ansible.module_utils.generic import Types from ansible.module_utils.module import SystemdUnitModule def boolconvert(b: Union[bool, str]) -> str: if b is True: return "yes" elif b is False: return "no" return b class Module(SystemdUnitModule): """Sets up the systemd network unit""" name = "systemd_network" module_spec = dict( argument_spec=dict( mac=Types.str(), device=Types.str(), name=Types.str(required=True), description=Types.str(), dot=Types.bool(), dnssec=Types.bool(), dns=Types.list(elements=str), domain=Types.list(elements=str), defaultdns=Types.bool(), address=Types.list(elements=str, required=True), route=Types.list(elements=str), ), required_if=(("defaultdns", True, ("dns",), False),), required_one_of=(("mac", "device"),), ) def prepare(self): self.unitfile = SYSTEMD_PATH.joinpath(self.get("name")).with_suffix(".network") self.__unit = None def unit(self) -> str: if self.__unit is None: self.__unit = "\n".join( ( self.match(), self.network(), self.addresses(), self.routes(), ) ) return self.__unit def match(self) -> str: matches = [] if self.get("mac", False): matches.append("MACAddress={}\n".format(self.get("mac"))) if self.get("device", False): matches.append("Name={}\n".format(self.get("device"))) return "[Match]\n" + "".join(matches) def network(self) -> str: output = "[Network]\n" options = [] try: options.append("Description={}".format(self.get("description"))) except KeyError: pass try: for server in self.get("dns", []): options.append(f"DNS={server}") options.append("DNSDefaultRoute={}".format(self.get("defaultdns", False))) except KeyError: pass try: domain = self.get("domain") self.set("domainlog", str(domain)) options.append("Domains={}".format(" ".join(domain))) options.append( "DNSOverTLS={}".format(boolconvert(self.get("dot", "opportunistic"))) ) options.append( "DNSSEC={}".format(boolconvert(self.get("dnssec", "allow-downgrade"))) ) except KeyError: pass output += "\n".join(options) return output def addresses(self) -> str: output = [] for address in self.get("address"): output.append(f"[Address]\nAddress={address}\n") return "\n".join(output) def routes(self) -> str: output = [] routes = self.get("route", []) self.set("routes", routes) for gw in routes: output.append(f"[Route]\nGateway={gw}\nGatewayOnLink=yes\nQuickAck=yes\n") self.set("routes", output) return "\n".join(output) DOCUMENTATION = """--- description: - Sets up the systemd network unit module: systemd_network options: address: elements: str required: true type: list defaultdns: required: false type: bool description: required: false type: str dns: default: [] elements: str required: false type: list dnssec: required: false type: bool domain: default: [] elements: str required: false type: list dot: required: false type: bool name: required: true type: str mac: elements: str required: true type: list route: default: [] elements: str required: false type: list short_description: Sets up the systemd network unit """ if __name__ == "__main__": Module()()