docs: expose clan service authoring interface

This commit is contained in:
Johannes Kirschbauer
2025-06-04 12:38:51 +02:00
parent 0180013e68
commit 6e7b2f94e5
4 changed files with 62 additions and 4 deletions

View File

@@ -80,7 +80,7 @@ nav:
- macOS: guides/macos.md - macOS: guides/macos.md
- Reference: - Reference:
- Overview: reference/index.md - Overview: reference/index.md
- Clan Services: - Services:
- Overview: reference/clanServices/index.md - Overview: reference/clanServices/index.md
- reference/clanServices/admin.md - reference/clanServices/admin.md
- reference/clanServices/auto-upgrade.md - reference/clanServices/auto-upgrade.md
@@ -92,7 +92,8 @@ nav:
- reference/clanServices/hello-world.md - reference/clanServices/hello-world.md
- reference/clanServices/wifi.md - reference/clanServices/wifi.md
- reference/clanServices/zerotier.md - reference/clanServices/zerotier.md
- Clan Modules: - Interface for making Services: reference/clanServices/clan-service-author-interface.md
- Modules:
- Overview: reference/clanModules/index.md - Overview: reference/clanModules/index.md
- reference/clanModules/frontmatter/index.md - reference/clanModules/frontmatter/index.md
# TODO: display the docs of the clan.service modules # 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_ROLES=${clanModulesViaRoles}
export CLAN_MODULES_VIA_SERVICE=${clanModulesViaService} export CLAN_MODULES_VIA_SERVICE=${clanModulesViaService}
export CLAN_MODULES_VIA_NIX=${clanModulesViaNix} 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 # Frontmatter format for clanModules
export CLAN_MODULES_FRONTMATTER_DOCS=${clanModulesFrontmatter}/share/doc/nixos/options.json 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 # Some modules can be imported via inventory
CLAN_MODULES_VIA_ROLES = os.environ.get("CLAN_MODULES_VIA_ROLES") 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") CLAN_MODULES_VIA_SERVICE = os.environ.get("CLAN_MODULES_VIA_SERVICE")
OUT = os.environ.get("out") OUT = os.environ.get("out")
@@ -309,7 +313,7 @@ def produce_clan_core_docs() -> None:
core_outputs[indexfile] += """!!! info "Submodules"\n""" core_outputs[indexfile] += """!!! info "Submodules"\n"""
for submodule_name, split_options in split.items(): 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 = root.suboptions[0]
module_type = module.info.get("type") module_type = module.info.get("type")
if module_type is not None and "submodule" not in module_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 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 @dataclass
class Option: class Option:
name: str name: str
@@ -959,6 +1001,8 @@ if __name__ == "__main__": #
produce_build_clan_docs() produce_build_clan_docs()
produce_inventory_docs() produce_inventory_docs()
produce_clan_service_author_docs()
produce_clan_modules_docs() produce_clan_modules_docs()
produce_clan_service_docs() produce_clan_service_docs()

View File

@@ -8,7 +8,9 @@
## Service Module Specification ## Service Module Specification
This section explains how to author a clan service module. 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 ### 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 ### 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. 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. 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)