diff options
author | Maximilian Bosch <maximilian@mbosch.me> | 2023-09-21 00:05:35 +0200 |
---|---|---|
committer | Maximilian Bosch <maximilian@mbosch.me> | 2023-09-21 13:17:13 +0200 |
commit | 11376df6d40c8fdbbd3c9a048b742dc032a88d15 (patch) | |
tree | 721577cc368dc8fc2f80910f7d0556ff4c11315c /nixos/modules/programs | |
parent | 0a71cf07a82eacd0a618fe7ba7016f7de5f5c2f5 (diff) |
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
Diffstat (limited to 'nixos/modules/programs')
-rw-r--r-- | nixos/modules/programs/rust-motd.nix | 59 |
1 files changed, 56 insertions, 3 deletions
diff --git a/nixos/modules/programs/rust-motd.nix b/nixos/modules/programs/rust-motd.nix index 7fd89e1658efc..3e3ce63ab212c 100644 --- a/nixos/modules/programs/rust-motd.nix +++ b/nixos/modules/programs/rust-motd.nix @@ -5,6 +5,33 @@ with lib; let cfg = config.programs.rust-motd; 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 { options.programs.rust-motd = { enable = mkEnableOption (lib.mdDoc "rust-motd"); @@ -28,9 +55,35 @@ in { ''; }; settings = mkOption { - type = types.submodule { + type = types.attrsOf (types.submodule { 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 '' Settings on what to generate. Please read the [upstream documentation](https://github.com/rust-motd/rust-motd/blob/main/README.md#configuration) @@ -53,7 +106,7 @@ in { wantedBy = [ "multi-user.target" ]; serviceConfig = { 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 = [ "" ]; LockPersonality = true; |