sane.fs: dont generate systemd services for every file/dir/symlink

that's handled by systemd-tmpfiles now
This commit is contained in:
2024-09-30 10:01:49 +00:00
parent 572dd5854d
commit 49b5da6385
5 changed files with 1 additions and 156 deletions

View File

@@ -1,29 +1,10 @@
{ config, lib, pkgs, utils, sane-lib, ... }:
{ config, lib, pkgs, sane-lib, ... }:
with lib;
let
path-lib = sane-lib.path;
sane-types = sane-lib.types;
cfg = config.sane.fs;
ensure-dir = pkgs.static-nix-shell.mkBash {
pname = "ensure-dir";
srcRoot = ./.;
};
ensure-file = pkgs.static-nix-shell.mkBash {
pname = "ensure-file";
srcRoot = ./.;
};
ensure-symlink = pkgs.static-nix-shell.mkBash {
pname = "ensure-symlink";
srcRoot = ./.;
};
ensure-perms = pkgs.static-nix-shell.mkBash {
pname = "ensure-perms";
srcRoot = ./.;
};
serviceNameFor = path: "ensure-${utils.escapeSystemdPath path}";
# sane.fs."<path>" top-level options
fsEntry = types.submodule ({ name, config, ...}: let
parent = path-lib.parent name;
@@ -71,13 +52,6 @@ let
(sane-lib.filterNonNull config.symlink.acl))
];
# actually generate the item
generated.command = lib.mkMerge [
(lib.mkIf (config.dir != null) (lib.escapeShellArgs [ "${ensure-dir}/bin/ensure-dir" name ]))
(lib.mkIf (config.file != null) (lib.escapeShellArgs [ "${ensure-file}/bin/ensure-file" name config.file.copyFrom ]))
(lib.mkIf (config.symlink != null) (lib.escapeShellArgs [ "${ensure-symlink}/bin/ensure-symlink" name config.symlink.target ]))
];
# if we were asked to mount, make sure we create the dir that we mount over
dir = lib.mkIf (config.mount != null) {};
};
@@ -154,22 +128,6 @@ let
acl = mkOption {
type = sane-types.acl;
};
depends = mkOption {
type = types.listOf types.str;
description = ''
list of systemd units needed to be run before this item can be generated.
'';
default = [];
};
command = mkOption {
type = types.coercedTo (types.listOf types.str) lib.escapeShellArgs types.str;
default = "";
description = ''
command to `exec` which will generate the output.
this can be a list -- in which case it's treated as some `argv` to exec,
or a string, in which case it's passed onto the CLI unescaped.
'';
};
};
};
@@ -205,35 +163,6 @@ let
};
};
mkGeneratedConfig = path: opt: let
gen-opt = opt.generated;
wrappedCommand = [
"${ensure-perms}/bin/ensure-perms"
path
gen-opt.acl.user
gen-opt.acl.group
gen-opt.acl.mode
];
in {
systemd.services."${serviceNameFor path}" = {
description = "prepare ${path}";
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true; # makes `systemctl start ensure-blah` a noop if already completed, instead of a restart
ExecStart = (escapeShellArgs wrappedCommand) + " " + gen-opt.command;
};
after = gen-opt.depends;
requires = gen-opt.depends;
# prevent systemd making this unit implicitly dependent on sysinit.target.
# see: <https://www.freedesktop.org/software/systemd/man/systemd.special.html>
unitConfig.DefaultDependencies = "no";
# try to create all entries at boot, but don't block on them. blocking can be more targeted, by higher layers, via e.g. `RequiresMountsFor`
wantedBy = [ "default.target" ];
};
};
# given a mountEntry definition, evaluate its toplevel `config` output.
mkMountConfig = path: opt: let
fsEntry = config.fileSystems."${path}";
@@ -292,7 +221,6 @@ let
# satisfy mkTypedMerge
systemd.tmpfiles.settings."00-10-sane-fs" = {};
}]
++ [ (mkGeneratedConfig path opt) ]
++ lib.optional (opt.mount != null) (mkMountConfig path opt)
++ lib.optional (opt.dir != null) (mkDirConfig path opt)
++ lib.optional (opt.file != null) (mkFileConfig path opt)
@@ -352,7 +280,6 @@ in {
configs = lib.mapAttrsToList mkFsConfig cfg;
take = f: {
systemd.mounts = f.systemd.mounts;
systemd.services = f.systemd.services;
fileSystems = f.fileSystems;
systemd.tmpfiles.settings."00-10-sane-fs" = f.systemd.tmpfiles.settings."00-10-sane-fs";
};

View File

@@ -1,13 +0,0 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash
set -e
dirpath="$1"
if ! test -d "$dirpath"
then
# if the directory *doesn't* exist, try creating it
# if we fail to create it, ensure we raced with something else and that it's actually a directory
mkdir "$dirpath" || test -d "$dirpath"
fi

View File

@@ -1,26 +0,0 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash
set -e
cpto="$1"
cpfrom="$2"
cpOverwrite() {
# -f flag in case the destination perms were set to 000
# --no-dereference in case the destination already exists as a symlink
# however, "no-dereference" has the edge case of copying `cpfrom` to `cpto`
# when `cpto` already exists as a symlink to `cpfom`:
# "cp: <cpto> and <cpfrom> are the same file"
# use `--remove-destination` for that
cp --no-dereference -f "$cpfrom" "$cpto" \
|| cp --no-dereference --remove-destination "$cpfrom" "$cpto"
}
cpNoOverwrite() {
# --no-dereference in case the destination already exists as a symlink.
# it will still follow directory-level intermediate symlinks: just not a leaf symlink
cp --no-clobber --no-dereference "$cpfrom" "$cpto" || test -f "$cpto"
}
cpNoOverwrite

View File

@@ -1,31 +0,0 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash
set -e
fspath="$1"
acluser="$2"
aclgroup="$3"
aclmode="$4"
shift 4
# ensure any things created by the user script have the desired mode.
# chmod doesn't work on symlinks, so we *have* to use this umask approach.
decmask=$(( 0777 - "$aclmode" ))
octmask=$(printf "%o" "$decmask")
umask "$octmask"
# try to chmod/chown the result even if the user script errors
set +e
("$@")
user_status=$?
set -e
# claim ownership of the new thing (DON'T traverse symlinks)
chown --no-dereference "$acluser:$aclgroup" "$fspath"
# AS LONG AS IT'S NOT A SYMLINK, try to fix perms in case the entity existed before this script was called
if ! test -L "$fspath"
then
chmod "$aclmode" "$fspath"
fi
exit "$user_status"

View File

@@ -1,12 +0,0 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p bash
set -e
lnfrom="$1"
lnto="$2"
# ln is clever when there's something else at the place we want to create the link
# only create the link if nothing's there or what is there is another link,
# otherwise you'll get links at unexpected fs locations
! test -e "$lnfrom" || test -L "$lnfrom" && ln -sf --no-dereference "$lnto" "$lnfrom"