Merge pull request 'Docs: improve module author guide code examples, code structuring' (#2233) from hsjobeki/clan-core:hsjobeki-main into main

This commit is contained in:
clan-bot
2024-10-09 08:43:14 +00:00

View File

@@ -6,13 +6,17 @@ This site will guide you through authoring your first module. Explaining which c
Under construction Under construction
:fontawesome-solid-road-barrier: :fontawesome-solid-road-barrier: :fontawesome-solid-road-barrier: :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` ## 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. 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. Because ClanModules should be configurable via `json`/`API` 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.
!!! Tip !!! Tip
ClanModules interface can be checked by running the json schema converter as follows. ClanModules interface can be checked by running the json schema converter as follows.
@@ -35,10 +39,11 @@ clanModules/borgbackup
``` ```
!!! Tip !!! Tip
This format is strictly required for `features = [ "inventory" ]`. `README.md` is always required. See section [Readme](#readme) for further details.
Some module authors might decide to opt-out of [inventory](../manual/inventory.md) usage.
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" ```nix title="clanModules/flake-module.nix"
--8<-- "clanModules/flake-module.nix:0:6" --8<-- "clanModules/flake-module.nix:0:6"
@@ -48,7 +53,7 @@ The next step is to register the module via the `clanModules` attribute.
## Readme ## 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 ```markdown
--- ---
@@ -62,9 +67,11 @@ See the [frontmatter reference](#frontmatter-reference) for all supported attrib
## Roles ## 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 ```sh
└── roles └── roles
@@ -74,6 +81,37 @@ Other files can be placed alongside the `.nix` files
Adds the roles: `client` and `server` 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 ## Organizing the ClanModule
Each `{role}.nix` is included into the machine if the machine is declared to have the role. 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`. 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 ## Frontmatter Reference
`description` (**Required** `String`) `description` (**Required** `String`)
@@ -125,4 +189,6 @@ Then `roles/client.nix` will be added to the machine `MachineA`.
!!! warning "Important" !!! warning "Important"
Every ClanModule, that specifies `features = [ "inventory" ]` MUST have at least one role. 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.