users/services: s6: push bundle dependencies down onto the actual atomic services

This commit is contained in:
Colin 2024-03-23 13:04:12 +00:00
parent 8008fd35cb
commit 4418c16967
2 changed files with 33 additions and 46 deletions

View File

@ -134,17 +134,6 @@ let
};
};
};
defaultUserOptions = with lib; {
options = userOptions.options // {
services = mkOption {
# map to listOf attrs so that we can pass through
# w/o worrying about merging at this layer (TODO: this is probably not necessary with s6)
type = types.attrsOf (types.coercedTo types.attrs (a: [ a ]) (types.listOf types.attrs));
default = {};
inherit (userOptions.options.services) description;
};
};
};
userModule = let
nixConfig = config;
in with lib; types.submodule ({ name, config, ... }: {
@ -201,6 +190,18 @@ let
set +a
done
'';
services."default" = {
description = "service (bundle) which is started by default upon login";
};
services."graphical-session" = {
description = "service (bundle) which is started upon successful graphical login";
# partOf = [ "default" ]; #< leave it to the DEs to set this
};
services."sound" = {
description = "service (bundle) which represents functional sound input/output when active";
partOf = [ "default" ];
};
}
];
});
@ -241,7 +242,7 @@ in
};
sane.user = mkOption {
type = types.nullOr (types.submodule defaultUserOptions);
type = types.nullOr (types.submodule userOptions);
default = null;
description = ''
options to pass down to the default user

View File

@ -94,6 +94,7 @@ let
exec ${check}
'';
};
# N.B.: if this service is a bundle, then dependencies.d is ignored
"dependencies.d".dir = lib.genAttrs
depends
(dep: { text = ""; })
@ -168,44 +169,29 @@ let
})
services
;
# in the systemd service management, these targets are implicitly defined and used
# to accomplish something like run-levels, or service groups.
# map them onto s6 "bundles". their contents are determined via finding every other service which declares itself to be `partOf` this one.
implicitServices = {
"default" = {
command = null;
check = null;
cleanupCommand = null;
depends = [];
dependencyOf = [];
partOf = [];
readiness.waitCommand = null;
};
"graphical-session" = {
command = null;
check = null;
cleanupCommand = null;
depends = [];
dependencyOf = [];
partOf = [];
readiness.waitCommand = null;
};
"sound" = {
command = null;
check = null;
cleanupCommand = null;
depends = [];
dependencyOf = [];
partOf = [ "default" ];
readiness.waitCommand = null;
};
};
# return a list of bundles (AttrSets) which contain this service
containedBy = services: name: lib.filter (svc: lib.elem name svc.contents) services;
# for each bundle to which this service belongs, add that bundle's dependencies as direct dependencies of this service.
# this is to overcome that s6 doesn't support bundles having dependencies.
pushDownDependencies = services: builtins.map
(svc: svc // {
depends = lib.unique (
svc.depends ++ lib.concatMap
(bundle: bundle.depends)
(containedBy services svc.name)
);
})
services
;
in
{
options.sane.users = with lib; mkOption {
type = types.attrsOf (types.submodule ({ config, ...}: let
sources = genServices (s6SvcsFromConfigServices (implicitServices // config.services));
sources = genServices (
lib.converge pushDownDependencies (
s6SvcsFromConfigServices config.services
)
);
in {
fs.".config/s6/sources".symlink.target = sources;
# N.B.: `compiled` needs to be writable (for locks -- maybe i can use symlinks to dodge this someday),