Custom submodules without default values #622
|
In Configure Aspects, we have an example on how to setup a custom submodule for an user aspect, but is it possible to make it work without setting any default values? For context, I have a { ... }:
{
den.aspects.fonts =
{ config, lib, ... }:
{
imports = [
{
options = with lib.types; {
sansSerif = lib.mkOption { type = str; };
};
}
];
nixos =
{ pkgs, ... }:
{
fonts.fontconfig.defaultFonts = {
sansSerif = [ config.sansSerif ];
};
};
};
}Notice the lack of default values. My goal is to force hosts/users to set these values, but I also want to reference the values in other submodules, such as So, in the host file: den.aspects.myHost = {
includes = [
den.aspects.fonts
den.aspects.gnome
];
# Set default fonts here.
fonts.sansSerif = "Ubuntu";
# Or maybe we need the whole namespace?
den.aspects.fonts.sansSerif = "Ubuntu";
# Host config
nixos = { pkgs, ... }: {};
};Then, inside my { den, ... }:
{
# Simplified for the example.
den.aspects.gnome.homeManager.dconf = {
enable = true;
settings = {
"org/gnome/desktop/interface" = {
font-name = "${den.aspects.fonts.sans} 11";
# Or using `config.den.aspects.fonts.sans`.
};
};
};
}I've tried everything, but I could only make it work by setting a default value in the option. Without the default value, it says the option was accessed but has no value defined, even with me configuring the option in the host. It could be some kind of evaluation problem, where So, I'm either doing something wrong, forgetting about something important, or Den simply doesn't support this in the way that I'm approaching it. I know an alternative would be to set these options via Any tips? |
Replies: 4 comments 12 replies
|
If it's something you want set per-user, you might be better served by creating a new option on the user schema. |
|
I'll put together a gist of how I do aspect settings in my config tomorrow. What you're describing is either our quirks system, or my custom settings extension. Aspects provide behavior; they aren't data. Users/hosts provide data/context -- so in my configuration I define options on aspects, and assign values to context (generally the host). |
|
Just wanted to mention that I got this working nicely. The gist was very helpful, thanks again @sini. I implemented Option 1 as shown, but then created a policy to automatically inject # den/policies/settings-injection.nix
{ den, ... }:
{
den.policies.settings-injection =
{
host ? null,
home ? null,
...
}:
[
(den.lib.policy.resolve {
settings =
if host ? settings then
host.settings
else if home ? settings then
home.settings
else
throw "No settings found on host or home";
})
];
}# den/default.nix
{ den, ... }:
{
den.default.includes = [
den.policies.settings-injection
];
# Other settings..
}Also, an important change from the gist is that I went from # den/settings.nix
{ den, lib, ... }:
let
inherit (lib) mkOption types;
# Dynamic settings type. Read the gist for details.
settingsType = ...
in
{
den.reservedKeys = [ "settings" ];
# Applies to hosts, homes, and users, but I tend to configure everything in the host/home side.
den.schema.conf = {
imports = [
{
options.settings =
mkOption {
type = settingsType;
default = { };
description = "Per-aspect typed settings";
}
# Exclude settings from entity identity hashing
// {
identity = false;
};
}
];
};
}Now, the only thing "missing" would be the ability to reference values from inside the settings block somehow, like so: den.hosts.x86_64-linux."${host}" = {
users.lucas = { };
settings = rec {
fonts = {
sans = "Adwaita Sans";
};
gnome = {
interface-font = fonts.sans; # Defined above, `rec` lets us use this.
document-font = ???; # Use the default from `den.aspects.fonts.settings.serif`.
};
};
};But the above seems to be an unusual pattern in NixOS (even though it's common in enterprise development), so that's not really an issue for me. Besides that, I might run into issues if I ever need something more than what NixOS options pattern provides, but for now this is working nicely as a way for aspects to expose configurable options that can be defined in a per-host (or home) basis. EDIT: I think we're also missing the ability to set values inside another aspect, like the |
|
Old thread, but I would just like to add that making aspect-level custom options work would still be my ideal, one-size-fits-all way to pass data to reusable aspects, in a similar spirit to @lucasshiva's comments above. Each of quirks/class module custom options/settings has some friction with my current config:
(Of course, I could also just use different ones of the three approaches above depending on the use case, but I feel like it gets kinda messy having so many different ways to pass data to aspects.) Aspect-level custom options would solve all three: they can have hierarchical names, they aren't limited to one class, and they can be defined on the user aspect which is host-agnostic instead of the user entities. They fill the gap of "module options, but for aspects" that I feel like is needed given that den seems to essentially replace regular nix modules with aspects. I'm currently also trying to see if I can get something like an |
Just wanted to mention that I got this working nicely. The gist was very helpful, thanks again @sini. I implemented Option 1 as shown, but then created a policy to automatically inject
settingsfrom eitherhost.settingson NixOS orhome.settingson standalonehome-manager:# …