Inventory: move to lib.inventory
This commit is contained in:
committed by
hsjobeki
parent
6378a96b4d
commit
3aa7a6ee69
@@ -33,7 +33,7 @@ let
|
||||
mergedInventory =
|
||||
(lib.evalModules {
|
||||
modules = [
|
||||
./interface.nix
|
||||
clan-core.lib.inventory.interface
|
||||
{ inherit meta; }
|
||||
(
|
||||
if
|
||||
@@ -77,7 +77,7 @@ let
|
||||
];
|
||||
}).config;
|
||||
|
||||
buildInventory = import ./inventory.nix { inherit lib clan-core; };
|
||||
inherit (clan-core.lib.inventory) buildInventory;
|
||||
|
||||
# map from machine name to service configuration
|
||||
# { ${machineName} :: Config }
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
}:
|
||||
{
|
||||
evalClanModules = import ./eval-clan-modules { inherit clan-core nixpkgs lib; };
|
||||
inventory = import ./inventory { inherit lib clan-core; };
|
||||
jsonschema = import ./jsonschema { inherit lib; };
|
||||
modules = import ./description.nix { inherit clan-core lib; };
|
||||
buildClan = import ./build-clan { inherit clan-core lib nixpkgs; };
|
||||
|
||||
5
lib/inventory/.envrc
Normal file
5
lib/inventory/.envrc
Normal file
@@ -0,0 +1,5 @@
|
||||
source_up
|
||||
|
||||
watch_file flake-module.nix
|
||||
|
||||
use flake .#inventory-schema --builders ''
|
||||
90
lib/inventory/README.md
Normal file
90
lib/inventory/README.md
Normal file
@@ -0,0 +1,90 @@
|
||||
# Inventory
|
||||
|
||||
The inventory is our concept for distributed services. Users can configure multiple machines with minimal effort.
|
||||
|
||||
- The inventory acts as a declarative source of truth for all machine configurations.
|
||||
- Users can easily add or remove machines to/from services.
|
||||
- Ensures that all machines and services are configured consistently, across multiple nixosConfigs.
|
||||
- Defaults and predefined roles in our modules minimizes the need for manual configuration.
|
||||
|
||||
Open questions:
|
||||
|
||||
- [ ] How do we set default role, description and other metadata?
|
||||
- It must be accessible from Python.
|
||||
- It must set the value in the module system.
|
||||
|
||||
- [ ] Inventory might use assertions. Should each machine inherit the inventory assertions ?
|
||||
|
||||
- [ ] Is the service config interface the same as the module config interface ?
|
||||
|
||||
- [ ] As a user do I want to see borgbackup as the high level category?
|
||||
|
||||
|
||||
Architecture
|
||||
|
||||
```
|
||||
nixosConfig < machine_module < inventory
|
||||
---------------------------------------------
|
||||
nixos < borgbackup <- inventory <-> UI
|
||||
|
||||
creates the config Maps from high level services to the borgbackup clan module
|
||||
for ONE machine Inventory is completely serializable.
|
||||
UI can interact with the inventory to define machines, and services
|
||||
Defining Users is out of scope for the first prototype.
|
||||
```
|
||||
|
||||
## Provides a specification for the inventory
|
||||
|
||||
It is used for design phase and as validation helper.
|
||||
|
||||
> Cue is less verbose and easier to understand and maintain than json-schema.
|
||||
> Json-schema, if needed can be easily generated on-the fly.
|
||||
|
||||
## Checking validity
|
||||
|
||||
Directly check a json against the schema
|
||||
|
||||
`cue vet inventory.json root.cue -d '#Root'`
|
||||
|
||||
## Json schema
|
||||
|
||||
Export the json-schema i.e. for usage in python / javascript / nix
|
||||
|
||||
`cue export --out openapi root.cue`
|
||||
|
||||
## Usage
|
||||
|
||||
Comments are rendered as descriptions in the json schema.
|
||||
|
||||
```cue
|
||||
// A name of the clan (primarily shown by the UI)
|
||||
name: string
|
||||
```
|
||||
|
||||
Cue open sets. In the following `foo = {...}` means that the key `foo` can contain any arbitrary json object.
|
||||
|
||||
```cue
|
||||
foo: { ... }
|
||||
```
|
||||
|
||||
Cue dynamic keys.
|
||||
|
||||
```cue
|
||||
[string]: {
|
||||
attr: string
|
||||
}
|
||||
```
|
||||
|
||||
This is the schema of
|
||||
|
||||
```json
|
||||
{
|
||||
"a": {
|
||||
"attr": "foo"
|
||||
},
|
||||
"b": {
|
||||
"attr": "bar"
|
||||
}
|
||||
// ... Indefinitely more dynamic keys of type "string"
|
||||
}
|
||||
```
|
||||
32
lib/inventory/_old_default.nix
Normal file
32
lib/inventory/_old_default.nix
Normal file
@@ -0,0 +1,32 @@
|
||||
{ self, lib, ... }:
|
||||
let
|
||||
clan-core = self;
|
||||
in
|
||||
{
|
||||
clan = clan-core.lib.buildClan {
|
||||
meta.name = "kenjis clan";
|
||||
# Should usually point to the directory of flake.nix
|
||||
directory = self;
|
||||
|
||||
inventory = {
|
||||
services = {
|
||||
borgbackup.instance_1 = {
|
||||
roles.server.machines = [ "vyr_machine" ];
|
||||
roles.client.tags = [ "laptop" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# merged with
|
||||
machines = {
|
||||
"vyr_machine" = { };
|
||||
"vi_machine" = {
|
||||
clan.tags = [ "laptop" ];
|
||||
};
|
||||
"camina_machine" = {
|
||||
clan.tags = [ "laptop" ];
|
||||
clan.meta.name = "camina";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -78,6 +78,7 @@ in
|
||||
};
|
||||
|
||||
options.services = lib.mkOption {
|
||||
default = { };
|
||||
type = t.attrsOf (
|
||||
t.attrsOf (
|
||||
t.submodule {
|
||||
5
lib/inventory/default.nix
Normal file
5
lib/inventory/default.nix
Normal file
@@ -0,0 +1,5 @@
|
||||
{ lib, clan-core }:
|
||||
{
|
||||
buildInventory = import ./build-inventory { inherit lib clan-core; };
|
||||
interface = ./build-inventory/interface.nix;
|
||||
}
|
||||
48
lib/inventory/flake-module.nix
Normal file
48
lib/inventory/flake-module.nix
Normal file
@@ -0,0 +1,48 @@
|
||||
{ ... }:
|
||||
{
|
||||
# flake.inventory = import ./default.nix { inherit inputs self lib; };
|
||||
perSystem =
|
||||
{ pkgs, config, ... }:
|
||||
{
|
||||
packages.inventory-schema = pkgs.stdenv.mkDerivation {
|
||||
name = "inventory-schema";
|
||||
src = ./src;
|
||||
|
||||
buildInputs = [ pkgs.cue ];
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
'';
|
||||
};
|
||||
|
||||
devShells.inventory-schema = pkgs.mkShell { inputsFrom = [ config.packages.inventory-schema ]; };
|
||||
|
||||
checks.inventory-schema-checks = pkgs.stdenv.mkDerivation {
|
||||
name = "inventory-schema-checks";
|
||||
src = ./src;
|
||||
buildInputs = [ pkgs.cue ];
|
||||
buildPhase = ''
|
||||
echo "Running inventory tests..."
|
||||
|
||||
echo "Export cue as json-schema..."
|
||||
cue export --out openapi root.cue
|
||||
|
||||
echo "Validate test/*.json against inventory-schema..."
|
||||
|
||||
test_dir="test"
|
||||
for file in "$test_dir"/*; do
|
||||
# Check if the item is a file
|
||||
if [ -f "$file" ]; then
|
||||
# Print the filename
|
||||
echo "Running test on: $file"
|
||||
|
||||
# Run the cue vet command
|
||||
cue vet "$file" root.cue -d "#Root"
|
||||
fi
|
||||
done
|
||||
|
||||
touch $out
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
2
lib/inventory/src/cue.mod/module.cue
Normal file
2
lib/inventory/src/cue.mod/module.cue
Normal file
@@ -0,0 +1,2 @@
|
||||
module: "clan.lol/inventory"
|
||||
language: version: "v0.8.2"
|
||||
23
lib/inventory/src/root.cue
Normal file
23
lib/inventory/src/root.cue
Normal file
@@ -0,0 +1,23 @@
|
||||
package inventory
|
||||
|
||||
import (
|
||||
"clan.lol/inventory/schema"
|
||||
)
|
||||
|
||||
@jsonschema(schema="http://json-schema.org/schema#")
|
||||
#Root: {
|
||||
meta: {
|
||||
// A name of the clan (primarily shown by the UI)
|
||||
name: string
|
||||
// A description of the clan
|
||||
description?: string
|
||||
// The icon path
|
||||
icon?: string
|
||||
}
|
||||
|
||||
// // A map of services
|
||||
schema.#service
|
||||
|
||||
// // A map of machines
|
||||
schema.#machine
|
||||
}
|
||||
39
lib/inventory/src/schema/schema.cue
Normal file
39
lib/inventory/src/schema/schema.cue
Normal file
@@ -0,0 +1,39 @@
|
||||
package schema
|
||||
|
||||
#machine: machines: [string]: {
|
||||
name: string,
|
||||
description?: string,
|
||||
icon?: string
|
||||
tags: [...string]
|
||||
}
|
||||
|
||||
#role: string
|
||||
|
||||
#service: services: [string]: [string]: {
|
||||
// Required meta fields
|
||||
meta: {
|
||||
name: string,
|
||||
icon?: string
|
||||
description?: string,
|
||||
},
|
||||
// We moved the machine sepcific config to "machines".
|
||||
// It may be moved back depending on what makes more sense in the future.
|
||||
roles: [#role]: {
|
||||
machines: [...string],
|
||||
tags: [...string],
|
||||
}
|
||||
machines: {
|
||||
[string]: {
|
||||
config?: {
|
||||
...
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Configuration for the service
|
||||
config: {
|
||||
// Schema depends on the module.
|
||||
// It declares the interface how the service can be configured.
|
||||
...
|
||||
}
|
||||
}
|
||||
53
lib/inventory/src/tests/borgbackup.json
Normal file
53
lib/inventory/src/tests/borgbackup.json
Normal file
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"machines": {
|
||||
"camina_machine": {
|
||||
"name": "camina",
|
||||
"tags": ["laptop"]
|
||||
},
|
||||
"vyr_machine": {
|
||||
"name": "vyr"
|
||||
},
|
||||
"vi_machine": {
|
||||
"name": "vi",
|
||||
"tags": ["laptop"]
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"name": "kenjis clan"
|
||||
},
|
||||
"services": {
|
||||
"borgbackup": {
|
||||
"instance_1": {
|
||||
"meta": {
|
||||
"name": "My backup"
|
||||
},
|
||||
"roles": {
|
||||
"server": {
|
||||
"machines": ["vyr_machine"]
|
||||
},
|
||||
"client": {
|
||||
"machines": ["vyr_machine"],
|
||||
"tags": ["laptop"]
|
||||
}
|
||||
},
|
||||
"machines": {},
|
||||
"config": {}
|
||||
},
|
||||
"instance_2": {
|
||||
"meta": {
|
||||
"name": "My backup"
|
||||
},
|
||||
"roles": {
|
||||
"server": {
|
||||
"machines": ["vi_machine"]
|
||||
},
|
||||
"client": {
|
||||
"machines": ["camina_machine"]
|
||||
}
|
||||
},
|
||||
"machines": {},
|
||||
"config": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
47
lib/inventory/src/tests/syncthing.json
Normal file
47
lib/inventory/src/tests/syncthing.json
Normal file
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"machines": {
|
||||
"camina_machine": {
|
||||
"name": "camina"
|
||||
},
|
||||
"vyr_machine": {
|
||||
"name": "vyr"
|
||||
},
|
||||
"vi_machine": {
|
||||
"name": "vi"
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"name": "kenjis clan"
|
||||
},
|
||||
"services": {
|
||||
"syncthing": {
|
||||
"instance_1": {
|
||||
"meta": {
|
||||
"name": "My sync"
|
||||
},
|
||||
"roles": {
|
||||
"peer": {
|
||||
"machines": ["vyr_machine", "vi_machine", "camina_machine"]
|
||||
}
|
||||
},
|
||||
"machines": {},
|
||||
"config": {
|
||||
"folders": {
|
||||
"test": {
|
||||
"path": "~/data/docs",
|
||||
"devices": ["camina_machine", "vyr_machine", "vi_machine"]
|
||||
},
|
||||
"videos": {
|
||||
"path": "~/data/videos",
|
||||
"devices": ["camina_machine", "vyr_machine"]
|
||||
},
|
||||
"playlist": {
|
||||
"path": "~/data/playlist",
|
||||
"devices": ["camina_machine", "vi_machine"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
36
lib/inventory/src/tests/zerotier.json
Normal file
36
lib/inventory/src/tests/zerotier.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"machines": {
|
||||
"camina_machine": {
|
||||
"name": "camina"
|
||||
},
|
||||
"vyr_machine": {
|
||||
"name": "vyr"
|
||||
},
|
||||
"vi_machine": {
|
||||
"name": "vi"
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"name": "kenjis clan"
|
||||
},
|
||||
"services": {
|
||||
"zerotier": {
|
||||
"instance_1": {
|
||||
"meta": {
|
||||
"name": "My Network"
|
||||
},
|
||||
"roles": {
|
||||
"controller": { "machines": ["vyr_machine"] },
|
||||
"moon": { "machines": ["vyr_machine"] },
|
||||
"peer": { "machines": ["vi_machine", "camina_machine"] }
|
||||
},
|
||||
"machines": {
|
||||
"vyr_machine": {
|
||||
"config": {}
|
||||
}
|
||||
},
|
||||
"config": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user