sane.fs: dont generate systemd services for every file/dir/symlink
that's handled by systemd-tmpfiles now
This commit is contained in:
@@ -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";
|
||||
};
|
||||
|
@@ -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
|
@@ -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
|
@@ -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"
|
@@ -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"
|
Reference in New Issue
Block a user