Inventory: init first implementation #1638
@ -45,6 +45,13 @@ let
|
|||||||
# Maybe load from readme.md
|
# Maybe load from readme.md
|
||||||
metaInfoOption = lib.mkOption {
|
metaInfoOption = lib.mkOption {
|
||||||
readOnly = true;
|
readOnly = true;
|
||||||
|
description = ''
|
||||||
|
Meta is used to retrieve information about this module.
|
||||||
|
|
||||||
|
- `availableRoles` is a list of roles that can be assigned via the inventory.
|
||||||
|
- `category` is used to group services in the clan marketplace.
|
||||||
|
- `description` is a short description of the service for the clan marketplace.
|
||||||
|
'';
|
||||||
default = {
|
default = {
|
||||||
description = "Borgbackup is a backup program. Optionally, it supports compression and authenticated encryption.";
|
description = "Borgbackup is a backup program. Optionally, it supports compression and authenticated encryption.";
|
||||||
availableRoles = roles;
|
availableRoles = roles;
|
||||||
|
@ -78,7 +78,9 @@ def render_option(name: str, option: dict[str, Any], level: int = 3) -> str:
|
|||||||
|
|
||||||
res = f"""
|
res = f"""
|
||||||
{"#" * level} {sanitize(name)}
|
{"#" * level} {sanitize(name)}
|
||||||
{"Readonly" if read_only else ""}
|
|
||||||
|
{"**Readonly**" if read_only else ""}
|
||||||
|
|
||||||
{option.get("description", "No description available.")}
|
{option.get("description", "No description available.")}
|
||||||
|
|
||||||
**Type**: `{option["type"]}`
|
**Type**: `{option["type"]}`
|
||||||
@ -190,6 +192,35 @@ def produce_clan_core_docs() -> None:
|
|||||||
of.write(output)
|
of.write(output)
|
||||||
|
|
||||||
|
|
||||||
|
def render_meta(meta: dict[str, Any], module_name: str) -> str:
|
||||||
|
roles = meta.get("availableRoles", None)
|
||||||
|
|
||||||
|
if roles:
|
||||||
|
roles_list = "\n".join([f" - `{r}`" for r in roles])
|
||||||
|
return f"""
|
||||||
|
???+ tip "Inventory (WIP)"
|
||||||
|
|
||||||
|
Predefined roles:
|
||||||
|
|
||||||
|
{roles_list}
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
```{{.nix hl_lines="4"}}
|
||||||
|
buildClan {{
|
||||||
|
inventory.services = {{
|
||||||
|
{module_name}.instance_1 = {{
|
||||||
|
roles.{roles[0]}.machines = [ "sara_machine" ];
|
||||||
|
# ...
|
||||||
|
}};
|
||||||
|
}};
|
||||||
|
}}
|
||||||
|
```
|
||||||
|
|
||||||
|
"""
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
def produce_clan_modules_docs() -> None:
|
def produce_clan_modules_docs() -> None:
|
||||||
if not CLAN_MODULES:
|
if not CLAN_MODULES:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
@ -218,38 +249,6 @@ def produce_clan_modules_docs() -> None:
|
|||||||
meta_map: dict[str, Any] = json.load(f)
|
meta_map: dict[str, Any] = json.load(f)
|
||||||
print(meta_map)
|
print(meta_map)
|
||||||
|
|
||||||
def render_meta(meta: dict[str, Any], module_name: str) -> str:
|
|
||||||
roles = meta.get("availableRoles", None)
|
|
||||||
|
|
||||||
if roles:
|
|
||||||
roles_list = "\n".join([f" - `{r}`" for r in roles])
|
|
||||||
return f"""
|
|
||||||
???+ tip "Inventory (WIP)"
|
|
||||||
|
|
||||||
Predefined roles:
|
|
||||||
|
|
||||||
{roles_list}
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
|
|
||||||
```{{.nix hl_lines="4"}}
|
|
||||||
buildClan {{
|
|
||||||
inventory.services = {{
|
|
||||||
{module_name}.instance_1 = {{
|
|
||||||
roles.{roles[0]}.machines = [ "sara_machine" ];
|
|
||||||
# ...
|
|
||||||
}};
|
|
||||||
}};
|
|
||||||
}}
|
|
||||||
```
|
|
||||||
|
|
||||||
"""
|
|
||||||
return """
|
|
||||||
???+ example "Inventory (WIP)"
|
|
||||||
This module does not support the inventory yet.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
# {'borgbackup': '/nix/store/hi17dwgy7963ddd4ijh81fv0c9sbh8sw-options.json', ... }
|
# {'borgbackup': '/nix/store/hi17dwgy7963ddd4ijh81fv0c9sbh8sw-options.json', ... }
|
||||||
for module_name, options_file in links.items():
|
for module_name, options_file in links.items():
|
||||||
with open(Path(options_file) / "share/doc/nixos/options.json") as f:
|
with open(Path(options_file) / "share/doc/nixos/options.json") as f:
|
||||||
@ -262,6 +261,7 @@ def produce_clan_modules_docs() -> None:
|
|||||||
|
|
||||||
# Add meta information:
|
# Add meta information:
|
||||||
# - Inventory implementation status
|
# - Inventory implementation status
|
||||||
|
if meta_map.get(module_name, None):
|
||||||
output += render_meta(meta_map.get(module_name, {}), module_name)
|
output += render_meta(meta_map.get(module_name, {}), module_name)
|
||||||
|
|
||||||
output += module_usage(module_name)
|
output += module_usage(module_name)
|
||||||
|
@ -70,6 +70,8 @@ let
|
|||||||
}
|
}
|
||||||
) machines;
|
) machines;
|
||||||
}
|
}
|
||||||
|
# Will be deprecated
|
||||||
|
# {machines = lib.mapAttrs (n: _: {}) machinesDirs;}
|
||||||
|
|
||||||
# Deprecated interface
|
# Deprecated interface
|
||||||
(if clanName != null then { meta.name = clanName; } else { })
|
(if clanName != null then { meta.name = clanName; } else { })
|
||||||
@ -83,6 +85,25 @@ let
|
|||||||
# { ${machineName} :: Config }
|
# { ${machineName} :: Config }
|
||||||
serviceConfigs = buildInventory mergedInventory;
|
serviceConfigs = buildInventory mergedInventory;
|
||||||
|
|
||||||
|
# machinesDirs = lib.optionalAttrs (builtins.pathExists "${directory}/machines") (
|
||||||
|
# builtins.readDir (directory + /machines)
|
||||||
|
# );
|
||||||
|
|
||||||
|
machineSettings =
|
||||||
|
machineName:
|
||||||
|
# CLAN_MACHINE_SETTINGS_FILE allows to override the settings file temporarily
|
||||||
|
# This is useful for doing a dry-run before writing changes into the settings.json
|
||||||
|
# Using CLAN_MACHINE_SETTINGS_FILE requires passing --impure to nix eval
|
||||||
|
if builtins.getEnv "CLAN_MACHINE_SETTINGS_FILE" != "" then
|
||||||
|
builtins.fromJSON (builtins.readFile (builtins.getEnv "CLAN_MACHINE_SETTINGS_FILE"))
|
||||||
|
else
|
||||||
|
lib.optionalAttrs (builtins.pathExists "${directory}/machines/${machineName}/settings.json") (
|
||||||
|
builtins.fromJSON (builtins.readFile (directory + /machines/${machineName}/settings.json))
|
||||||
|
);
|
||||||
|
|
||||||
|
machineImports =
|
||||||
|
machineSettings: map (module: clan-core.clanModules.${module}) (machineSettings.clanImports or [ ]);
|
||||||
|
|
||||||
deprecationWarnings = [
|
deprecationWarnings = [
|
||||||
(lib.warnIf (
|
(lib.warnIf (
|
||||||
clanName != null
|
clanName != null
|
||||||
@ -99,7 +120,12 @@ let
|
|||||||
extraConfig ? { },
|
extraConfig ? { },
|
||||||
}:
|
}:
|
||||||
nixpkgs.lib.nixosSystem {
|
nixpkgs.lib.nixosSystem {
|
||||||
modules = [
|
modules =
|
||||||
|
let
|
||||||
|
settings = machineSettings name;
|
||||||
|
in
|
||||||
|
(machineImports settings)
|
||||||
|
++ [
|
||||||
clan-core.nixosModules.clanCore
|
clan-core.nixosModules.clanCore
|
||||||
extraConfig
|
extraConfig
|
||||||
(machines.${name} or { })
|
(machines.${name} or { })
|
||||||
|
@ -5,7 +5,10 @@
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
{
|
{
|
||||||
imports = [ ./jsonschema/flake-module.nix ];
|
imports = [
|
||||||
|
./jsonschema/flake-module.nix
|
||||||
|
./inventory/flake-module.nix
|
||||||
|
];
|
||||||
flake.lib = import ./default.nix {
|
flake.lib = import ./default.nix {
|
||||||
inherit lib inputs;
|
inherit lib inputs;
|
||||||
inherit (inputs) nixpkgs;
|
inherit (inputs) nixpkgs;
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
{ 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";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
38
lib/inventory/example.nix
Normal file
38
lib/inventory/example.nix
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
{ self, ... }:
|
||||||
|
self.lib.buildClan {
|
||||||
|
# Name of the clan in the UI, should be unique
|
||||||
|
meta.name = "Inventory clan";
|
||||||
|
|
||||||
|
# Should usually point to the directory of flake.nix
|
||||||
|
directory = self;
|
||||||
|
|
||||||
|
inventory = {
|
||||||
|
services = {
|
||||||
|
borgbackup.instance_1 = {
|
||||||
|
roles.server.machines = [ "backup_server" ];
|
||||||
|
roles.client.tags = [ "backup" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# merged with
|
||||||
|
machines = {
|
||||||
|
"backup_server" = {
|
||||||
|
clan.tags = [ "all" ];
|
||||||
|
};
|
||||||
|
"client_1_machine" = {
|
||||||
|
clan.tags = [
|
||||||
|
"all"
|
||||||
|
"backup"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
"client_2_machine" = {
|
||||||
|
clan.tags = [
|
||||||
|
"all"
|
||||||
|
"backup"
|
||||||
|
];
|
||||||
|
# Name of the machine in the UI
|
||||||
|
clan.meta.name = "camina";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
{ ... }:
|
{ ... }:
|
||||||
{
|
{
|
||||||
# flake.inventory = import ./default.nix { inherit inputs self lib; };
|
|
||||||
perSystem =
|
perSystem =
|
||||||
{ pkgs, config, ... }:
|
{ pkgs, config, ... }:
|
||||||
{
|
{
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{ self, ... }:
|
{ self, inputs, ... }:
|
||||||
{
|
{
|
||||||
flake.templates = {
|
flake.templates = {
|
||||||
new-clan = {
|
new-clan = {
|
||||||
@ -15,4 +15,25 @@
|
|||||||
path = ./minimal;
|
path = ./minimal;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
flake.checks.x86_64-linux.template-minimal =
|
||||||
|
let
|
||||||
|
path = self.templates.minimal.path;
|
||||||
|
initialized = inputs.nixpkgs.legacyPackages.x86_64-linux.runCommand "minimal-clan-flake" { } ''
|
||||||
|
mkdir $out
|
||||||
|
cp -r ${path}/* $out
|
||||||
|
mkdir -p $out/machines/foo
|
||||||
|
echo '{ "nixpkgs": { "hostPlatform": "x86_64-linux" } }' > $out/machines/foo/settings.json
|
||||||
|
'';
|
||||||
|
evaled = (import "${initialized}/flake.nix").outputs {
|
||||||
|
self = evaled // {
|
||||||
|
outPath = initialized;
|
||||||
|
};
|
||||||
|
clan-core = self;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
type = "derivation";
|
||||||
|
name = "minimal-clan-flake-check";
|
||||||
|
inherit (evaled.nixosConfigurations.foo.config.system.build.vm) drvPath outPath;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user