Merge pull request 'docs(service-modules): add description and docs for options' (#3848) from doc-1 into main

Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3848
This commit is contained in:
hsjobeki
2025-06-04 12:44:32 +00:00
10 changed files with 397 additions and 119 deletions

View File

@@ -80,7 +80,7 @@ nav:
- macOS: guides/macos.md
- Reference:
- Overview: reference/index.md
- Clan Services:
- Services:
- Overview: reference/clanServices/index.md
- reference/clanServices/admin.md
- reference/clanServices/auto-upgrade.md
@@ -93,7 +93,8 @@ nav:
- reference/clanServices/hello-world.md
- reference/clanServices/wifi.md
- reference/clanServices/zerotier.md
- Clan Modules:
- Interface for making Services: reference/clanServices/clan-service-author-interface.md
- Modules:
- Overview: reference/clanModules/index.md
- reference/clanModules/frontmatter/index.md
# TODO: display the docs of the clan.service modules

View File

@@ -90,6 +90,7 @@
export CLAN_MODULES_VIA_ROLES=${clanModulesViaRoles}
export CLAN_MODULES_VIA_SERVICE=${clanModulesViaService}
export CLAN_MODULES_VIA_NIX=${clanModulesViaNix}
export CLAN_SERVICE_INTERFACE=${self'.legacyPackages.clan-service-module-interface}/share/doc/nixos/options.json
# Frontmatter format for clanModules
export CLAN_MODULES_FRONTMATTER_DOCS=${clanModulesFrontmatter}/share/doc/nixos/options.json

View File

@@ -49,6 +49,10 @@ CLAN_MODULES_VIA_NIX = os.environ.get("CLAN_MODULES_VIA_NIX")
# Some modules can be imported via inventory
CLAN_MODULES_VIA_ROLES = os.environ.get("CLAN_MODULES_VIA_ROLES")
# Options how to author clan.modules
# perInstance, perMachine, ...
CLAN_SERVICE_INTERFACE = os.environ.get("CLAN_SERVICE_INTERFACE")
CLAN_MODULES_VIA_SERVICE = os.environ.get("CLAN_MODULES_VIA_SERVICE")
OUT = os.environ.get("out")
@@ -309,7 +313,7 @@ def produce_clan_core_docs() -> None:
core_outputs[indexfile] += """!!! info "Submodules"\n"""
for submodule_name, split_options in split.items():
root = options_to_tree(split_options, debug=True)
root = options_to_tree(split_options)
module = root.suboptions[0]
module_type = module.info.get("type")
if module_type is not None and "submodule" not in module_type:
@@ -798,6 +802,44 @@ def split_options_by_root(options: dict[str, Any]) -> dict[str, dict[str, Any]]:
return res
def produce_clan_service_author_docs() -> None:
if not CLAN_SERVICE_INTERFACE:
msg = f"Environment variables are not set correctly: CLAN_SERVICE_INTERFACE={CLAN_SERVICE_INTERFACE}. Expected a path to the optionsJSON"
raise ClanError(msg)
if not OUT:
msg = f"Environment variables are not set correctly: $out={OUT}"
raise ClanError(msg)
output = """
This document describes the structure and configurable attributes of a `clan.service` module.
Typically needed by module authors to define roles, behavior and metadata for distributed services.
!!! Note
This is not a user-facing documentation, but rather meant as a reference for *module authors*
See: [clanService Authoring Guide](../../guides/authoring/clanServices/index.md)
"""
# Inventory options are already included under the buildClan attribute
# We just omitted them in the buildClan docs, because we want a separate output for the inventory model
with Path(CLAN_SERVICE_INTERFACE).open() as f:
options: dict[str, dict[str, Any]] = json.load(f)
options_tree = options_to_tree(options, debug=True)
# Find the inventory options
# Render the inventory options
# This for loop excludes the root node
# for option in options_tree.suboptions:
output += options_docs_from_tree(options_tree, init_level=2)
outfile = Path(OUT) / "clanServices/clan-service-author-interface.md"
outfile.parent.mkdir(parents=True, exist_ok=True)
with Path.open(outfile, "w") as of:
of.write(output)
@dataclass
class Option:
name: str
@@ -959,6 +1001,8 @@ if __name__ == "__main__": #
produce_build_clan_docs()
produce_inventory_docs()
produce_clan_service_author_docs()
produce_clan_modules_docs()
produce_clan_service_docs()

View File

@@ -8,7 +8,9 @@
## Service Module Specification
This section explains how to author a clan service module.
We discussed the initial architecture in [01-clan-service-modules](../../../decisions/01-ClanModules.md) and decided to rework the format as follows:
We discussed the initial architecture in [01-clan-service-modules](../../../decisions/01-ClanModules.md) and decided to rework the format.
For the full specification and current state see: **[Service Author Reference](../../../reference/clanServices/clan-service-author-interface.md)**
### A Minimal module
@@ -49,6 +51,8 @@ The imported module file must fulfill at least the following requirements:
}
```
For more attributes see: **[Service Author Reference](../../../reference/clanServices/clan-service-author-interface.md)**
### Adding functionality to the module
While the very minimal module is valid in itself it has no way of adding any machines to it, because it doesn't specify any roles.
@@ -254,3 +258,11 @@ outputs = inputs: flake-parts.lib.mkFlake { inherit inputs; } ({self, lib, ...}:
```
The benefit of this approach is that downstream users can override the value of `myClan` by using `mkForce` or other priority modifiers.
---
## Further
- [Reference Documentation for Service Authors](../../../reference/clanServices/clan-service-author-interface.md)
- [Migration Guide from ClanModules to ClanServices](../../migrations/migrate-inventory-services.md)
- [Decision that lead to ClanServices](../../../decisions/01-ClanModules.md)