refactor: modules/users/s6-rc.nix
This commit is contained in:
parent
d4f217a4f5
commit
218072b2fe
|
@ -1,73 +1,85 @@
|
|||
{ lib, pkgs, ... }:
|
||||
let
|
||||
logBase = "$HOME/.local/state/s6/logs";
|
||||
maybe = cond: value: if cond then value else null;
|
||||
normalizeName = name: lib.removeSuffix ".service" (lib.removeSuffix ".target" name);
|
||||
|
||||
# infers the service type from the arguments and dispatches appropriately
|
||||
genService = { name, run, finish, depends }: let
|
||||
# create a derivation whose output is the on-disk representation of some attrset.
|
||||
# @path: /foo/bar/...
|
||||
# @obj: one of:
|
||||
# - { file = { text = "foo bar"; executable = true|false; } }
|
||||
# - { dir = <obj>; }
|
||||
fsItemToDerivation = path: obj: if obj ? dir then
|
||||
pkgs.symlinkJoin {
|
||||
name = "s6-${path}";
|
||||
paths = lib.mapAttrsToList
|
||||
(n: v: fsItemToDerivation "${path}/${n}" v)
|
||||
obj.dir
|
||||
;
|
||||
}
|
||||
else if obj ? text then
|
||||
if obj.text != null then
|
||||
pkgs.writeTextFile {
|
||||
name = "s6-${path}";
|
||||
destination = path;
|
||||
text = obj.text;
|
||||
}
|
||||
else
|
||||
pkgs.emptyDirectory
|
||||
else if obj ? executable then
|
||||
if obj.executable != null then
|
||||
pkgs.writeTextFile {
|
||||
name = "s6-${path}";
|
||||
destination = path;
|
||||
executable = true;
|
||||
text = obj.executable;
|
||||
}
|
||||
else
|
||||
pkgs.emptyDirectory
|
||||
else throw "don't know how to convert fs item at path ${path} to derivation: ${obj}";
|
||||
|
||||
# call with an AttrSet of fs items:
|
||||
# example:
|
||||
# ```
|
||||
# fsToDerivation {
|
||||
# usr.dir = {
|
||||
# normal.text = "i'm /usr/normal";
|
||||
# exec.executable = ''
|
||||
# #!/bin/sh
|
||||
# echo "i'm executable"
|
||||
# '';
|
||||
# lib.dir = { ... };
|
||||
# };
|
||||
# bin.dir = { ... };
|
||||
# }
|
||||
fsToDerivation = fs: fsItemToDerivation "/" { dir = fs; };
|
||||
|
||||
# infers the service type from the arguments and creates an attrset usable by `fsToDerivation`.
|
||||
serviceToFs = { name, run, finish, depends }: let
|
||||
name' = normalizeName name;
|
||||
type = if run != null then "longrun" else "bundle";
|
||||
in genService' {
|
||||
name = name';
|
||||
inherit type;
|
||||
# TODO: a bundle can totally have dependencies. i can't just map them *all* to contents.
|
||||
depends = lib.optionals (type == "longrun") depends;
|
||||
finish = finish;
|
||||
longrun-run = run;
|
||||
bundle-contents = lib.optionals (type == "bundle") depends;
|
||||
};
|
||||
|
||||
genService' = {
|
||||
name,
|
||||
type,
|
||||
depends,
|
||||
finish,
|
||||
longrun-run,
|
||||
bundle-contents,
|
||||
}: pkgs.symlinkJoin {
|
||||
name = "s6-${name}";
|
||||
paths = [
|
||||
(pkgs.writeTextFile {
|
||||
name = "s6-${name}-type";
|
||||
destination = "/${name}/type";
|
||||
text = type;
|
||||
})
|
||||
] ++ lib.optionals (finish != null) [
|
||||
(pkgs.writeTextFile {
|
||||
# TODO: use 'writeShellScript'?
|
||||
name = "s6-${name}-finish";
|
||||
destination = "/${name}/finish";
|
||||
executable = true;
|
||||
text = ''
|
||||
#!/bin/sh
|
||||
${finish}
|
||||
'';
|
||||
})
|
||||
] ++ lib.optionals (longrun-run != null) [
|
||||
(pkgs.writeTextFile {
|
||||
name = "s6-${name}-run";
|
||||
destination = "/${name}/run";
|
||||
executable = true;
|
||||
# TODO: consider using `makeWrapper`/`makeBinaryWrapper`?
|
||||
text = ''
|
||||
#!/bin/sh
|
||||
echo "starting: s6-${name}"
|
||||
${longrun-run} 2>&1
|
||||
'';
|
||||
})
|
||||
] ++ lib.optionals (bundle-contents != null) [
|
||||
(pkgs.writeTextFile {
|
||||
name = "s6-${name}-contents";
|
||||
destination = "/${name}/contents";
|
||||
text = lib.concatStringsSep "\n" (builtins.map normalizeName bundle-contents);
|
||||
})
|
||||
] ++ builtins.map
|
||||
(d: pkgs.writeTextFile {
|
||||
name = "s6-${name}-depends-${d}";
|
||||
destination = "/${name}/dependencies.d/${normalizeName d}";
|
||||
text = "";
|
||||
})
|
||||
depends;
|
||||
in {
|
||||
"${name}".dir = {
|
||||
"type".text = type;
|
||||
"finish".executable = maybe (finish != null) ''
|
||||
#!/bin/sh
|
||||
${finish}
|
||||
'';
|
||||
"run".executable = maybe (run != null) ''
|
||||
#!/bin/sh
|
||||
echo "starting: s6-${name}"
|
||||
${run} 2>&1
|
||||
'';
|
||||
"contents".text = maybe (type == "bundle") (
|
||||
lib.concatStringsSep "\n" (builtins.map normalizeName depends)
|
||||
);
|
||||
# TODO: a bundle can also have dependencies
|
||||
"dependencies.d".dir = lib.optionalAttrs (type == "longrun") (
|
||||
lib.genAttrs
|
||||
(builtins.map normalizeName depends)
|
||||
(dep: { text = ""; })
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
# create a directory, containing N subdirectories:
|
||||
|
@ -78,10 +90,11 @@ let
|
|||
# - type
|
||||
# - run
|
||||
# - ...
|
||||
genServices = svcs: pkgs.symlinkJoin {
|
||||
name = "s6-user-services";
|
||||
paths = builtins.map genService svcs;
|
||||
};
|
||||
genServices = svcs: fsToDerivation (lib.foldl'
|
||||
(acc: srv: acc // (serviceToFs srv))
|
||||
{}
|
||||
svcs
|
||||
);
|
||||
|
||||
# output is a directory containing:
|
||||
# - db
|
||||
|
|
Loading…
Reference in New Issue
Block a user