Merge pull request 'clanServices: add flake level exports' (#4172) from flake-exports into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4172
This commit is contained in:
@@ -185,7 +185,6 @@ in
|
|||||||
];
|
];
|
||||||
|
|
||||||
clan.core.vars.generators.borgbackup = {
|
clan.core.vars.generators.borgbackup = {
|
||||||
|
|
||||||
files."borgbackup.ssh.pub".secret = false;
|
files."borgbackup.ssh.pub".secret = false;
|
||||||
files."borgbackup.ssh" = { };
|
files."borgbackup.ssh" = { };
|
||||||
files."borgbackup.repokey" = { };
|
files."borgbackup.repokey" = { };
|
||||||
|
|||||||
@@ -67,6 +67,44 @@ in
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# TODO: make this writable by moving the options from inventoryClass into clan.
|
||||||
|
exports = lib.mkOption {
|
||||||
|
readOnly = true;
|
||||||
|
visible = false;
|
||||||
|
internal = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
exportsModule = lib.mkOption {
|
||||||
|
internal = true;
|
||||||
|
visible = false;
|
||||||
|
type = types.deferredModule;
|
||||||
|
default = { };
|
||||||
|
description = ''
|
||||||
|
A module that is used to define the module of flake level exports -
|
||||||
|
|
||||||
|
such as 'exports.machines.<name>' and 'exports.instances.<name>'
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{
|
||||||
|
options.vars.generators = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf (
|
||||||
|
lib.types.submoduleWith {
|
||||||
|
modules = [
|
||||||
|
{
|
||||||
|
options.script = lib.mkOption { type = lib.types.str; };
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
);
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
specialArgs = lib.mkOption {
|
specialArgs = lib.mkOption {
|
||||||
type = types.attrsOf types.raw;
|
type = types.attrsOf types.raw;
|
||||||
default = { };
|
default = { };
|
||||||
|
|||||||
@@ -224,6 +224,8 @@ in
|
|||||||
inherit nixosConfigurations;
|
inherit nixosConfigurations;
|
||||||
inherit darwinConfigurations;
|
inherit darwinConfigurations;
|
||||||
|
|
||||||
|
exports = config.clanInternals.inventoryClass.distributedServices.servicesEval.config.exports;
|
||||||
|
|
||||||
clanInternals = {
|
clanInternals = {
|
||||||
inventoryClass =
|
inventoryClass =
|
||||||
let
|
let
|
||||||
@@ -244,10 +246,13 @@ in
|
|||||||
inherit inventory directory;
|
inherit inventory directory;
|
||||||
}
|
}
|
||||||
(
|
(
|
||||||
|
let
|
||||||
|
clanConfig = config;
|
||||||
|
in
|
||||||
{ config, ... }:
|
{ config, ... }:
|
||||||
{
|
{
|
||||||
distributedServices = clanLib.inventory.mapInstances {
|
distributedServices = clanLib.inventory.mapInstances {
|
||||||
inherit (config) inventory;
|
inherit (clanConfig) inventory exportsModule;
|
||||||
inherit flakeInputs;
|
inherit flakeInputs;
|
||||||
clanCoreModules = clan-core.clan.modules;
|
clanCoreModules = clan-core.clan.modules;
|
||||||
prefix = [ "distributedServices" ];
|
prefix = [ "distributedServices" ];
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
# Wraps all services in one fixed point module
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
specialArgs,
|
||||||
|
_ctx,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
let
|
||||||
|
inherit (lib) mkOption types;
|
||||||
|
inherit (types) attrsWith submoduleWith;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
# TODO: merge these options into clan options
|
||||||
|
options = {
|
||||||
|
exportsModule = mkOption {
|
||||||
|
type = types.deferredModule;
|
||||||
|
readOnly = true;
|
||||||
|
};
|
||||||
|
mappedServices = mkOption {
|
||||||
|
visible = false;
|
||||||
|
type = attrsWith {
|
||||||
|
placeholder = "mappedServiceName";
|
||||||
|
elemType = submoduleWith {
|
||||||
|
modules = [
|
||||||
|
(
|
||||||
|
{ name, ... }:
|
||||||
|
{
|
||||||
|
_module.args._ctx = [ name ];
|
||||||
|
_module.args.exports' = config.exports;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
./service-module.nix
|
||||||
|
# feature modules
|
||||||
|
(lib.modules.importApply ./api-feature.nix {
|
||||||
|
inherit (specialArgs) clanLib;
|
||||||
|
prefix = _ctx;
|
||||||
|
})
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
exports = mkOption {
|
||||||
|
type = submoduleWith {
|
||||||
|
modules = [
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
instances = lib.mkOption {
|
||||||
|
# instances.<instanceName>...
|
||||||
|
type = types.attrsOf (submoduleWith {
|
||||||
|
modules = [
|
||||||
|
config.exportsModule
|
||||||
|
];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
# instances.<machineName>...
|
||||||
|
machines = lib.mkOption {
|
||||||
|
type = types.attrsOf (submoduleWith {
|
||||||
|
modules = [
|
||||||
|
config.exportsModule
|
||||||
|
];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
] ++ lib.mapAttrsToList (_: service: service.exports) config.mappedServices;
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
debug = mkOption {
|
||||||
|
default = lib.mapAttrsToList (_: service: service.exports) config.mappedServices;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -26,6 +26,7 @@ in
|
|||||||
inventory,
|
inventory,
|
||||||
clanCoreModules,
|
clanCoreModules,
|
||||||
prefix ? [ ],
|
prefix ? [ ],
|
||||||
|
exportsModule,
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
# machineHasTag = machineName: tagName: lib.elem tagName inventory.machines.${machineName}.tags;
|
# machineHasTag = machineName: tagName: lib.elem tagName inventory.machines.${machineName}.tags;
|
||||||
@@ -89,23 +90,6 @@ in
|
|||||||
}
|
}
|
||||||
) inventory.instances or { };
|
) inventory.instances or { };
|
||||||
|
|
||||||
# TODO: Eagerly check the _class of the resolved module
|
|
||||||
importedModulesEvaluated = lib.mapAttrs (
|
|
||||||
module_ident: instances:
|
|
||||||
clanLib.evalService {
|
|
||||||
prefix = prefix ++ [ module_ident ];
|
|
||||||
modules =
|
|
||||||
[
|
|
||||||
# Import the resolved module.
|
|
||||||
# i.e. clan.modules.admin
|
|
||||||
(builtins.head instances).instance.resolvedModule
|
|
||||||
] # Include all the instances that correlate to the resolved module
|
|
||||||
++ (builtins.map (v: {
|
|
||||||
instances.${v.instanceName}.roles = v.instance.instanceRoles;
|
|
||||||
}) instances);
|
|
||||||
}
|
|
||||||
) grouped;
|
|
||||||
|
|
||||||
# Group the instances by the module they resolve to
|
# Group the instances by the module they resolve to
|
||||||
# This is necessary to evaluate the module in a single pass
|
# This is necessary to evaluate the module in a single pass
|
||||||
# :: { <module.input>_<module.name> :: [ { name, value } ] }
|
# :: { <module.input>_<module.name> :: [ { name, value } ] }
|
||||||
@@ -126,16 +110,52 @@ in
|
|||||||
}
|
}
|
||||||
) { } importedModuleWithInstances;
|
) { } importedModuleWithInstances;
|
||||||
|
|
||||||
|
# servicesEval.config.mappedServices.self-A.result.final.jon.nixosModule
|
||||||
allMachines = lib.mapAttrs (machineName: _: {
|
allMachines = lib.mapAttrs (machineName: _: {
|
||||||
# This is the list of nixosModules for each machine
|
# This is the list of nixosModules for each machine
|
||||||
machineImports = lib.foldlAttrs (
|
machineImports = lib.foldlAttrs (
|
||||||
acc: _module_ident: eval:
|
acc: _module_ident: serviceModule:
|
||||||
acc ++ [ eval.config.result.final.${machineName}.nixosModule or { } ]
|
acc ++ [ serviceModule.result.final.${machineName}.nixosModule or { } ]
|
||||||
) [ ] importedModulesEvaluated;
|
) [ ] servicesEval.config.mappedServices;
|
||||||
}) inventory.machines or { };
|
}) inventory.machines or { };
|
||||||
|
|
||||||
|
evalServices =
|
||||||
|
{ modules, prefix }:
|
||||||
|
lib.evalModules {
|
||||||
|
specialArgs = {
|
||||||
|
inherit clanLib;
|
||||||
|
_ctx = prefix;
|
||||||
|
};
|
||||||
|
modules = [
|
||||||
|
./all-services-wrapper.nix
|
||||||
|
] ++ modules;
|
||||||
|
};
|
||||||
|
|
||||||
|
servicesEval = evalServices {
|
||||||
|
inherit prefix;
|
||||||
|
modules = [
|
||||||
|
{
|
||||||
|
inherit exportsModule;
|
||||||
|
mappedServices = lib.mapAttrs (_module_ident: instances: {
|
||||||
|
imports =
|
||||||
|
[
|
||||||
|
# Import the resolved module.
|
||||||
|
# i.e. clan.modules.admin
|
||||||
|
(builtins.head instances).instance.resolvedModule
|
||||||
|
] # Include all the instances that correlate to the resolved module
|
||||||
|
++ (builtins.map (v: {
|
||||||
|
instances.${v.instanceName}.roles = v.instance.instanceRoles;
|
||||||
|
}) instances);
|
||||||
|
}) grouped;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
importedModulesEvaluated = servicesEval.config.mappedServices;
|
||||||
|
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
inherit
|
inherit
|
||||||
|
servicesEval
|
||||||
importedModuleWithInstances
|
importedModuleWithInstances
|
||||||
grouped
|
grouped
|
||||||
allMachines
|
allMachines
|
||||||
|
|||||||
@@ -104,6 +104,13 @@ let
|
|||||||
in
|
in
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
|
# Option to disable some behavior during docs rendering
|
||||||
|
_docs_rendering = mkOption {
|
||||||
|
default = false;
|
||||||
|
visible = false;
|
||||||
|
type = types.bool;
|
||||||
|
};
|
||||||
|
|
||||||
instances = mkOption {
|
instances = mkOption {
|
||||||
visible = false;
|
visible = false;
|
||||||
defaultText = "Throws: 'The service must define its instances' when not defined";
|
defaultText = "Throws: 'The service must define its instances' when not defined";
|
||||||
@@ -384,6 +391,33 @@ in
|
|||||||
type = types.deferredModuleWith {
|
type = types.deferredModuleWith {
|
||||||
staticModules = [
|
staticModules = [
|
||||||
({
|
({
|
||||||
|
options.exports = mkOption {
|
||||||
|
type = types.deferredModule;
|
||||||
|
default = { };
|
||||||
|
description = ''
|
||||||
|
export modules defined in 'perInstance'
|
||||||
|
mapped to their instance name
|
||||||
|
|
||||||
|
Example
|
||||||
|
|
||||||
|
with instances:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
instances.A = { ... };
|
||||||
|
instances.B= { ... };
|
||||||
|
|
||||||
|
roles.peer.perInstance = { instanceName, machine, ... }:
|
||||||
|
{
|
||||||
|
exports.foo = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
This yields all other services can access these exports
|
||||||
|
=>
|
||||||
|
exports.instances.A.foo = 1;
|
||||||
|
exports.instances.B.foo = 1;
|
||||||
|
```
|
||||||
|
'';
|
||||||
|
};
|
||||||
options.nixosModule = mkOption {
|
options.nixosModule = mkOption {
|
||||||
type = types.deferredModule;
|
type = types.deferredModule;
|
||||||
default = { };
|
default = { };
|
||||||
@@ -493,6 +527,32 @@ in
|
|||||||
type = types.deferredModuleWith {
|
type = types.deferredModuleWith {
|
||||||
staticModules = [
|
staticModules = [
|
||||||
({
|
({
|
||||||
|
options.exports = mkOption {
|
||||||
|
type = types.deferredModule;
|
||||||
|
default = { };
|
||||||
|
description = ''
|
||||||
|
export modules defined in 'perMachine'
|
||||||
|
mapped to their machine name
|
||||||
|
|
||||||
|
Example
|
||||||
|
|
||||||
|
with machines:
|
||||||
|
```nix
|
||||||
|
instances.A = { roles.peer.machines.jon = ... };
|
||||||
|
instances.B = { roles.peer.machines.jon = ... };
|
||||||
|
|
||||||
|
perMachine = { machine, ... }:
|
||||||
|
{
|
||||||
|
exports.foo = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
This yields all other services can access these exports
|
||||||
|
=>
|
||||||
|
exports.machines.jon.foo = 1;
|
||||||
|
exports.machines.sara.foo = 1;
|
||||||
|
```
|
||||||
|
'';
|
||||||
|
};
|
||||||
options.nixosModule = mkOption {
|
options.nixosModule = mkOption {
|
||||||
type = types.deferredModule;
|
type = types.deferredModule;
|
||||||
default = { };
|
default = { };
|
||||||
@@ -568,6 +628,96 @@ in
|
|||||||
modules = [ v ];
|
modules = [ v ];
|
||||||
}).config;
|
}).config;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
exports = mkOption {
|
||||||
|
description = ''
|
||||||
|
This services exports.
|
||||||
|
Gets merged with all other services exports
|
||||||
|
|
||||||
|
Final value (merged and evaluated with other services) available as `exports'` in the arguments of this module.
|
||||||
|
|
||||||
|
```nix
|
||||||
|
{ exports', ... }: {
|
||||||
|
_class = "clan.service";
|
||||||
|
# ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
'';
|
||||||
|
default = { };
|
||||||
|
type = types.submoduleWith {
|
||||||
|
# Static modules
|
||||||
|
modules = [
|
||||||
|
{
|
||||||
|
options.instances = mkOption {
|
||||||
|
type = types.attrsOf types.deferredModule;
|
||||||
|
description = ''
|
||||||
|
export modules defined in 'perInstance'
|
||||||
|
mapped to their instance name
|
||||||
|
|
||||||
|
Example
|
||||||
|
|
||||||
|
with instances:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
instances.A = { ... };
|
||||||
|
instances.B= { ... };
|
||||||
|
|
||||||
|
roles.peer.perInstance = { instanceName, machine, ... }:
|
||||||
|
{
|
||||||
|
exports.foo = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
This yields all other services can access these exports
|
||||||
|
=>
|
||||||
|
exports.instances.A.foo = 1;
|
||||||
|
exports.instances.B.foo = 1;
|
||||||
|
```
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
options.machines = mkOption {
|
||||||
|
type = types.attrsOf types.deferredModule;
|
||||||
|
description = ''
|
||||||
|
export modules defined in 'perMachine'
|
||||||
|
mapped to their machine name
|
||||||
|
|
||||||
|
Example
|
||||||
|
|
||||||
|
with machines:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
instances.A = { roles.peer.machines.jon = ... };
|
||||||
|
instances.B = { roles.peer.machines.jon = ... };
|
||||||
|
|
||||||
|
perMachine = { machine, ... }:
|
||||||
|
{
|
||||||
|
exports.foo = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
This yields all other services can access these exports
|
||||||
|
=>
|
||||||
|
exports.machines.jon.foo = 1;
|
||||||
|
exports.machines.sara.foo = 1;
|
||||||
|
```
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
# Lazy default via imports
|
||||||
|
# should probably be moved to deferredModuleWith { staticModules = [ ]; }
|
||||||
|
imports =
|
||||||
|
if config._docs_rendering then
|
||||||
|
[ ]
|
||||||
|
else
|
||||||
|
lib.mapAttrsToList (_roleName: role: {
|
||||||
|
instances = lib.mapAttrs (_instanceName: instance: {
|
||||||
|
imports = lib.mapAttrsToList (_machineName: v: v.exports) instance.allMachines;
|
||||||
|
}) role.allInstances;
|
||||||
|
}) config.result.allRoles
|
||||||
|
++ lib.mapAttrsToList (machineName: machine: {
|
||||||
|
machines.${machineName} = machine.exports;
|
||||||
|
}) config.result.allMachines;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
# ---
|
# ---
|
||||||
# Place the result in _module.result to mark them as "internal" and discourage usage/overrides
|
# Place the result in _module.result to mark them as "internal" and discourage usage/overrides
|
||||||
#
|
#
|
||||||
|
|||||||
@@ -48,9 +48,11 @@ let
|
|||||||
clanCoreModules = { };
|
clanCoreModules = { };
|
||||||
flakeInputs = flakeInputsFixture;
|
flakeInputs = flakeInputsFixture;
|
||||||
inherit inventory;
|
inherit inventory;
|
||||||
|
exportsModule = { };
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
exports = import ./exports.nix { inherit lib clanLib; };
|
||||||
resolve_module_spec = import ./import_module_spec.nix { inherit lib callInventoryAdapter; };
|
resolve_module_spec = import ./import_module_spec.nix { inherit lib callInventoryAdapter; };
|
||||||
test_simple =
|
test_simple =
|
||||||
let
|
let
|
||||||
@@ -171,7 +173,7 @@ in
|
|||||||
{
|
{
|
||||||
# Test that the module is mapped into the output
|
# Test that the module is mapped into the output
|
||||||
# We might change the attribute name in the future
|
# We might change the attribute name in the future
|
||||||
expr = lib.attrNames res.importedModulesEvaluated.self-A.config.instances;
|
expr = lib.attrNames res.importedModulesEvaluated.self-A.instances;
|
||||||
expected = [
|
expected = [
|
||||||
"instance_bar"
|
"instance_bar"
|
||||||
"instance_foo"
|
"instance_foo"
|
||||||
@@ -227,7 +229,7 @@ in
|
|||||||
{
|
{
|
||||||
# Test that the module is mapped into the output
|
# Test that the module is mapped into the output
|
||||||
# We might change the attribute name in the future
|
# We might change the attribute name in the future
|
||||||
expr = lib.attrNames res.importedModulesEvaluated.self-A.config.result.allMachines;
|
expr = lib.attrNames res.importedModulesEvaluated.self-A.result.allMachines;
|
||||||
expected = [
|
expected = [
|
||||||
"jon"
|
"jon"
|
||||||
"sara"
|
"sara"
|
||||||
@@ -279,13 +281,14 @@ in
|
|||||||
{
|
{
|
||||||
# Test that the module is mapped into the output
|
# Test that the module is mapped into the output
|
||||||
# We might change the attribute name in the future
|
# We might change the attribute name in the future
|
||||||
expr = lib.attrNames res.importedModulesEvaluated.self-A.config.result.allMachines;
|
expr = lib.attrNames res.importedModulesEvaluated.self-A.result.allMachines;
|
||||||
expected = [
|
expected = [
|
||||||
"jon"
|
"jon"
|
||||||
"sara"
|
"sara"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
machine_imports = import ./machine_imports.nix { inherit lib clanLib; };
|
||||||
per_machine_args = import ./per_machine_args.nix { inherit lib callInventoryAdapter; };
|
per_machine_args = import ./per_machine_args.nix { inherit lib callInventoryAdapter; };
|
||||||
per_instance_args = import ./per_instance_args.nix { inherit lib callInventoryAdapter; };
|
per_instance_args = import ./per_instance_args.nix { inherit lib callInventoryAdapter; };
|
||||||
}
|
}
|
||||||
|
|||||||
170
lib/modules/inventory/distributed-service/tests/exports.nix
Normal file
170
lib/modules/inventory/distributed-service/tests/exports.nix
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
{ lib, clanLib }:
|
||||||
|
let
|
||||||
|
clan = clanLib.clan {
|
||||||
|
self = { };
|
||||||
|
directory = ./.;
|
||||||
|
|
||||||
|
exportsModule = {
|
||||||
|
options.vars.generators = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf (
|
||||||
|
lib.types.submoduleWith {
|
||||||
|
# TODO: import the vars submodule here
|
||||||
|
modules = [
|
||||||
|
{
|
||||||
|
options.script = lib.mkOption { type = lib.types.str; };
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
);
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
machines.jon = { };
|
||||||
|
machines.sara = { };
|
||||||
|
# A module that adds exports perMachine
|
||||||
|
modules.A =
|
||||||
|
{ exports', ... }:
|
||||||
|
{
|
||||||
|
manifest.name = "A";
|
||||||
|
roles.peer.perInstance =
|
||||||
|
{ machine, ... }:
|
||||||
|
{
|
||||||
|
# Cross reference a perMachine exports
|
||||||
|
exports.vars.generators."${machine.name}-network-ip".script =
|
||||||
|
"A:" + exports'.machines.${machine.name}.vars.generators.key.script;
|
||||||
|
# Cross reference a perInstance exports from a different service
|
||||||
|
exports.vars.generators."${machine.name}-full-hostname".script =
|
||||||
|
"A:" + exports'.instances."B-1".vars.generators.hostname.script;
|
||||||
|
};
|
||||||
|
roles.server = { };
|
||||||
|
perMachine =
|
||||||
|
{ machine, ... }:
|
||||||
|
{
|
||||||
|
exports = {
|
||||||
|
vars.generators.key.script = machine.name;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
# A module that adds exports perInstance
|
||||||
|
modules.B = {
|
||||||
|
manifest.name = "B";
|
||||||
|
roles.peer.perInstance =
|
||||||
|
{ instanceName, ... }:
|
||||||
|
{
|
||||||
|
exports = {
|
||||||
|
vars.generators.hostname.script = instanceName;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
inventory = {
|
||||||
|
instances.B-1 = {
|
||||||
|
module.name = "B";
|
||||||
|
module.input = "self";
|
||||||
|
roles.peer.tags.all = { };
|
||||||
|
};
|
||||||
|
instances.B-2 = {
|
||||||
|
module.name = "B";
|
||||||
|
module.input = "self";
|
||||||
|
roles.peer.tags.all = { };
|
||||||
|
};
|
||||||
|
instances.A-1 = {
|
||||||
|
module.name = "A";
|
||||||
|
module.input = "self";
|
||||||
|
roles.peer.tags.all = { };
|
||||||
|
roles.server.tags.all = { };
|
||||||
|
};
|
||||||
|
instances.A-2 = {
|
||||||
|
module.name = "A";
|
||||||
|
module.input = "self";
|
||||||
|
roles.peer.tags.all = { };
|
||||||
|
roles.server.tags.all = { };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
test_1 = {
|
||||||
|
inherit clan;
|
||||||
|
expr = clan.config.exports;
|
||||||
|
expected = {
|
||||||
|
instances = {
|
||||||
|
A-1 = {
|
||||||
|
vars = {
|
||||||
|
generators = {
|
||||||
|
jon-full-hostname = {
|
||||||
|
script = "A:B-1";
|
||||||
|
};
|
||||||
|
jon-network-ip = {
|
||||||
|
script = "A:jon";
|
||||||
|
};
|
||||||
|
sara-full-hostname = {
|
||||||
|
script = "A:B-1";
|
||||||
|
};
|
||||||
|
sara-network-ip = {
|
||||||
|
script = "A:sara";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
A-2 = {
|
||||||
|
vars = {
|
||||||
|
generators = {
|
||||||
|
jon-full-hostname = {
|
||||||
|
script = "A:B-1";
|
||||||
|
};
|
||||||
|
jon-network-ip = {
|
||||||
|
script = "A:jon";
|
||||||
|
};
|
||||||
|
sara-full-hostname = {
|
||||||
|
script = "A:B-1";
|
||||||
|
};
|
||||||
|
sara-network-ip = {
|
||||||
|
script = "A:sara";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
B-1 = {
|
||||||
|
vars = {
|
||||||
|
generators = {
|
||||||
|
hostname = {
|
||||||
|
script = "B-1";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
B-2 = {
|
||||||
|
vars = {
|
||||||
|
generators = {
|
||||||
|
hostname = {
|
||||||
|
script = "B-2";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
machines = {
|
||||||
|
jon = {
|
||||||
|
vars = {
|
||||||
|
generators = {
|
||||||
|
key = {
|
||||||
|
script = "jon";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
sara = {
|
||||||
|
vars = {
|
||||||
|
generators = {
|
||||||
|
key = {
|
||||||
|
script = "sara";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
{ lib, clanLib }:
|
||||||
|
let
|
||||||
|
clan = clanLib.clan {
|
||||||
|
self = { };
|
||||||
|
directory = ./.;
|
||||||
|
|
||||||
|
machines.jon = { };
|
||||||
|
machines.sara = { };
|
||||||
|
# A module that adds exports perMachine
|
||||||
|
modules.A =
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
manifest.name = "A";
|
||||||
|
roles.peer.perInstance =
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
nixosModule = {
|
||||||
|
options.bar = lib.mkOption {
|
||||||
|
default = 1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
roles.server = { };
|
||||||
|
perMachine =
|
||||||
|
{ ... }:
|
||||||
|
{
|
||||||
|
nixosModule = {
|
||||||
|
options.foo = lib.mkOption {
|
||||||
|
default = 1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
inventory.instances.A = {
|
||||||
|
module.input = "self";
|
||||||
|
roles.peer.tags.all = { };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
test_1 = {
|
||||||
|
inherit clan;
|
||||||
|
expr = { inherit (clan.config.clanInternals.machines.x86_64-linux.jon.config) bar foo; };
|
||||||
|
expected = {
|
||||||
|
foo = 1;
|
||||||
|
bar = 1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -106,7 +106,7 @@ in
|
|||||||
test_per_instance_arguments = {
|
test_per_instance_arguments = {
|
||||||
expr = {
|
expr = {
|
||||||
instanceName =
|
instanceName =
|
||||||
res.importedModulesEvaluated.self-A.config.result.allRoles.peer.allInstances."instance_foo".allMachines.jon.passthru.instanceName;
|
res.importedModulesEvaluated.self-A.result.allRoles.peer.allInstances."instance_foo".allMachines.jon.passthru.instanceName;
|
||||||
|
|
||||||
# settings are specific.
|
# settings are specific.
|
||||||
# Below we access:
|
# Below we access:
|
||||||
@@ -114,11 +114,11 @@ in
|
|||||||
# roles = peer
|
# roles = peer
|
||||||
# machines = jon
|
# machines = jon
|
||||||
settings =
|
settings =
|
||||||
res.importedModulesEvaluated.self-A.config.result.allRoles.peer.allInstances.instance_foo.allMachines.jon.passthru.settings;
|
res.importedModulesEvaluated.self-A.result.allRoles.peer.allInstances.instance_foo.allMachines.jon.passthru.settings;
|
||||||
machine =
|
machine =
|
||||||
res.importedModulesEvaluated.self-A.config.result.allRoles.peer.allInstances.instance_foo.allMachines.jon.passthru.machine;
|
res.importedModulesEvaluated.self-A.result.allRoles.peer.allInstances.instance_foo.allMachines.jon.passthru.machine;
|
||||||
roles =
|
roles =
|
||||||
res.importedModulesEvaluated.self-A.config.result.allRoles.peer.allInstances.instance_foo.allMachines.jon.passthru.roles;
|
res.importedModulesEvaluated.self-A.result.allRoles.peer.allInstances.instance_foo.allMachines.jon.passthru.roles;
|
||||||
};
|
};
|
||||||
expected = {
|
expected = {
|
||||||
instanceName = "instance_foo";
|
instanceName = "instance_foo";
|
||||||
@@ -161,9 +161,9 @@ in
|
|||||||
|
|
||||||
# TODO: Cannot be tested like this anymore
|
# TODO: Cannot be tested like this anymore
|
||||||
test_per_instance_settings_vendoring = {
|
test_per_instance_settings_vendoring = {
|
||||||
x = res.importedModulesEvaluated.self-A.config;
|
x = res.importedModulesEvaluated.self-A;
|
||||||
expr =
|
expr =
|
||||||
res.importedModulesEvaluated.self-A.config.result.allRoles.peer.allInstances.instance_foo.allMachines.jon.passthru.vendoredSettings;
|
res.importedModulesEvaluated.self-A.result.allRoles.peer.allInstances.instance_foo.allMachines.jon.passthru.vendoredSettings;
|
||||||
expected = {
|
expected = {
|
||||||
timeout = "config.thing";
|
timeout = "config.thing";
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ in
|
|||||||
inherit res;
|
inherit res;
|
||||||
expr = {
|
expr = {
|
||||||
hasMachineSettings =
|
hasMachineSettings =
|
||||||
res.importedModulesEvaluated.self-A.config.result.allMachines.jon.passthru.instances.instance_foo.roles.peer.machines.jon
|
res.importedModulesEvaluated.self-A.result.allMachines.jon.passthru.instances.instance_foo.roles.peer.machines.jon
|
||||||
? settings;
|
? settings;
|
||||||
|
|
||||||
# settings are specific.
|
# settings are specific.
|
||||||
@@ -89,10 +89,10 @@ in
|
|||||||
# instance = instance_foo
|
# instance = instance_foo
|
||||||
# roles = peer
|
# roles = peer
|
||||||
# machines = jon
|
# machines = jon
|
||||||
specificMachineSettings = filterInternals res.importedModulesEvaluated.self-A.config.result.allMachines.jon.passthru.instances.instance_foo.roles.peer.machines.jon.settings;
|
specificMachineSettings = filterInternals res.importedModulesEvaluated.self-A.result.allMachines.jon.passthru.instances.instance_foo.roles.peer.machines.jon.settings;
|
||||||
|
|
||||||
hasRoleSettings =
|
hasRoleSettings =
|
||||||
res.importedModulesEvaluated.self-A.config.result.allMachines.jon.passthru.instances.instance_foo.roles.peer
|
res.importedModulesEvaluated.self-A.result.allMachines.jon.passthru.instances.instance_foo.roles.peer
|
||||||
? settings;
|
? settings;
|
||||||
|
|
||||||
# settings are specific.
|
# settings are specific.
|
||||||
@@ -100,7 +100,7 @@ in
|
|||||||
# instance = instance_foo
|
# instance = instance_foo
|
||||||
# roles = peer
|
# roles = peer
|
||||||
# machines = *
|
# machines = *
|
||||||
specificRoleSettings = filterInternals res.importedModulesEvaluated.self-A.config.result.allMachines.jon.passthru.instances.instance_foo.roles.peer.settings;
|
specificRoleSettings = filterInternals res.importedModulesEvaluated.self-A.result.allMachines.jon.passthru.instances.instance_foo.roles.peer.settings;
|
||||||
};
|
};
|
||||||
expected = {
|
expected = {
|
||||||
hasMachineSettings = true;
|
hasMachineSettings = true;
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ in
|
|||||||
(pkgs.nixosOptionsDoc {
|
(pkgs.nixosOptionsDoc {
|
||||||
options =
|
options =
|
||||||
(self.clanLib.evalService {
|
(self.clanLib.evalService {
|
||||||
modules = [ ];
|
modules = [ { _docs_rendering = true; } ];
|
||||||
prefix = [ ];
|
prefix = [ ];
|
||||||
}).options;
|
}).options;
|
||||||
warningsAreErrors = true;
|
warningsAreErrors = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user