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:
@@ -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.
|
||||||
Reference in New Issue
Block a user