Files
clan-core/lib/distributed-service/tests/default.nix
2025-03-29 15:40:31 +01:00

328 lines
8.7 KiB
Nix

{
lib,
...
}:
let
inherit (lib)
evalModules
;
evalInventory =
m:
(evalModules {
# Static modules
modules = [
../../inventory/build-inventory/interface.nix
{
modules.test = { };
}
m
];
}).config;
flakeFixture = {
inputs = { };
};
callInventoryAdapter =
inventoryModule:
import ../inventory-adapter.nix {
inherit lib;
flake = flakeFixture;
inventory = evalInventory inventoryModule;
};
in
{
test_simple =
let
res = callInventoryAdapter {
# Authored module
# A minimal module looks like this
# It isn't exactly doing anything but it's a valid module that produces an output
modules."simple-module" = {
_class = "clan.service";
manifest = {
name = "netwitness";
};
};
# User config
instances."instance_foo" = {
module = {
name = "simple-module";
};
};
};
in
{
# Test that the module is mapped into the output
# We might change the attribute name in the future
expr = res.evals ? "self-simple-module";
expected = true;
};
# A module can be imported multiple times
# A module can also have multiple instances within the same module
# This mean modules must be grouped together, imported once
# All instances should be included within one evaluation to make all of them available
test_module_grouping =
let
res = callInventoryAdapter {
# Authored module
# A minimal module looks like this
# It isn't exactly doing anything but it's a valid module that produces an output
modules."A" = {
_class = "clan.service";
manifest = {
name = "A-name";
};
perMachine = { }: { };
};
modules."B" = {
_class = "clan.service";
manifest = {
name = "B-name";
};
perMachine = { }: { };
};
# User config
instances."instance_foo" = {
module = {
name = "A";
};
};
instances."instance_bar" = {
module = {
name = "B";
};
};
instances."instance_baz" = {
module = {
name = "A";
};
};
};
in
{
# Test that the module is mapped into the output
# We might change the attribute name in the future
expr = lib.mapAttrs (_n: v: builtins.length v) res.grouped;
expected = {
self-A = 2;
self-B = 1;
};
};
test_creates_all_instances =
let
res = callInventoryAdapter {
# Authored module
# A minimal module looks like this
# It isn't exactly doing anything but it's a valid module that produces an output
modules."A" = {
_class = "clan.service";
manifest = {
name = "network";
};
perMachine = { }: { };
};
instances."instance_foo" = {
module = {
name = "A";
};
};
instances."instance_bar" = {
module = {
name = "A";
};
};
instances."instance_zaza" = {
module = {
name = "B";
};
};
};
in
{
# Test that the module is mapped into the output
# We might change the attribute name in the future
expr = lib.attrNames res.evals.self-A.config.instances;
expected = [
"instance_bar"
"instance_foo"
];
};
# Membership via roles
test_add_machines_directly =
let
res = callInventoryAdapter {
# Authored module
# A minimal module looks like this
# It isn't exactly doing anything but it's a valid module that produces an output
modules."A" = {
_class = "clan.service";
manifest = {
name = "network";
};
# Define a role without special behavior
roles.peer = { };
# perMachine = {}: {};
};
machines = {
jon = { };
sara = { };
hxi = { };
};
instances."instance_foo" = {
module = {
name = "A";
};
roles.peer.machines.jon = { };
};
instances."instance_bar" = {
module = {
name = "A";
};
roles.peer.machines.sara = { };
};
instances."instance_zaza" = {
module = {
name = "B";
};
roles.peer.tags.all = { };
};
};
in
{
# Test that the module is mapped into the output
# We might change the attribute name in the future
expr = lib.attrNames res.evals.self-A.config.result.allMachines;
expected = [
"jon"
"sara"
];
};
# Membership via tags
test_add_machines_via_tags =
let
res = callInventoryAdapter {
# Authored module
# A minimal module looks like this
# It isn't exactly doing anything but it's a valid module that produces an output
modules."A" = {
_class = "clan.service";
manifest = {
name = "network";
};
# Define a role without special behavior
roles.peer = { };
# perMachine = {}: {};
};
machines = {
jon = {
tags = [ "foo" ];
};
sara = {
tags = [ "foo" ];
};
hxi = { };
};
instances."instance_foo" = {
module = {
name = "A";
};
roles.peer.tags.foo = { };
};
instances."instance_zaza" = {
module = {
name = "B";
};
roles.peer.tags.all = { };
};
};
in
{
# Test that the module is mapped into the output
# We might change the attribute name in the future
expr = lib.attrNames res.evals.self-A.config.result.allMachines;
expected = [
"jon"
"sara"
];
};
per_machine_args = import ./per_machine_args.nix { inherit lib callInventoryAdapter; };
# test_per_machine_receives_instances =
# let
# res = callInventoryAdapter {
# # Authored module
# # A minimal module looks like this
# # It isn't exactly doing anything but it's a valid module that produces an output
# modules."A" = {
# _class = "clan.service";
# manifest = {
# name = "network";
# };
# # Define a role without special behavior
# roles.peer = { };
# perMachine =
# { instances, ... }:
# {
# nixosModule = instances;
# };
# };
# machines = {
# jon = { };
# sara = { };
# };
# instances."instance_foo" = {
# module = {
# name = "A";
# };
# roles.peer.machines.jon = { };
# };
# instances."instance_bar" = {
# module = {
# name = "A";
# };
# roles.peer.machines.sara = { };
# };
# instances."instance_zaza" = {
# module = {
# name = "B";
# };
# roles.peer.tags.all = { };
# };
# };
# in
# {
# expr = {
# hasMachineSettings =
# res.evals.self-A.config.result.allMachines.jon.nixosModule. # { {instanceName} :: { roles :: { {roleName} :: { machines :: { {machineName} :: { settings :: {} } } } } } }
# instance_foo.roles.peer.machines.jon ? settings;
# machineSettingsEmpty =
# lib.filterAttrs (n: _v: n != "__functor" ) res.evals.self-A.config.result.allMachines.jon.nixosModule. # { {instanceName} :: { roles :: { {roleName} :: { machines :: { {machineName} :: { settings :: {} } } } } } }
# instance_foo.roles.peer.machines.jon.settings;
# hasRoleSettings =
# res.evals.self-A.config.result.allMachines.jon.nixosModule. # { {instanceName} :: { roles :: { {roleName} :: { machines :: { {machineName} :: { settings :: {} } } } } } }
# instance_foo.roles.peer ? settings;
# roleSettingsEmpty =
# lib.filterAttrs (n: _v: n != "__functor" ) res.evals.self-A.config.result.allMachines.jon.nixosModule. # { {instanceName} :: { roles :: { {roleName} :: { machines :: { {machineName} :: { settings :: {} } } } } } }
# instance_foo.roles.peer.settings;
# };
# expected = {
# hasMachineSettings = true;
# machineSettingsEmpty = {};
# hasRoleSettings = true;
# roleSettingsEmpty = {};
# };
# };
}