Fediversity/deployment/data-model-test.nix

183 lines
6.6 KiB
Nix

let
inherit (import ../default.nix { }) pkgs inputs;
inherit (pkgs) lib;
inherit (lib) mkOption types;
eval =
module:
(lib.evalModules {
specialArgs = {
inherit inputs;
};
modules = [
module
./data-model.nix
];
}).config;
in
{
_class = "nix-unit";
test-eval = {
expr =
let
fediversity = eval (
{ config, ... }:
{
_class = "fediversity-settings";
config = {
resources.nixos-configuration = {
description = "An entire NixOS configuration";
request =
{ ... }:
{
_class = "fediversity-resource-request";
options.config = mkOption {
description = "Any options from NixOS";
};
};
policy =
{ ... }:
{
_class = "fediversity-resource-policy";
options = {
extra-config = mkOption {
description = "Any options from NixOS";
};
apply = mkOption {
type = with types; functionTo raw;
default = policy: requests: lib.mkMerge (requests ++ [ policy.extra-config ]);
};
};
};
};
resources.login-shell = {
_class = "fediversity-resource";
description = "The operator needs to be able to log into the shell";
request =
{ ... }:
{
_class = "fediversity-resource-request";
options = {
wheel = mkOption {
description = "Whether the login user needs root permissions";
type = types.bool;
default = false;
};
packages = mkOption {
description = "Packages that need to be available in the user environment";
type = with types; attrsOf package;
};
};
};
policy =
{ ... }:
{
_class = "fediversity-resource-policy";
options = {
username = mkOption {
description = "Username for the operator";
type = types.str; # TODO: use the proper constraints from NixOS
};
wheel = mkOption {
description = "Whether to allow login with root permissions";
type = types.bool;
default = false;
};
apply = mkOption {
type = with types; functionTo raw; # TODO: splice out the user type from NixOS
default =
policy: requests:
let
# Filter out requests that need wheel if policy doesn't allow it
validRequests = lib.filterAttrs (_name: req: !req.wheel || policy.wheel) requests;
in
lib.optionalAttrs (validRequests != { }) {
${policy.username} = {
isNormalUser = true;
packages = with lib; concatMap (request: attrValues request.packages) (attrValues validRequests);
extraGroups = lib.optional policy.wheel "wheel";
};
};
};
};
};
};
applications.hello =
{ ... }:
{
_class = "fediversity-application";
description = ''Command-line tool that will print "Hello, world!" on the terminal'';
module =
{ ... }:
{
_class = "fediversity-application-config";
options = {
enable = lib.mkEnableOption "Hello in the shell";
};
};
resources =
cfg:
lib.optionalAttrs cfg.enable {
dummy.login-shell.packages = {
# hello = pkgs.hello;
};
};
};
environments.single-nixos-vm = environment: {
_class = "fediversity-environment";
resources.shell.login-shell = {
username = "operator";
# wheel = false; # FIXME: why do i need to make this explicit, if a default was supposed to be set?
};
implementation = requests: {
_class = "nixos";
users.users = (
config.resources.login-shell.policy.apply environment.config.resources.shell.login-shell (
lib.concatMapAttrs (
_application: resources:
lib.mapAttrs (_k: lib.getAttr "login-shell") (
lib.filterAttrs (_name: value: value ? login-shell) resources
)
) requests
)
);
};
};
};
options = {
example-configuration = mkOption {
type = config.configuration;
readOnly = true;
default = {
_class = "fediversity-configuration";
enable = true;
applications.hello.enable = true;
};
};
example-deployment = mkOption {
type = types.raw;
readOnly = true;
default = config.environments.single-nixos-vm.deployment config.example-configuration;
};
};
}
);
in
{
inherit (fediversity)
example-configuration
example-deployment
;
num-packages = lib.lists.length fediversity.example-deployment.users.users.operator.packages;
};
expected = {
example-configuration = {
enable = true;
applications.hello.enable = true;
};
num-packages = 1;
};
};
}