mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-12 04:35:41 +03:00
nixos/rust-motd: allow ordering sections by priority
Closes #234802 The problem here is that with e.g. { uptime.prefix = "Up"; banner.command = "hostname | figlet -f slant"; } `banner` still appears before `uptime` in the final motd text because Nix sorts attribute names alphabetically internally. To work around this without breaking compatibility or losing the property to override individual sections in other modules - e.g. { banner.color = mkForce "blue"; } I decided to introduce an option `priority` here, similar to the priority field for `nginx`[1] and with the same semantics (i.e. higher value means lower priority). Internally a bunch of env vars are generated, i.e. `env0` to `envN` for `N` sections with each of them containing a declaration for the TOML, i.e. `env0` contains `{ uptime.prefix = "Up"; }` and `env1` contains `{ banner.command = "hostname | figlet -f slant"; }` if `uptime.priority` is set to a value below 1000. In this order, the declarations are concatenated together by `jq(1)` which doesn't sort keys alphabetically which results in a JSON representation with `uptime` before `banner`. This is finally piped to `json2toml` which converts this into TOML for rust-motd. [1] https://nixos.org/manual/nixos/unstable/options#opt-services.nginx.virtualHosts._name_.locations._name_.priority
This commit is contained in:
parent
0a71cf07a8
commit
11376df6d4
1 changed files with 56 additions and 3 deletions
|
@ -5,6 +5,33 @@ with lib;
|
||||||
let
|
let
|
||||||
cfg = config.programs.rust-motd;
|
cfg = config.programs.rust-motd;
|
||||||
format = pkgs.formats.toml { };
|
format = pkgs.formats.toml { };
|
||||||
|
|
||||||
|
orderedSections = listToAttrs
|
||||||
|
(imap0
|
||||||
|
(i: items@{ sectionHeader, ... }: nameValuePair "env${toString i}" {
|
||||||
|
${sectionHeader} = removeAttrs items [ "priority" "sectionHeader" ];
|
||||||
|
})
|
||||||
|
(sortProperties (mapAttrsToList (k: v: v // { sectionHeader = k; }) cfg.settings)));
|
||||||
|
|
||||||
|
# Order the sections in the TOML according to the `priority` field.
|
||||||
|
# This is done by
|
||||||
|
# * creating an attribute set with keys `env0`/`env1`/.../`envN`
|
||||||
|
# where `env0` contains the first section and `envN` the last
|
||||||
|
# (in the form of `{ sectionName = { /* ... */ }}`)
|
||||||
|
# * the declarations of `env0` to `envN` in ascending order are
|
||||||
|
# concatenated with `jq`. Now we have a JSON representation of
|
||||||
|
# the config in the correct order.
|
||||||
|
# * this is piped to `json2toml` to get the correct format for rust-motd.
|
||||||
|
motdConf = pkgs.runCommand "motd.conf"
|
||||||
|
(orderedSections // {
|
||||||
|
__structuredAttrs = true;
|
||||||
|
nativeBuildInputs = [ pkgs.remarshal pkgs.jq ];
|
||||||
|
})
|
||||||
|
''
|
||||||
|
cat "$NIX_BUILD_TOP"/.attrs.json \
|
||||||
|
| jq '${concatMapStringsSep " + " (key: ''."${key}"'') (attrNames orderedSections)}' \
|
||||||
|
| json2toml /dev/stdin "$out"
|
||||||
|
'';
|
||||||
in {
|
in {
|
||||||
options.programs.rust-motd = {
|
options.programs.rust-motd = {
|
||||||
enable = mkEnableOption (lib.mdDoc "rust-motd");
|
enable = mkEnableOption (lib.mdDoc "rust-motd");
|
||||||
|
@ -28,9 +55,35 @@ in {
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
settings = mkOption {
|
settings = mkOption {
|
||||||
type = types.submodule {
|
type = types.attrsOf (types.submodule {
|
||||||
freeformType = format.type;
|
freeformType = format.type;
|
||||||
};
|
options.priority = mkOption {
|
||||||
|
type = types.int;
|
||||||
|
default = modules.defaultOrderPriority;
|
||||||
|
description = mdDoc ''
|
||||||
|
In `rust-motd`, the order of the sections in TOML correlates to the order
|
||||||
|
of the items displayed in the resulting `motd`. Attributes in Nix are
|
||||||
|
ordered alphabetically, e.g. `banner` would always be before `uptime`.
|
||||||
|
|
||||||
|
To change that, this option can be used. The lower this number is, the higher
|
||||||
|
is the priority and the more a section is at the top of the message.
|
||||||
|
|
||||||
|
For instance
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
banner.command = "hostname | figlet -f slant";
|
||||||
|
uptime = {
|
||||||
|
prefix = "Up";
|
||||||
|
priority = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
would make the `uptime` appear before the banner.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
});
|
||||||
description = mdDoc ''
|
description = mdDoc ''
|
||||||
Settings on what to generate. Please read the
|
Settings on what to generate. Please read the
|
||||||
[upstream documentation](https://github.com/rust-motd/rust-motd/blob/main/README.md#configuration)
|
[upstream documentation](https://github.com/rust-motd/rust-motd/blob/main/README.md#configuration)
|
||||||
|
@ -53,7 +106,7 @@ in {
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
serviceConfig = {
|
serviceConfig = {
|
||||||
ExecStart = "${pkgs.writeShellScript "update-motd" ''
|
ExecStart = "${pkgs.writeShellScript "update-motd" ''
|
||||||
${pkgs.rust-motd}/bin/rust-motd ${format.generate "motd.conf" cfg.settings} > motd
|
${pkgs.rust-motd}/bin/rust-motd ${motdConf} > motd
|
||||||
''}";
|
''}";
|
||||||
CapabilityBoundingSet = [ "" ];
|
CapabilityBoundingSet = [ "" ];
|
||||||
LockPersonality = true;
|
LockPersonality = true;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue