nixos/programs/gnome-session: add top-level systemd namespace for systemd-specific options

Also included a little refactor.
This commit is contained in:
Gabriel Arazas 2024-08-21 18:51:57 +08:00
parent 23b2be907f
commit 03f51384cf
No known key found for this signature in database
GPG Key ID: 62104B43D00AA360
3 changed files with 150 additions and 137 deletions

View File

@ -107,20 +107,20 @@ let
pathToUnit serviceToUnit targetToUnit timerToUnit socketToUnit; pathToUnit serviceToUnit targetToUnit timerToUnit socketToUnit;
mkSystemdUnits = name: component: { mkSystemdUnits = name: component: {
"${component.id}.service" = serviceToUnit component.serviceUnit; "${component.id}.service" = serviceToUnit component.systemd.serviceUnit;
"${component.id}.target" = targetToUnit component.targetUnit; "${component.id}.target" = targetToUnit component.systemd.targetUnit;
} // lib.optionalAttrs (component.socketUnit != null) { } // lib.optionalAttrs (component.systemd.socketUnit != null) {
"${component.id}.socket" = socketToUnit component.socketUnit; "${component.id}.socket" = socketToUnit component.systemd.socketUnit;
} // lib.optionalAttrs (component.timerUnit != null) { } // lib.optionalAttrs (component.systemd.timerUnit != null) {
"${component.id}.timer" = timerToUnit component.timerUnit; "${component.id}.timer" = timerToUnit component.systemd.timerUnit;
} // lib.optionalAttrs (component.pathUnit != null) { } // lib.optionalAttrs (component.systemd.pathUnit != null) {
"${component.id}.path" = pathToUnit component.pathUnit; "${component.id}.path" = pathToUnit component.systemd.pathUnit;
}; };
componentsUnits = lib.concatMapAttrs mkSystemdUnits session.components; componentsUnits = lib.concatMapAttrs mkSystemdUnits session.components;
in in
componentsUnits // { componentsUnits // {
"gnome-session@${session.name}.target" = targetToUnit session.targetUnit; "gnome-session@${session.name}.target" = targetToUnit session.systemd.targetUnit;
} }
) )
cfg.sessions; cfg.sessions;

View File

@ -1,10 +1,13 @@
{ name, config, pkgs, lib, utils, session, ... }: { name, config, pkgs, lib, utils, session, ... }:
let let
optionalSystemdUnitOption = type: systemdModuleAttribute: optionalSystemdUnitOption = {
unitType, systemdModuleAttribute, otherType,
}:
lib.mkOption { lib.mkOption {
type = lib.types.nullOr otherType;
description = '' description = ''
An optional systemd ${type} configuration to be generated. This should An optional systemd ${unitType} configuration to be generated. This should
be configured if the session is managed by systemd. be configured if the session is managed by systemd.
:::{.note} :::{.note}
@ -73,106 +76,114 @@ in
}; };
}; };
# Most of the systemd config types are trying to eliminate as much of the systemd = {
# NixOS systemd extensions as much as possible. For more details, see # Most of the systemd config types are trying to eliminate as much of the
# `config` attribute of the `sessionType`. # NixOS systemd extensions as much as possible. For more details, see
serviceUnit = lib.mkOption { # `config` attribute of the `sessionType`.
type = serviceUnit = lib.mkOption {
let type =
inherit (utils.systemdUtils.lib) unitConfig serviceConfig; let
inherit (utils.systemdUtils.unitOptions) commonUnitOptions serviceOptions; inherit (utils.systemdUtils.lib) unitConfig serviceConfig;
in inherit (utils.systemdUtils.unitOptions) commonUnitOptions serviceOptions;
lib.types.submodule [ in
commonUnitOptions lib.types.submodule [
serviceOptions commonUnitOptions
serviceConfig serviceOptions
unitConfig serviceConfig
]; unitConfig
description = '' ];
systemd service configuration to be generated. This should be description = ''
configured if the session is managed by systemd. systemd service configuration to be generated. This should be
configured if the session is managed by systemd.
:::{.note} :::{.note}
This has the same options as {option}`systemd.user.services.<name>` This has the same options as {option}`systemd.user.services.<name>`
but without certain options from stage 2 counterparts such as but without certain options from stage 2 counterparts such as
`reloadTriggers` and `restartTriggers`. `reloadTriggers` and `restartTriggers`.
By default, this module sets the service unit as part of the respective By default, this module sets the service unit as part of the respective
target unit (i.e., `PartOf=$COMPONENTID.target`). target unit (i.e., `PartOf=$COMPONENTID.target`).
On a typical case, you shouldn't mess with much of the dependency On a typical case, you shouldn't mess with much of the dependency
ordering of the service unit. You should configure `targetUnit` for ordering of the service unit. You should configure `targetUnit` for
that instead. that instead.
::: :::
''; '';
default = { }; default = { };
visible = "shallow"; visible = "shallow";
}; };
targetUnit = lib.mkOption { targetUnit = lib.mkOption {
type = type =
let let
inherit (utils.systemdUtils.lib) unitConfig; inherit (utils.systemdUtils.lib) unitConfig;
inherit (utils.systemdUtils.unitOptions) commonUnitOptions; inherit (utils.systemdUtils.unitOptions) commonUnitOptions;
in in
lib.types.submodule [ lib.types.submodule [
commonUnitOptions commonUnitOptions
unitConfig unitConfig
]; ];
description = '' description = ''
systemd target configuration to be generated. This should be systemd target configuration to be generated. This should be
configured if the session is managed by systemd. configured if the session is managed by systemd.
:::{.note} :::{.note}
This has the same options as {option}`systemd.user.targets.<name>` This has the same options as {option}`systemd.user.targets.<name>`
but without certain options from stage 2 counterparts such as but without certain options from stage 2 counterparts such as
`reloadTriggers` and `restartTriggers`. `reloadTriggers` and `restartTriggers`.
This module doesn't set the typical dependency ordering relative to This module doesn't set the typical dependency ordering relative to
gnome-session targets. This is on the user to manually set them. gnome-session targets. This is on the user to manually set them.
::: :::
''; '';
default = { }; default = { };
visible = "shallow"; visible = "shallow";
}; };
timerUnit = optionalSystemdUnitOption "timer" "timers" // { timerUnit = optionalSystemdUnitOption {
type = unitType = "timer";
let systemdModuleAttribute = "timers";
inherit (utils.systemdUtils.unitOptions) timerOptions commonUnitOptions; otherType =
inherit (utils.systemdUtils.lib) unitConfig; let
in inherit (utils.systemdUtils.unitOptions) timerOptions commonUnitOptions;
with lib.types; nullOr (submodule [ inherit (utils.systemdUtils.lib) unitConfig;
commonUnitOptions in
timerOptions lib.types.submodule [
unitConfig commonUnitOptions
]); timerOptions
}; unitConfig
];
};
socketUnit = optionalSystemdUnitOption "socket" "sockets" // { socketUnit = optionalSystemdUnitOption {
type = unitType = "socket";
let systemdModuleAttribute = "sockets";
inherit (utils.systemdUtils.unitOptions) socketOptions commonUnitOptions; otherType =
inherit (utils.systemdUtils.lib) unitConfig; let
in inherit (utils.systemdUtils.unitOptions) socketOptions commonUnitOptions;
with lib.types; nullOr (submodule [ inherit (utils.systemdUtils.lib) unitConfig;
commonUnitOptions in
socketOptions lib.types.submodule [
unitConfig commonUnitOptions
]); socketOptions
}; unitConfig
];
};
pathUnit = optionalSystemdUnitOption "path" "paths" // { pathUnit = optionalSystemdUnitOption {
type = unitType = "path";
let systemdModuleAttribute = "paths";
inherit (utils.systemdUtils.unitOptions) pathOptions commonUnitOptions; otherType =
inherit (utils.systemdUtils.lib) unitConfig; let
in inherit (utils.systemdUtils.unitOptions) pathOptions commonUnitOptions;
with lib.types; nullOr (submodule [ inherit (utils.systemdUtils.lib) unitConfig;
commonUnitOptions in
pathOptions lib.types.submodule [
unitConfig commonUnitOptions
]); pathOptions
unitConfig
];
};
}; };
id = lib.mkOption { id = lib.mkOption {
@ -235,7 +246,7 @@ in
systemd user unit, much of them are unnecessary and rarely needed (if systemd user unit, much of them are unnecessary and rarely needed (if
ever like `Service.PrivateTmp=`?) so we didn't set such defaults here. ever like `Service.PrivateTmp=`?) so we didn't set such defaults here.
*/ */
serviceUnit = { systemd.serviceUnit = {
script = lib.mkAfter config.script; script = lib.mkAfter config.script;
description = lib.mkDefault config.description; description = lib.mkDefault config.description;
@ -282,7 +293,7 @@ in
likely for a user to design their own desktop session with full control likely for a user to design their own desktop session with full control
so it would be better for these options to be empty for less confusion. so it would be better for these options to be empty for less confusion.
*/ */
targetUnit = { systemd.targetUnit = {
# This should be the dependency-related directive to be configured. The # This should be the dependency-related directive to be configured. The
# rest is for the user to judge. # rest is for the user to judge.
wants = [ "${config.id}.service" ]; wants = [ "${config.id}.service" ];

View File

@ -184,40 +184,42 @@ in
]; ];
}; };
targetUnit = lib.mkOption { systemd = {
type = targetUnit = lib.mkOption {
let type =
inherit (utils.systemdUtils.lib) unitConfig; let
inherit (utils.systemdUtils.unitOptions) commonUnitOptions; inherit (utils.systemdUtils.lib) unitConfig;
in inherit (utils.systemdUtils.unitOptions) commonUnitOptions;
lib.types.submodule [ in
commonUnitOptions lib.types.submodule [
unitConfig commonUnitOptions
]; unitConfig
description = '' ];
systemd target configuration to be generated for description = ''
`gnome-session@<name>.target`. This should be configured if the systemd target configuration to be generated for
session is managed by systemd and you want to control the session `gnome-session@<name>.target`. This should be configured if the
further (which is recommended since this module don't know what session is managed by systemd and you want to control the session
components are more important, etc.). further (which is recommended since this module don't know what
components are more important, etc.).
By default, the session target will have all of its components from By default, the session target will have all of its components from
{option}`<session>.requiredComponents` under `Wants=` directive. It {option}`<session>.requiredComponents` under `Wants=` directive. It
also assumes all of them have a target unit at also assumes all of them have a target unit at
`''${requiredComponent}.target`. `''${requiredComponent}.target`.
:::{.note} :::{.note}
This has the same options as {option}`systemd.user.targets.<name>` This has the same options as {option}`systemd.user.targets.<name>`
but without certain options from stage 2 counterparts such as but without certain options from stage 2 counterparts such as
`reloadTriggers` and `restartTriggers`. `reloadTriggers` and `restartTriggers`.
::: :::
''; '';
visible = "shallow"; visible = "shallow";
defaultText = '' defaultText = ''
{ {
wants = ... # All of the required components as a target unit. wants = ... # All of the required components as a target unit.
} }
''; '';
};
}; };
}; };
@ -225,7 +227,7 @@ in
# Append the session argument. # Append the session argument.
extraArgs = [ "--session=${name}" ]; extraArgs = [ "--session=${name}" ];
targetUnit = { systemd.targetUnit = {
overrideStrategy = lib.mkForce "asDropin"; overrideStrategy = lib.mkForce "asDropin";
wants = lib.mkDefault (builtins.map (c: "${c}.target") config.requiredComponents); wants = lib.mkDefault (builtins.map (c: "${c}.target") config.requiredComponents);
}; };