storage¶
The storage package provides a repository pattern for persisting and retrieving data (currently backed by JSON files).
- class otto.storage.protocol.LabRepository(*args, **kwargs)¶
Bases:
ProtocolProtocol defining DB-agnostic interface for loading labs.
-
load_lab(name, search_paths, defaults=
None)¶ Load a lab by name from the repository.
Parameters¶
- namestr
Name of the lab to load
- search_pathslist[Path]
Directories to search for the lab data
- defaultsdict[str, dict[str, Any]] | None
Optional repo-level option defaults forwarded to the host factory. Backends should pass this through unchanged; the factory handles per-key merging beneath each host’s own
*_options.Nonereproduces today’s behavior.
Returns¶
- Lab
Fully constructed Lab object with all hosts
Raises¶
- FileNotFoundError
If lab cannot be found in any search path
- ValueError
If lab data is malformed
- ImportError
If module loading fails (Python repository only)
- supports_location(path)¶
Check if this repository can handle data at the given location.
- Return type:¶
bool
Parameters¶
- pathPath
Location to check
Returns¶
- bool
True if this repository can load from this location
- list_labs(search_paths)¶
List all valid lab names available in the search paths.
- Return type:¶
list[str]
Parameters¶
- search_pathslist[Path]
Directories to search for labs
Returns¶
- list[str]
List of lab names found in the search paths
-
load_lab(name, search_paths, defaults=
- class otto.storage.json_repository.JsonFileLabRepository¶
Bases:
objectRepository implementation for loading labs from a hosts.json file.
Each search-path directory may contain a hosts.json file holding all known hosts. Each host carries a ‘labs’ field listing the lab names it belongs to, mirroring a database row-with-membership design.
- supports_location(path)¶
Check if path is a directory that could contain a hosts.json file.
- Return type:¶
bool
-
load_lab(name, search_paths, defaults=
None)¶ Load a lab by filtering hosts from hosts.json files.
Searches all search paths for hosts.json files, merges all hosts, then returns only those whose ‘labs’ field contains the requested name.
Parameters¶
- namestr
Name of the lab to load
- search_pathslist[Path]
Directories to search for hosts.json files
- defaultsdict[str, dict[str, Any]] | None
Optional repo-level option defaults forwarded to the host factory; merged per-key beneath each host’s own
*_options.
Returns¶
- Lab
Constructed Lab object with all matching hosts added
Raises¶
- FileNotFoundError
If no hosts.json found in any search path, or no hosts belong to the requested lab
- ValueError
If a hosts.json file doesn’t contain a JSON array or host data is invalid
- json.JSONDecodeError
If a hosts.json file contains malformed JSON
- list_labs(search_paths)¶
List all lab names referenced by hosts across all hosts.json files.
- Return type:¶
list[str]
Parameters¶
- search_pathslist[Path]
Directories to search for hosts.json files
Returns¶
- list[str]
Sorted list of unique lab names found
-
otto.storage.factory.create_host_from_dict(host_data, defaults=
None)¶ Create the appropriate
RemoteHostsubclass from a host dict.os_typenames a registeredOsProfile, which selects the base host class and carries a bundle of default field values. The profile’s base resolves to a(host_class, host_spec)pair; the merged dict (host > profile > repo defaults, per-key for*_options) is validated once by the spec (extra='forbid', typed, with field-name suggestions on typos) and the spec builds the runtime host.Field precedence, highest to lowest: the host’s own value; the profile’s
defaults; repo-level*_optionsdefaults (options only); the runtime class’s stock default.- Return type:¶
Raises¶
- ValueError
If
os_typenames no registered profile.- pydantic.ValidationError
If a field is missing, mistyped, misplaced, or unknown (a subclass of
ValueError).
- otto.storage.factory.validate_host_dict(host_data)¶
Validate a host dict without constructing the host.
os_typemust name a registered profile; the profile’s base spec validates the merged dict (extra='forbid', required fields, typed coercion, family-specific field validators forcommand_frame/filesystem/transfer/docker_capable).- Return type:¶
None
Raises¶
- ValueError
If
os_typenames no registered profile.- pydantic.ValidationError
On any structural problem (subclass of
ValueError).