From 824c737055adb402daef9980479707d2ff856f1c Mon Sep 17 00:00:00 2001 From: Johannes Kirschbauer Date: Wed, 9 Oct 2024 10:28:30 +0200 Subject: [PATCH] Docs: improve module author guide code examples, code structuring --- docs/site/clanmodules/index.md | 86 ++++++++++++++++++++++++++++++---- 1 file changed, 76 insertions(+), 10 deletions(-) diff --git a/docs/site/clanmodules/index.md b/docs/site/clanmodules/index.md index 7e6878130..16e8a6355 100644 --- a/docs/site/clanmodules/index.md +++ b/docs/site/clanmodules/index.md @@ -6,13 +6,17 @@ This site will guide you through authoring your first module. Explaining which c Under construction :fontawesome-solid-road-barrier: :fontawesome-solid-road-barrier: :fontawesome-solid-road-barrier: +!!! Note + Currently ClanModules should be contributed to the [clan-core repository](https://git.clan.lol/clan/clan-core) via a PR. + + Ad-hoc loading of custom modules is not recommended / supported yet. + ## Bootstrapping the `clanModule` A ClanModule is a specific subset of a [NixOS Module](https://nix.dev/tutorials/module-system/index.html), but it has some constraints and might be used via the [Inventory](../manual/inventory.md) interface. +In fact a `ClanModule` can be thought of as a layer of abstraction on-top of NixOS and/or other ClanModules. It may configure sane defaults and provide an ergonomic interface that is easy to use and can also be used via a UI that is under development currently. -Because ClanModules should be configurable via `json` all of its interface (`options`) must be serializable. - -Currently ClanModules should be contributed to the [clan-core repository](https://git.clan.lol/clan/clan-core). Ad-hoc loading of custom modules is not recommended / supported yet. +Because ClanModules should be configurable via `json`/`API` all of its interface (`options`) must be serializable. !!! Tip ClanModules interface can be checked by running the json schema converter as follows. @@ -35,10 +39,11 @@ clanModules/borgbackup ``` !!! Tip - This format is strictly required for `features = [ "inventory" ]`. - Some module authors might decide to opt-out of [inventory](../manual/inventory.md) usage. + `README.md` is always required. See section [Readme](#readme) for further details. -The next step is to register the module via the `clanModules` attribute. + The `roles` folder is strictly required for `features = [ "inventory" ]`. + +The clanModule must be registered via the `clanModules` attribute in `clan-core` ```nix title="clanModules/flake-module.nix" --8<-- "clanModules/flake-module.nix:0:6" @@ -48,7 +53,7 @@ The next step is to register the module via the `clanModules` attribute. ## Readme -The `README.md` is a required file. It MUST contain frontmatter in [`toml`](https://toml.io) format. +The `README.md` is a required file for all modules. It MUST contain frontmatter in [`toml`](https://toml.io) format. ```markdown --- @@ -62,9 +67,11 @@ See the [frontmatter reference](#frontmatter-reference) for all supported attrib ## Roles -Each `.nix` file in the `roles` directory is added as a role to the service. +If the module declares to implement `features = [ "inventory" ]` then it MUST contain a roles directory. -Other files can be placed alongside the `.nix` files +Each `.nix` file in the `roles` directory is added as a role to the inventory service. + +Other files can also be placed alongside the `.nix` files ```sh └── roles @@ -74,6 +81,37 @@ Other files can be placed alongside the `.nix` files Adds the roles: `client` and `server` +??? Tip "Good to know" + Sometimes a `ClanModule` should be usable via both clan's `inventory` concept but also natively as a NixOS module. + + > In the long term, we want most modules to implement support for the inventory, + > but we are also aware that there are certain low-level modules that always serve as a backend for other higher-level inventory modules. + > These modules may not want to implement inventory interfaces as they are always used directly by other modules. + + This can be achieved by placing an additional `default.nix` into the root of the ClanModules directory as shown: + + ```sh + # ModuleA + ├── README.md + ├── default.nix + └── roles + └── default.nix + ``` + + ```nix title="default.nix" + {...}:{ + imports = [ ./roles/default.nix ]; + } + ``` + + By utilizing this pattern the module (`moduleA`) can then be imported into any regular NixOS module via: + + ```nix + {...}:{ + imports = [ clanModules.moduleA ]; + } + ``` + ## Organizing the ClanModule Each `{role}.nix` is included into the machine if the machine is declared to have the role. @@ -86,6 +124,32 @@ roles.client.machines = ["MachineA"]; Then `roles/client.nix` will be added to the machine `MachineA`. +This behavior makes it possible to split the interface and common code paths when using multiple roles. +In the concrete example of `borgbackup` this allows a `server` to declare a different interface than the corresponding `client`. + +The client offers configuration option, to exclude certain local directories from being backed up: + +```nix title="roles/client.nix" +# Example client interface + options.clan.borgbackup.exclude = ... +``` + +The server doesn't offer any configuration option. Because everything is set-up automatically. + +```nix title="roles/server.nix" +# Example server interface + options.clan.borgbackup = {}; +``` + +Assuming that there is a common code path or a common interface between `server` and `client` this can be structured as: + +```nix title="roles/server.nix, roles/client.nix" +{...}: { + # ... + imports = [ ../common.nix ]; +} +``` + ## Frontmatter Reference `description` (**Required** `String`) @@ -125,4 +189,6 @@ Then `roles/client.nix` will be added to the machine `MachineA`. !!! warning "Important" Every ClanModule, that specifies `features = [ "inventory" ]` MUST have at least one role. - Many modules use `roles/default.nix` which registers the role `default` + Many modules use `roles/default.nix` which registers the role `default`. + + If you are a clan module author and your module has only one role where you cannot determine the name, then we would like you to follow the convention. \ No newline at end of file