Merge pull request 'doc(inventory): document experimental settingsExtend' (#3207) from hsjobeki/clan-core:lib-cleanup into main

Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3207
This commit is contained in:
hsjobeki
2025-04-08 18:10:04 +00:00
7 changed files with 105 additions and 30 deletions

View File

@@ -13,8 +13,14 @@
# { clanCore = «derivation JSON»; clanModules = { ${name} = «derivation JSON» }; }
jsonDocs = pkgs.callPackage ./get-module-docs.nix {
inherit (self) clanModules;
clan-core = self;
inherit pkgs;
evalClanModules = self.lib.evalClan.evalClanModules;
modulesRolesOptions = self.lib.evalClan.evalClanModulesWithRoles self.clanModules;
modulesRolesOptions = self.lib.evalClan.evalClanModulesWithRoles {
allModules = self.clanModules;
inherit pkgs;
clan-core = self;
};
};
# Frontmatter for clanModules

View File

@@ -4,6 +4,8 @@
clanModules,
evalClanModules,
lib,
pkgs,
clan-core,
}:
{
# clanModules docs
@@ -11,7 +13,12 @@
name: module:
if builtins.pathExists (module + "/default.nix") then
(nixosOptionsDoc {
options = ((evalClanModules [ module ]).options).clan.${name} or { };
options =
((evalClanModules {
modules = [ module ];
inherit pkgs clan-core;
}).options
).clan.${name} or { };
warningsAreErrors = true;
}).optionsJSON
else
@@ -31,7 +38,12 @@
clanCore =
(nixosOptionsDoc {
options = ((evalClanModules [ ]).options).clan.core or { };
options =
((evalClanModules {
modules = [ ];
inherit pkgs clan-core;
}).options
).clan.core or { };
warningsAreErrors = true;
}).optionsJSON;
}

View File

@@ -280,3 +280,40 @@ Next we need to define the settings and the behavior of these distinct roles.
# ...
}
```
## Using values from a NixOS machine inside the module
!!! Example "Experimental Status"
This feature is experimental and should be used with care.
Sometimes a settings value depends on something within a machines `config`.
Since the `interface` is defined completely machine-agnostic this means values from a machine cannot be set in the traditional way.
The following example shows how to create a local instance of machine specific settings.
```nix title="someservice.nix"
{
# Maps over all instances and produces one result per instance.
perInstance = { instanceName, extendSettings, machine, roles, ... }: {
nixosModule = { config, ... }:
let
# Create new settings with
# 'ipRanges' defaulting to 'config.network.ip.range' from this machine
# This only works if there is no 'default' already.
localSettings = extendSettings {
ipRanges = lib.mkDefault config.network.ip.range;
};
in
{
# ...
};
};
}
```
!!! Danger
`localSettings` are a local attribute. Other machines cannot access it.
If calling extendSettings is done that doesn't change the original `settings` this means if a different machine tries to access i.e `roles.client.settings` it would *NOT* contain your changes.
Exposing the changed settings to other machines would come with a huge performance penalty, thats why we don't want to offer it.

View File

@@ -9,25 +9,21 @@
# 'clanLib' attribute set
# Wrapped with fix, so we can depend on other clanLib functions without passing the whole flake
lib.fix (clanLib: {
# TODO:
# SSome bad lib functions that depend on something in 'self'.
# We should reduce the dependency on 'self' aka the 'flake' object
# This makes it easier to test
# most of the time passing the whole flake is unnecessary
/**
Like callPackage, but doesn't try to automatically detect arguments
'lib' and 'clanLib' are always passed, plus the additional arguments
*/
callLib = file: args: import file ({ inherit lib clanLib; } // args);
evalClan = import ./inventory/eval-clan-modules {
inherit lib;
clan-core = self;
pkgs = nixpkgs.legacyPackages.x86_64-linux;
};
buildClanModule = clanLib.callLib ./build-clan { inherit nixpkgs nix-darwin; };
buildClan = clanLib.buildClanModule.buildClanWith { clan-core = self; };
# ------------------------------------
# Lib functions that don't depend on 'self'
# ClanLib functions
evalClan = clanLib.callLib ./inventory/eval-clan-modules { };
buildClanModule = clanLib.callLib ./build-clan { inherit nixpkgs nix-darwin; };
inventory = clanLib.callLib ./inventory { };
modules = clanLib.callLib ./inventory/frontmatter { };
# Plain imports.
values = import ./introspection { inherit lib; };
jsonschema = import ./jsonschema { inherit lib; };
select = import select/default.nix;

View File

@@ -1,10 +1,11 @@
{
clan-core,
lib,
pkgs,
clanLib,
}:
let
baseModule =
{ pkgs }:
# Module
{ config, ... }:
{
imports = (import (pkgs.path + "/nixos/modules/module-list.nix"));
@@ -20,11 +21,15 @@ let
# This function takes a list of module names and evaluates them
# [ module ] -> { config, options, ... }
evalClanModulesLegacy =
modules:
{
modules,
pkgs,
clan-core,
}:
let
evaled = lib.evalModules {
modules = [
baseModule
(baseModule { inherit pkgs; })
{
clan.core.settings.directory = clan-core;
}
@@ -56,16 +61,20 @@ let
}
*/
evalClanModulesWithRoles =
allModules:
{
allModules,
clan-core,
pkgs,
}:
let
res = builtins.mapAttrs (
moduleName: module:
let
frontmatter = clan-core.lib.modules.getFrontmatter allModules.${moduleName} moduleName;
frontmatter = clanLib.modules.getFrontmatter allModules.${moduleName} moduleName;
roles =
if builtins.elem "inventory" frontmatter.features or [ ] then
assert lib.isPath module;
clan-core.lib.modules.getRoles allModules moduleName
clanLib.modules.getRoles allModules moduleName
else
[ ];
in
@@ -75,7 +84,7 @@ let
value =
(lib.evalModules {
modules = [
baseModule
(baseModule { inherit pkgs; })
clan-core.nixosModules.clanCore
{
clan.core.settings.directory = clan-core;

View File

@@ -9,11 +9,22 @@ let
};
getModulesSchema =
modules:
lib.mapAttrs (
{
modules,
clan-core,
pkgs,
}:
lib.mapAttrs
(
_moduleName: rolesOptions:
lib.mapAttrs (_roleName: options: jsonWithoutHeader.parseOptions options { }) rolesOptions
) (clanLib.evalClan.evalClanModulesWithRoles modules);
)
(
clanLib.evalClan.evalClanModulesWithRoles {
allModules = modules;
inherit pkgs clan-core;
}
);
evalFrontmatter =
{

View File

@@ -6,7 +6,11 @@
}:
let
modulesSchema = self.lib.modules.getModulesSchema self.clanModules;
modulesSchema = self.lib.modules.getModulesSchema {
modules = self.clanModules;
inherit pkgs;
clan-core = self;
};
jsonLib = self.lib.jsonschema { inherit includeDefaults; };
includeDefaults = true;