combine UX with parameter type-check - DRYing TODO

This commit is contained in:
Kiara Grouwstra 2025-08-17 17:24:43 +02:00
parent 6fa9c40662
commit fb004a4d4c
Signed by: kiara
SSH key fingerprint: SHA256:COspvLoLJ5WC5rFb9ZDe5urVCkK4LJZOsjfF4duRJFU
3 changed files with 112 additions and 72 deletions

View file

@ -99,7 +99,7 @@ in
{
options.enable = lib.mkEnableOption "Hello in the shell";
};
implementation =
config-mapping.implementation =
cfg:
lib.optionalAttrs cfg.enable {
resources.hello.login-shell.packages.hello = pkgs.hello;
@ -109,7 +109,7 @@ in
{ config, ... }:
{
resources.operator-environment.login-shell.username = "operator";
implementation =
resource-mapping.implementation =
requests:
{ providers, ... }:
{
@ -149,7 +149,7 @@ in
};
}
);
resources = fediversity.applications.hello.resources fediversity.example-configuration.applications.hello;
resources = fediversity.applications.hello.config-mapping.apply fediversity.example-configuration.applications.hello;
hello-shell = resources.resources.hello.login-shell;
environment = fediversity.environments.single-nixos-vm.resources.operator-environment.login-shell;
result = mkDeployment {

View file

@ -15,7 +15,6 @@ let
functionTo
;
functionType = import ./function.nix;
application-resources = submodule {
options.resources = mkOption {
# TODO: maybe transpose, and group the resources by type instead
@ -97,25 +96,63 @@ in
description = "Operator-facing configuration options for the application";
type = deferredModuleWith { staticModules = [ { _class = "fediversity-application-config"; } ]; };
};
implementation = mkOption {
description = "Mapping of application configuration to deployment resources, a description of what an application needs to run";
type = application.config.config-mapping.implementation-type;
};
resources = mkOption {
description = "Compute resources required by an application";
type = functionTo application.config.config-mapping.output-type;
readOnly = true;
default = application.config.implementation;
};
# TODO(@fricklerhandwerk): this needs a better name, it's just the type
# TODO(@fricklerhandwerk): this needs a better name
config-mapping = mkOption {
description = "Function type for the mapping from application configuration to required resources";
type = submodule functionType;
readOnly = true;
default = {
input-type = submodule application.config.module;
output-type = application-resources;
};
type = submodule (
{ config, ... }:
{
options = {
input-type = mkOption {
type = optionType;
default = submodule application.config.module;
# default = types.int;
};
output-type = mkOption {
type = optionType;
default = application-resources;
};
function-type = mkOption {
type = optionType;
readOnly = true;
default = functionTo config.output-type;
};
wrapper-type = mkOption {
type = optionType;
readOnly = true;
default = functionTo (submodule {
options = {
input = mkOption {
type = config.input-type;
};
output = mkOption {
type = config.output-type;
};
};
});
};
implementation = mkOption {
type = config.function-type;
description = "Mapping of application configuration to deployment resources, a description of what an application needs to run";
default = _: { };
};
wrapper = mkOption {
type = config.wrapper-type;
readOnly = true;
default = input: fn: {
inherit input;
output = config.implementation fn.config.input;
};
};
apply = mkOption {
type = config.function-type;
readOnly = true;
default = input: (config.wrapper input).output;
};
};
}
);
default = { };
};
};
})
@ -140,18 +177,62 @@ in
)
);
};
implementation = mkOption {
description = "Mapping of resources required by applications to available resources; the result can be deployed";
type = environment.config.resource-mapping.implementation-type;
};
resource-mapping = mkOption {
description = "Function type for the mapping from resources to a (NixOps4) deployment";
type = submodule functionType;
readOnly = true;
default = {
input-type = application-resources;
output-type = nixops4Deployment;
};
type = submodule (
{ config, ... }:
{
options = {
input-type = mkOption {
type = optionType;
default = submodule application-resources;
# default = types.int;
};
output-type = mkOption {
type = optionType;
default = nixops4Deployment;
};
function-type = mkOption {
type = optionType;
readOnly = true;
default = functionTo config.output-type;
};
wrapper-type = mkOption {
type = optionType;
readOnly = true;
default = functionTo (submodule {
options = {
input = mkOption {
type = config.input-type;
};
output = mkOption {
type = config.output-type;
};
};
});
};
implementation = mkOption {
type = config.function-type;
description = "Mapping of resources required by applications to available resources; the result can be deployed";
default = _: { };
};
wrapper = mkOption {
type = config.wrapper-type;
readOnly = true;
default = input: fn: {
inherit input;
output = config.implementation fn.config.input;
};
};
apply = mkOption {
type = config.function-type;
readOnly = true;
default = input: (config.wrapper input).output;
};
};
}
);
default = { };
};
# TODO(@fricklerhandwerk): maybe this should be a separate thing such as `fediversity-setup`,
# which makes explicit which applications and environments are available.

View file

@ -1,41 +0,0 @@
/**
Modular function type
*/
{ config, lib, ... }:
let
inherit (lib) mkOption types;
inherit (types)
submodule
functionTo
optionType
;
in
{
options = {
input-type = mkOption {
type = optionType;
};
output-type = mkOption {
type = optionType;
};
implementation-type = mkOption {
type = optionType;
readOnly = true;
default = functionTo config.output-type;
};
function-type = mkOption {
type = optionType;
readOnly = true;
default = functionTo (submodule {
options = {
input = mkOption {
type = config.input-type;
};
output = mkOption {
type = config.output-type;
};
};
});
};
};
}