diff --git a/CHANGELOG.rst b/CHANGELOG.rst index a1170e1..df4002d 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,10 +1,18 @@ ===================================== -sebastian.systemd 0.4.0 Release Notes +sebastian.systemd 0.4.2 Release Notes ===================================== .. contents:: Topics +v0.4.2 +====== + +Changelog +--------- + +upgraded to the new method used by sebastian.base + v0.4.0 ====== diff --git a/changelogs/changelog.yaml b/changelogs/changelog.yaml index daa392e..9847f7c 100644 --- a/changelogs/changelog.yaml +++ b/changelogs/changelog.yaml @@ -66,3 +66,7 @@ releases: release_date: "2024-02-24" changes: release_summary: added timer module + 0.4.2: + release_date: "2024-03-09" + changes: + release_summary: upgraded to the new method used by sebastian.base diff --git a/galaxy.yml b/galaxy.yml index df87a58..3cc93d3 100644 --- a/galaxy.yml +++ b/galaxy.yml @@ -1,7 +1,7 @@ --- namespace: sebastian name: systemd -version: 0.4.1 +version: 0.4.2 readme: README.md @@ -13,7 +13,7 @@ tags: - systemd - linux dependencies: - sebastian.base: ">=0.3.1" + sebastian.base: ">=0.4.0" repository: https://gitea.sebastian-tobie.de/ansible/ansible-systemd.git # documentation: http://docs.example.com homepage: https://gitea.sebastian-tobie.de/ansible/ansible-systemd diff --git a/plugins/modules/link.py b/plugins/modules/link.py index 10ed8a5..2103e4e 100644 --- a/plugins/modules/link.py +++ b/plugins/modules/link.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 import pathlib -from typing import List +from typing import List, Optional try: from ansible_module.module_utils.generic import SYSTEMD_NETWORK_CONFIG, Types, modspec @@ -54,10 +54,10 @@ class Module(SystemdUnitModule): # type: ignore def unit(self) -> str: if self.__unit is None: - self.__unit = "\n".join((self.match(), self.link())) + self.__unit = self._unit(self.match(), self.link()) return self.__unit - def match(self) -> str: + def match(self) -> Optional[str]: options = self.map_param( mac="MACAddress", permanentmac="PermanentAddress", @@ -67,9 +67,11 @@ class Module(SystemdUnitModule): # type: ignore kind="Kind", virtualization="Virtualization", ) + if len(options) == 0: + return None return "[Match]\n" + "".join(options) - def link(self) -> str: + def link(self) -> Optional[str]: options = [] if self.get("description", False): options.append("Description={}\n".format(self.get("description", False))) @@ -77,6 +79,8 @@ class Module(SystemdUnitModule): # type: ignore options.append("Name={}\n".format(self.get("name", False))) if self.get("mtu", False): options.append("MTUBytes={}\n".format(self.get("mtu", False))) + if len(options) == 0: + return None return "[Link]\n" + "".join(options) def post(self): diff --git a/plugins/modules/mount.py b/plugins/modules/mount.py index 2021213..b6f9afd 100644 --- a/plugins/modules/mount.py +++ b/plugins/modules/mount.py @@ -18,7 +18,7 @@ OPTION_MAPPING = dict( @installable -class Module(SystemdUnitModule, SystemdReloadMixin): # type: ignore +class Module(SystemdUnitModule, SystemdReloadMixin): # type: ignore[misc] """Creates an systemd mount""" name = "mount" @@ -45,26 +45,25 @@ class Module(SystemdUnitModule, SystemdReloadMixin): # type: ignore def unit(self) -> str: if self.__unit is None: - self.__unit = "\n".join( - ( - self.header(), - self.mount(), - self.install(), - ) + self.__unit = self._unit( + self.header(), + self.mount(), + self.install(), # type: ignore[misc,call-arg] ) return self.__unit def header(self) -> str: - return "[Unit]\nDescription={}\n".format(self.get("description", "Mount for {}".format(self.get("where")))) + description = self.get("description", "Mount for {}".format(self.get("where"))) + return f"[Unit]\nDescription={description}\n" def mount(self) -> str: - output = "[Mount]\n" - output += "Where={}\n".format(self.get("where")) - output += "What={}\n".format(self.get("what")) - output += "Type={}\n".format(self.get("fs")) + options = [] + options.append("Where={}\n".format(self.get("where"))) + options.append("What={}\n".format(self.get("what"))) + options.append("Type={}\n".format(self.get("fs"))) if self.get("options", False): - output += "Options={}\n".format(",".join(self.get("options"))) - return output + options.append("Options={}\n".format(",".join(self.get("options")))) + return "[Mount]\n" + "".join(options) DOCUMENTATION = """--- diff --git a/plugins/modules/netdev.py b/plugins/modules/netdev.py index 648fb9f..ec1ce04 100644 --- a/plugins/modules/netdev.py +++ b/plugins/modules/netdev.py @@ -75,55 +75,65 @@ class Module(SystemdUnitModule): parts = [self.match(), self.netdev()] if kind != "dummy": parts.append(getattr(self, kind)()) - self.__unit = "\n".join(parts) + self.__unit = self._unit(*parts) return self.__unit - def match(self) -> str: + def match(self) -> Optional[str]: options = self.map_param( host="Host", kernelcmd="KernelCommandLine", virtualization="Virtualization", ) + if len(options) == 0: + return None return "[Match]\n" + "".join(options) - def netdev(self) -> str: + def netdev(self) -> Optional[str]: options = self.map_param( description="Description", name="Name", kind="Kind", ) + if len(options) == 0: + return None return "[NetDev]\n" + "".join(options) - def bond(self) -> str: - return "[Bond]\n" + "".join( - self.map_param( - mode="Mode", - minlinks="MinLinks", - ) + def bond(self) -> Optional[str]: + options = self.map_param( + mode="Mode", + minlinks="MinLinks", ) + if len(options) == 0: + return None + return "[Bond]\n" + "".join(options) - def bridge(self) -> str: - return "[Bridge]\n" + "".join( - self.map_param( - stp="STP", - priority="Priority", - ) + def bridge(self) -> Optional[str]: + options = self.map_param( + stp="STP", + priority="Priority", ) + if len(options) == 0: + return None + return "[Bridge]\n" + "".join(options) - def wireguard(self) -> str: + def wireguard(self) -> Optional[str]: + options = self.map_param( + privatekey="PrivateKey", + privatekeyfile="PrivateKeyFile", + port="ListenPort", + ) port = self.get("port", False) if port not in (False, "auto") and (port < 1 or port > 65535): raise ValueError("Port must be between 0 and 65536") - return "[Wireguard]\n" + "".join( - self.map_param( - privatekey="PrivateKey", - privatekeyfile="PrivateKeyFile", - port="ListenPort", - ) - ) + if len(options) == 0: + return None + return "[Wireguard]\n" + "".join(options) - def vlan(self) -> str: - return "" + def vlan(self) -> Optional[str]: + options: list[str] = [] + if len(options) == 0: + return None + return "[Vlan]\n" + "".join(options) DOCUMENTATION = """--- diff --git a/plugins/modules/network.py b/plugins/modules/network.py index 5337b18..27d7cf4 100644 --- a/plugins/modules/network.py +++ b/plugins/modules/network.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 import pathlib -from typing import List, Union +from typing import List, Union, Optional try: from ansible_module.module_utils.generic import SYSTEMD_NETWORK_CONFIG, Types, modspec, systemdbool @@ -36,7 +36,7 @@ class Module(SystemdUnitModule): # type: ignore ), masquerade=Types.str( help="how the packets are modified to look like the come from the computer itself.", - choices=("true", "false", "both", "ipv4", "ipv6"), + choices=("true", "false", "both", "ipv4", "ipv6", "no"), ), ), required_if=(("defaultdns", True, ("dns",), False),), @@ -49,56 +49,46 @@ class Module(SystemdUnitModule): # type: ignore def unit(self) -> str: if self.__unit is None: - self.__unit = "\n".join( - ( - self.match(), - self.network(), - self.addresses(), - self.routes(), - ) + self.__unit = self._unit( + self.match(), + self.network(), + self.addresses(), + self.routes(), ) return self.__unit - def match(self) -> str: - matches = [] - return "[Match]\n" + "".join( - self.map_param( - mac="MACAddress", - device="Name", - virtualization="Virtualization", - ) + def match(self) -> Optional[str]: + matches = self.map_param( + mac="MACAddress", + device="Name", + virtualization="Virtualization", ) + if len(matches) == 0: + return None + return "[Match]\n" + "".join(matches) - def network(self) -> str: - output = "[Network]\n" + def network(self) -> Optional[str]: options = [] - try: + if self.get("description", None) is None: 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))) + server: str + for server in self.get("dns", []): + options.append(f"DNS={server}") + options.append("DNSDefaultRoute={}".format(self.get("defaultdns", False))) + if self.get("domain", False): + options.append("Domains={}".format(" ".join(self.get("domain")))) options.append("DNSOverTLS={}".format(systemdbool(self.get("dot", "opportunistic")))) options.append("DNSSEC={}".format(systemdbool(self.get("dnssec", "allow-downgrade")))) - except KeyError: - pass - if self.get("masquerade", -1) != -1: - masquerade = self.get("masquerade") + if self.get("masquerade", None) is not None: + masquerade: str = self.get("masquerade") if masquerade == "true": masquerade = "both" elif masquerade == "false": masquerade = "no" options.append(f"IPMasquerade={masquerade}") - output += "\n".join(options) - return output + if len(options) == 0: + return None + return "[Network]\n" + "".join(options) def addresses(self) -> str: output = [] @@ -106,13 +96,13 @@ class Module(SystemdUnitModule): # type: ignore output.append(f"[Address]\nAddress={address}\n") return "\n".join(output) - def routes(self) -> str: + def routes(self) -> Optional[str]: output = [] - routes = self.get("route", []) - self.set("routes", routes) + routes: list[str] = self.get("route", []) for gw in routes: output.append(f"[Route]\nGateway={gw}\nGatewayOnLink=yes\nQuickAck=yes\n") - self.set("routes", output) + if len(output) == 0: + return None return "\n".join(output) @@ -205,6 +195,7 @@ options: - both - ipv4 - ipv6 + - 'no' description: - how the packets are modified to look like the come from the computer itself. required: false diff --git a/plugins/modules/socket.py b/plugins/modules/socket.py index 5c61d6c..e968c15 100644 --- a/plugins/modules/socket.py +++ b/plugins/modules/socket.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 import pathlib -from typing import List, Union +from typing import List, Union, Optional try: from ansible_module.module_utils.generic import SYSTEMD_SERVICE_CONFIG, Types, modspec @@ -47,29 +47,26 @@ class Module(SystemdUnitModule, SystemdReloadMixin): # type: ignore self.unitfile = (SYSTEMD_SERVICE_CONFIG / self.get("name")).with_suffix(".socket") self.__unit = None - def socket(self): - section = "[Socket]\n" - section += "".join( - self.map_param( - stream="ListenStream", - datagram="ListenDatagram", - sequential="ListenSequential", - fifo="ListenFIFO", - socketuser="SocketUser", - socketgroup="SocketGroup", - socketmode="SocketMode", - ) + def socket(self) -> Optional[str]: + section = self.map_param( + stream="ListenStream", + datagram="ListenDatagram", + sequential="ListenSequential", + fifo="ListenFIFO", + socketuser="SocketUser", + socketgroup="SocketGroup", + socketmode="SocketMode", ) - return section + if len(section) == 0: + return None + return "[Socket]\n" + "".join(section) def unit(self) -> str: if self.__unit is None: - self.__unit = "\n".join( - ( - self.header(), - self.socket(), - self.install(), - ) + self.__unit = self._unit( + self.header(), + self.socket(), + self.install(), # type: ignore[call-arg,misc] ) return self.__unit diff --git a/plugins/modules/system_service.py b/plugins/modules/system_service.py index 6d824e2..ef34a78 100644 --- a/plugins/modules/system_service.py +++ b/plugins/modules/system_service.py @@ -11,7 +11,7 @@ except ImportError: @installable -class Module(SystemdUnitModule, SystemdReloadMixin): +class Module(SystemdUnitModule, SystemdReloadMixin): # type: ignore[misc] """Creates System Services units""" name = "system_service" @@ -95,8 +95,7 @@ class Module(SystemdUnitModule, SystemdReloadMixin): if self.get("type", "simple") != "oneshot" and len(self.get("start")) > 1: self.module.fail_json("only oneshot services are allowed to have multiple start commands", **self.result) - def service(self): - section = "[Service]\n" + def service(self) -> str: params = [] if self.get("environment", False): for env in self.get("environment"): @@ -122,17 +121,14 @@ class Module(SystemdUnitModule, SystemdReloadMixin): nonewprivileges="NoNewPriviledges", ) ) - section += "".join(params) - return section + return "[Service]\n" + "".join(params) def unit(self) -> str: if self.__unit is None: - self.__unit = "\n".join( - ( - self.header(), - self.service(), - self.install(), - ) + self.__unit = self._unit( + self.header(), + self.service(), + self.install(), # type: ignore[call-arg,misc] ) return self.__unit @@ -246,7 +242,7 @@ options: pre: default: [] description: - - command or list of commands that are started before the main command(Types.str) + - command or list of commands that are started before the main command elements: str required: false type: list diff --git a/plugins/modules/target.py b/plugins/modules/target.py index 5979d11..e3d450b 100644 --- a/plugins/modules/target.py +++ b/plugins/modules/target.py @@ -13,7 +13,7 @@ __module_name__ = "TargetModule" @installable -class TargetModule(SystemdUnitModule, SystemdReloadMixin): +class TargetModule(SystemdUnitModule, SystemdReloadMixin): # type: ignore[misc] """Creates Target units""" name = "target" @@ -35,16 +35,16 @@ class TargetModule(SystemdUnitModule, SystemdReloadMixin): def header(self) -> str: section = super().header() + if section is None: + section = "[Unit]\n" section += "AllowIsolate={}\n".format(systemdbool(self.get("allow_isolate", False))) return section def unit(self) -> str: if self.__unit is None: - self.__unit = "\n".join( - ( - self.header(), - self.install(), - ) + self.__unit = self._unit( + self.header(), + self.install(), # type: ignore[call-arg,misc] ) return self.__unit diff --git a/plugins/modules/timer.py b/plugins/modules/timer.py index c4a10a5..168ac1d 100644 --- a/plugins/modules/timer.py +++ b/plugins/modules/timer.py @@ -14,7 +14,7 @@ __module_name__ = "TimerModule" @installable -class TimerModule(SystemdUnitModule, SystemdReloadMixin): # type: ignore +class TimerModule(SystemdUnitModule, SystemdReloadMixin): # type: ignore[misc] """Creates Timer units""" name = "timer" @@ -56,14 +56,14 @@ class TimerModule(SystemdUnitModule, SystemdReloadMixin): # type: ignore unit=Types.str(help="The name of the unit. only needed if its not {{name}}.service"), ), required_one_of=[ - [ + ( "onactive", "onboot", "onstartup", "onunitactive", "onunitinactive", "oncalendar", - ], + ), ], ) @@ -82,19 +82,23 @@ class TimerModule(SystemdUnitModule, SystemdReloadMixin): # type: ignore onunitactive="OnUnitActiveSec", onunitinactive="OnUnitInactiveSec", oncalendar="OnCalendar", + persistent="Persistent", + randomdelay="RandomizedDelaySec", + fixdelay="FixedRandomDelay", + unit="Unit", ), ) + if len(params) == 0: + return None section += "".join(params) return section def unit(self) -> str: if self.__unit is None: - self.__unit = "\n".join( - ( - self.header(), - self.body(), - self.install(), - ) + self.__unit = self._unit( + self.header(), + self.body(), + self.install(), # type: ignore[call-arg,misc] ) return self.__unit diff --git a/pyproject.toml b/pyproject.toml index b65dbad..1424062 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,4 +4,7 @@ line-length = 140 [tool.isort] atomic = true profile = "black" -line_length = 140 \ No newline at end of file +line_length = 140 + +[tool.mypy] +disable_error_code = ["import-untyped", "no-redef", "attr-defined"]