From ed240f0db1e5d4bf3fc2252c07e2c804dc0c4ac4 Mon Sep 17 00:00:00 2001 From: Kiara Grouwstra Date: Fri, 15 Aug 2025 19:37:40 +0200 Subject: [PATCH] try to modularly apply functions, hoping to fix input type checks fix types --- deployment/data-model-test.nix | 21 +++++---- deployment/data-model.nix | 82 ++++++++++++++++++++++------------ deployment/function.nix | 10 ++--- 3 files changed, 70 insertions(+), 43 deletions(-) diff --git a/deployment/data-model-test.nix b/deployment/data-model-test.nix index 24d5cd6c..97531fe8 100644 --- a/deployment/data-model-test.nix +++ b/deployment/data-model-test.nix @@ -13,7 +13,6 @@ let ./data-model.nix ]; }).config; - nixops4Deployment = inputs.nixops4.modules.nixops4Deployment.default; inherit (inputs.nixops4.lib) mkDeployment; in { @@ -134,6 +133,10 @@ in }; }; }; + deployments.example = { + environment = config.environments.single-nixos-vm; + configuration = config.example-configuration; + }; }; options = { example-configuration = mkOption { @@ -144,27 +147,27 @@ in applications.hello.enable = true; }; }; - example-deployment = mkOption { - type = types.submodule nixops4Deployment; - readOnly = true; - default = config.environments.single-nixos-vm.deployment config.example-configuration; - }; }; } ); - resources = fediversity.applications.hello.resources fediversity.example-configuration.applications.hello; + resources = fediversity.example-configuration.required-resources.hello; hello-shell = resources.resources.hello.login-shell; environment = fediversity.environments.single-nixos-vm.resources.operator-environment.login-shell; result = mkDeployment { modules = [ - (fediversity.environments.single-nixos-vm.deployment fediversity.example-configuration) + fediversity.deployments.example.deployment ]; }; in { number-of-resources = with lib; length (attrNames fediversity.resources); - inherit (fediversity) example-configuration; + # XXX: nix-unit unlike nix-build seems to hit infinite recursions on + # evaluation of package paths, so we avoid evaluating + # fediversity.example-configuration.required-resources.hello.resources.hello.login-shell.packages.hello + example-configuration = { + inherit (fediversity.example-configuration) enable applications; + }; hello-package-exists = hello-shell.packages ? hello; wheel-required = hello-shell.wheel; wheel-allowed = environment.wheel; diff --git a/deployment/data-model.nix b/deployment/data-model.nix index c3d5d53a..b3a62b32 100644 --- a/deployment/data-model.nix +++ b/deployment/data-model.nix @@ -1,6 +1,7 @@ { lib, config, + options, inputs, ... }: @@ -15,7 +16,7 @@ let functionTo ; - functionType = import ./function.nix; + functionType = import ./function.nix { inherit lib; }; application-resources = submodule { options.resources = mkOption { # TODO: maybe transpose, and group the resources by type instead @@ -101,16 +102,10 @@ in description = "Mapping of application configuration to deployment resources, a description of what an application needs to run"; type = application.config.config-mapping.function-type; }; - resources = mkOption { - description = "Compute resources required by an application"; - type = functionTo application.config.config-mapping.output-type; - readOnly = true; - default = input: (application.config.implementation input).output; - }; # TODO(@fricklerhandwerk): this needs a better name, it's just the type config-mapping = mkOption { description = "Function type for the mapping from application configuration to required resources"; - type = submodule functionType; + type = functionType; readOnly = true; default = { input-type = submodule application.config.module; @@ -146,31 +141,13 @@ in }; resource-mapping = mkOption { description = "Function type for the mapping from resources to a (NixOps4) deployment"; - type = submodule functionType; + type = functionType; readOnly = true; default = { input-type = application-resources; output-type = nixops4Deployment; }; }; - # TODO(@fricklerhandwerk): maybe this should be a separate thing such as `fediversity-setup`, - # which makes explicit which applications and environments are available. - # then the deployments can simply be the result of the function application baked into this module. - deployment = mkOption { - description = "Generate a deployment from a configuration, by applying an environment's resource policies to the applications' resource mappings"; - type = functionTo (environment.config.resource-mapping.output-type); - readOnly = true; - default = - cfg: - # TODO: check cfg.enable.true - let - required-resources = lib.mapAttrs ( - name: application-settings: config.applications.${name}.resources application-settings - ) cfg.applications; - in - (environment.config.implementation required-resources).output; - - }; }; }) ); @@ -179,7 +156,7 @@ in description = "Configuration type declaring options to be set by operators"; type = optionType; readOnly = true; - default = submodule { + default = submodule (configuration: { options = { enable = lib.mkEnableOption { description = "your Fediversity configuration"; @@ -192,8 +169,55 @@ in default = { }; } ) config.applications; + required-resources = mkOption { + description = "The deployment's required resources by application"; + type = submodule { + options = lib.mapAttrs ( + name: _application: + mkOption { + description = "Resources required for ${name}"; + type = config.applications.${name}.config-mapping.output-type; + } + ) config.applications; + }; + readOnly = true; + default = lib.mapAttrs ( + # FIXME: in nix-unit invoking the implementation somehow triggers an infinite recursion, + # tho my trace statements so far got triggered just once + name: application-settings: (config.applications.${name}.implementation application-settings).output + ) configuration.config.applications; + }; }; - }; + }); + }; + deployments = mkOption { + description = "Deployment of a configuration of applications to a run-time environment."; + type = attrsOf ( + submodule (deployment: { + options = { + configuration = mkOption { + description = "Configuration to be deployed"; + type = config.configuration; + }; + environment = mkOption { + description = "The run-time environment to deploy to"; + type = options.environments.type.nestedTypes.elemType; + }; + # TODO(@fricklerhandwerk): maybe this should be a separate thing such as `fediversity-setup`, + # which makes explicit which applications and environments are available. + # then the deployments can simply be the result of the function application baked into this module. + deployment = mkOption { + description = "Generate a deployment from a configuration, by applying an environment's resource policies to the applications' resource mappings"; + type = deployment.config.environment.resource-mapping.output-type; + readOnly = true; + # TODO: check cfg.enable.true + default = + (deployment.config.environment.implementation deployment.config.configuration.required-resources) + .output; + }; + }; + }) + ); }; }; } diff --git a/deployment/function.nix b/deployment/function.nix index f0210a34..69241925 100644 --- a/deployment/function.nix +++ b/deployment/function.nix @@ -1,7 +1,7 @@ /** Modular function type */ -{ config, lib, ... }: +{ lib, ... }: let inherit (lib) mkOption types; inherit (types) @@ -10,7 +10,7 @@ let optionType ; in -{ +submodule (function: { options = { input-type = mkOption { type = optionType; @@ -24,13 +24,13 @@ in default = functionTo (submodule { options = { input = mkOption { - type = config.input-type; + type = function.config.input-type; }; output = mkOption { - type = config.output-type; + type = function.config.output-type; }; }; }); }; }; -} +})