411 Zeilen
14 KiB
Python
411 Zeilen
14 KiB
Python
#!/usr/bin/python3
|
|
import pathlib
|
|
from typing import List, Union
|
|
|
|
try:
|
|
from ansible_module.module_utils.generic import SYSTEMD_SERVICE_CONFIG, Types
|
|
from ansible_module.module_utils.module import SystemdReloadMixin, SystemdUnitModule, installable
|
|
except ImportError:
|
|
from ansible_collections.sebastian.base.plugins.module_utils.generic import SYSTEMD_SERVICE_CONFIG, Types
|
|
from ansible_collections.sebastian.base.plugins.module_utils.module import SystemdReloadMixin, SystemdUnitModule, installable
|
|
|
|
|
|
@installable
|
|
class Module(SystemdUnitModule, SystemdReloadMixin): # type: ignore[misc]
|
|
"""Creates System Services units"""
|
|
|
|
name = "system_service"
|
|
module_spec = dict(
|
|
argument_spec=dict(
|
|
name=Types.str(required=True, help="Name of the service"),
|
|
serviceuser=Types.str(help="Username of under which the commands run at.", default="root"),
|
|
servicegroup=Types.str(help="Group of under which the commands run at.", default="root"),
|
|
type=Types.str(
|
|
choices=("simple", "exec", "forking", "oneshot", "dbus", "notify", "notify-reload", "idle"),
|
|
default="simple",
|
|
help="Type of the systemd service.\n"
|
|
"simple and exec start long running services that run in the same process over the whole time, exec is waiting until the process was started completly.\n"
|
|
"forking does some things in the foreground, starts an background process and then exits to leave the work to the background process.\n"
|
|
"oneshot processes are started by systemd, do their work and then exit, similar to cronjobs.\n"
|
|
"dbus services will be considered started up once they aquire the specified dbus bus"
|
|
"notify and notify-reload notify systemd about the start up via sd_notify. notify-reload needs also inform systemd on reloads and when it is ready again after an reload.\n"
|
|
"idle is similar to simple, but it can delay the start up by a few seconds.",
|
|
),
|
|
pre=Types.list(elements=str, help="command or list of commands that are started before the main command"),
|
|
start=Types.list(
|
|
elements=str,
|
|
required=True,
|
|
help="command or list of commands that are started as main programm. Multiple commands are only allowed in a oneshot command",
|
|
),
|
|
stop=Types.str(help="command that is started to stop the main program."),
|
|
remain=Types.bool(help="should the service remain as started after the command exited"),
|
|
post=Types.list(str, help="Command or list of commands that are started after the main command(s) stopped without problems."),
|
|
environmentfile=Types.list(
|
|
elements=str,
|
|
help="List of file that are containing environment variables. They are evaluated before each pre/start/post command",
|
|
),
|
|
environment=Types.list(
|
|
elements=Types.dict(
|
|
name=Types.str(help="name of the Environment variable", required=True),
|
|
value=Types.str(help="value of the Environment variable", required=True),
|
|
),
|
|
help="List of environment variables that are set to each command before they run",
|
|
),
|
|
workingdirectory=Types.str(
|
|
help="The Directory that is used for the processes as current working directory",
|
|
),
|
|
rwpath=Types.list(
|
|
elements=Types.path(),
|
|
help="Path(s) that are readable and writable (if permission allow)",
|
|
),
|
|
ropath=Types.list(
|
|
elements=Types.path(),
|
|
help="Path(s) that are read only",
|
|
),
|
|
notreadablepath=Types.list(
|
|
elements=Types.path(),
|
|
help="Path(s) that are not accessible by the applications",
|
|
),
|
|
execpath=Types.list(
|
|
elements=Types.path(),
|
|
help="Path(s) where executable files are",
|
|
),
|
|
noexecpath=Types.list(
|
|
elements=Types.path(),
|
|
help="Path(s) which are never executable (uploaded files, user accessible paths)",
|
|
),
|
|
protecthome=Types.str(
|
|
help="if true makes user specific directories (/home, /root, /run/user) inaccessible. read-only makes them read only and tmpfs is useful to create binds in it",
|
|
choices=("true", "false", "read-only", "tmpfs"),
|
|
),
|
|
protectsystem=Types.str(
|
|
help="makes the system read only. if true /usr, /boot and /efi are read only, if full additionally /etc and if strict all except /proc, /sys and /dev",
|
|
choices=("true", "false", "full", "strict"),
|
|
),
|
|
nonewprivileges=Types.bool(
|
|
help="disables the ability to get new capabilities for processes than already granted ones",
|
|
),
|
|
statedirectory=Types.str(
|
|
help="creates an unit specific state directory in /var/lib and sets the env var STATE_DIRECTORY with the path to it. Its cleaned up after the unit is stopped"
|
|
),
|
|
runtimedirectory=Types.str(
|
|
help="creates an unit specific runtime directory in /run and sets the env var RUNTIME_DIRECTORY with the path to it. Its cleaned up after the unit is stopped"
|
|
),
|
|
restart=Types.str(),
|
|
restartsec=Types.str(),
|
|
),
|
|
)
|
|
|
|
def prepare(self):
|
|
self.unitfile = (SYSTEMD_SERVICE_CONFIG / self.get("name")).with_suffix(".service")
|
|
self.__unit = None
|
|
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) -> str:
|
|
params = []
|
|
if self.get("environment", False):
|
|
for env in self.get("environment"):
|
|
params.append(f"Environment={env['name']}={env['value']}\n")
|
|
params.extend(
|
|
self.map_param(
|
|
type="Type",
|
|
pre="ExecStartPre",
|
|
start="ExecStart",
|
|
stop="ExecStop",
|
|
post="ExecStartPost",
|
|
serviceuser="User",
|
|
servicegroup="Group",
|
|
workingdirectory="WorkingDirectory",
|
|
environmentfile="EnvironmentFile",
|
|
protecthome="ProtectHome",
|
|
protectsystem="ProtectSystem",
|
|
rwpath="ReadWritePaths",
|
|
ropath="ReadOnlyPaths",
|
|
notreadablepath="InaccessiblePaths",
|
|
execpath="ExecPaths",
|
|
noexecpath="NoExecPaths",
|
|
statedirectory="StateDirectory",
|
|
runtimedirectory="RuntimeDirectory",
|
|
nonewprivileges="NoNewPriviledges",
|
|
remain="RemainAfterExit",
|
|
restart="Restart",
|
|
restartsec="RestartSec",
|
|
)
|
|
)
|
|
return "[Service]\n" + "".join(params)
|
|
|
|
def unit(self) -> str:
|
|
if self.__unit is None:
|
|
self.__unit = self._unit(
|
|
self.header(),
|
|
self.service(),
|
|
self.install(), # type: ignore[call-arg,misc]
|
|
)
|
|
return self.__unit
|
|
|
|
|
|
DOCUMENTATION = """---
|
|
description:
|
|
- Creates System Services units
|
|
module: system_service
|
|
options:
|
|
after:
|
|
default: []
|
|
description:
|
|
- list of units that this unit wants to be started after this unit
|
|
elements: str
|
|
required: false
|
|
type: list
|
|
before:
|
|
default: []
|
|
description:
|
|
- list of units that this unit needs to be started before this unit.
|
|
elements: str
|
|
required: false
|
|
type: list
|
|
description:
|
|
description:
|
|
- An description for programs that access systemd
|
|
required: false
|
|
type: str
|
|
documentation:
|
|
default: []
|
|
description:
|
|
- Paths where documentation can be found
|
|
elements: str
|
|
required: false
|
|
type: list
|
|
environment:
|
|
default: []
|
|
description:
|
|
- List of environment variables that are set to each command before they run
|
|
elements: dict
|
|
options:
|
|
name:
|
|
description:
|
|
- name of the Environment variable
|
|
required: true
|
|
type: str
|
|
value:
|
|
description:
|
|
- value of the Environment variable
|
|
required: true
|
|
type: str
|
|
required: false
|
|
type: list
|
|
environmentfile:
|
|
default: []
|
|
description:
|
|
- List of file that are containing environment variables. They are evaluated before
|
|
each pre/start/post command
|
|
elements: str
|
|
required: false
|
|
type: list
|
|
execpath:
|
|
default: []
|
|
description:
|
|
- Path(s) where executable files are
|
|
elements: path
|
|
required: false
|
|
type: list
|
|
name:
|
|
description:
|
|
- Name of the service
|
|
required: true
|
|
type: str
|
|
noexecpath:
|
|
default: []
|
|
description:
|
|
- Path(s) which are never executable (uploaded files, user accessible paths)
|
|
elements: path
|
|
required: false
|
|
type: list
|
|
nonewprivileges:
|
|
description:
|
|
- disables the ability to get new capabilities for processes than already granted
|
|
ones
|
|
required: false
|
|
type: bool
|
|
notreadablepath:
|
|
default: []
|
|
description:
|
|
- Path(s) that are not accessible by the applications
|
|
elements: path
|
|
required: false
|
|
type: list
|
|
partof:
|
|
default: []
|
|
description:
|
|
- list of units that this unit is part of.
|
|
- If the restart this unit does it too, but if this restarts it does not affect
|
|
the other units.
|
|
elements: str
|
|
required: false
|
|
type: list
|
|
post:
|
|
default: []
|
|
description:
|
|
- Command or list of commands that are started after the main command(s) stopped
|
|
without problems.
|
|
elements: str
|
|
required: false
|
|
type: list
|
|
pre:
|
|
default: []
|
|
description:
|
|
- command or list of commands that are started before the main command
|
|
elements: str
|
|
required: false
|
|
type: list
|
|
protecthome:
|
|
choices:
|
|
- 'true'
|
|
- 'false'
|
|
- read-only
|
|
- tmpfs
|
|
description:
|
|
- if true makes user specific directories (/home, /root, /run/user) inaccessible.
|
|
read-only makes them read only and tmpfs is useful to create binds in it
|
|
required: false
|
|
type: str
|
|
protectsystem:
|
|
choices:
|
|
- 'true'
|
|
- 'false'
|
|
- full
|
|
- strict
|
|
description:
|
|
- makes the system read only. if true /usr, /boot and /efi are read only, if full
|
|
additionally /etc and if strict all except /proc, /sys and /dev
|
|
required: false
|
|
type: str
|
|
remain:
|
|
description:
|
|
- should the service remain as started after the command exited
|
|
required: false
|
|
type: bool
|
|
required_by:
|
|
default: []
|
|
description:
|
|
- systemd units that require this mount
|
|
elements: str
|
|
required: false
|
|
type: list
|
|
requires:
|
|
default: []
|
|
description:
|
|
- list of units that this unit requires. If it fails or can't be started this
|
|
unit fails. without before/after this is started at the same time
|
|
elements: str
|
|
required: false
|
|
type: list
|
|
restart:
|
|
required: false
|
|
type: str
|
|
restartsec:
|
|
required: false
|
|
type: str
|
|
ropath:
|
|
default: []
|
|
description:
|
|
- Path(s) that are read only
|
|
elements: path
|
|
required: false
|
|
type: list
|
|
runtimedirectory:
|
|
description:
|
|
- creates an unit specific runtime directory in /run and sets the env var RUNTIME_DIRECTORY
|
|
with the path to it. Its cleaned up after the unit is stopped
|
|
required: false
|
|
type: str
|
|
rwpath:
|
|
default: []
|
|
description:
|
|
- Path(s) that are readable and writable (if permission allow)
|
|
elements: path
|
|
required: false
|
|
type: list
|
|
servicegroup:
|
|
default: root
|
|
description:
|
|
- Group of under which the commands run at.
|
|
required: false
|
|
type: str
|
|
serviceuser:
|
|
default: root
|
|
description:
|
|
- Username of under which the commands run at.
|
|
required: false
|
|
type: str
|
|
start:
|
|
description:
|
|
- command or list of commands that are started as main programm. Multiple commands
|
|
are only allowed in a oneshot command
|
|
elements: str
|
|
required: true
|
|
type: list
|
|
statedirectory:
|
|
description:
|
|
- creates an unit specific state directory in /var/lib and sets the env var STATE_DIRECTORY
|
|
with the path to it. Its cleaned up after the unit is stopped
|
|
required: false
|
|
type: str
|
|
stop:
|
|
description:
|
|
- command that is started to stop the main program.
|
|
required: false
|
|
type: str
|
|
type:
|
|
choices:
|
|
- simple
|
|
- exec
|
|
- forking
|
|
- oneshot
|
|
- dbus
|
|
- notify
|
|
- notify-reload
|
|
- idle
|
|
default: simple
|
|
description:
|
|
- Type of the systemd service.
|
|
- simple and exec start long running services that run in the same process over
|
|
the whole time, exec is waiting until the process was started completly.
|
|
- forking does some things in the foreground, starts an background process and
|
|
then exits to leave the work to the background process.
|
|
- oneshot processes are started by systemd, do their work and then exit, similar
|
|
to cronjobs.
|
|
- dbus services will be considered started up once they aquire the specified dbus
|
|
busnotify and notify-reload notify systemd about the start up via sd_notify.
|
|
notify-reload needs also inform systemd on reloads and when it is ready again
|
|
after an reload.
|
|
- idle is similar to simple, but it can delay the start up by a few seconds.
|
|
required: false
|
|
type: str
|
|
wanted_by:
|
|
default: []
|
|
description:
|
|
- systemd units that want the mount, but not explicitly require it. Commonly used
|
|
for target if not service explicitly require it.
|
|
elements: str
|
|
required: false
|
|
type: list
|
|
wants:
|
|
default: []
|
|
description:
|
|
- list of units that this unit wants. If it fails or can't be started it does
|
|
not affect this unit
|
|
elements: str
|
|
required: false
|
|
type: list
|
|
workingdirectory:
|
|
description:
|
|
- The Directory that is used for the processes as current working directory
|
|
required: false
|
|
type: str
|
|
short_description: Creates System Services units
|
|
"""
|
|
|
|
if __name__ == "__main__":
|
|
Module()()
|