From fb004a4d4c69893d991e71908af0381ce46504e9 Mon Sep 17 00:00:00 2001 From: Kiara Grouwstra Date: Sun, 17 Aug 2025 17:24:43 +0200 Subject: [PATCH] combine UX with parameter type-check - DRYing TODO --- deployment/data-model-test.nix | 6 +- deployment/data-model.nix | 137 ++++++++++++++++++++++++++------- deployment/function.nix | 41 ---------- 3 files changed, 112 insertions(+), 72 deletions(-) delete mode 100644 deployment/function.nix diff --git a/deployment/data-model-test.nix b/deployment/data-model-test.nix index 7ce2fce2..5bd58b21 100644 --- a/deployment/data-model-test.nix +++ b/deployment/data-model-test.nix @@ -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 { diff --git a/deployment/data-model.nix b/deployment/data-model.nix index cefa1e4f..9620e3ea 100644 --- a/deployment/data-model.nix +++ b/deployment/data-model.nix @@ -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. diff --git a/deployment/function.nix b/deployment/function.nix deleted file mode 100644 index 48ab9abe..00000000 --- a/deployment/function.nix +++ /dev/null @@ -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; - }; - }; - }); - }; - }; -}