Shared inventory model for the linux-fleet tools: linux-audit, linux-harden and linux-motd.
One inventory file, three tools. Write your fleet down once.
Each tool started with its own copy of the inventory loader. Two copies was tolerable. Three is where the cost curve turns: every schema change becomes three edits, three test runs, and the copies have already started to diverge.
This package is the extraction. It is deliberately small, because three tools depend on it staying stable.
version,defaults,groups,hosts,vars- Resolution order: host > group > defaults > builtin
- Connection settings: user, port, auth, sudo behaviour, timeouts
- Provenance: every resolved value records which layer supplied it
Tool-specific settings live in namespaced blocks (motd:, audit:, harden:) and are
passed through untouched. Adding a key to one tool never requires a change to this package,
and never triggers a three-repo release.
pip install linux-fleet-commonfrom linux_fleet_common import load_inventory
inventory = load_inventory("inventory.yaml")
for host in inventory.select(groups=["prod-web"]):
print(host.name, host.user, host.port)
print(host.tool("motd")) # tool block, untouched
print(host.var("owner_team")) # free-form var
print(host.source_of("user")) # "group:prod-web"version: 1
defaults:
user: svc-fleet
port: 22
auth: password
sudo: true
sudo_password: same
vars:
support_contact: "ops@example.com"
groups:
prod-web:
vars:
environment: PRODUCTION
owner_team: Platform
motd:
hook: both
fields:
extra_mounts: ["/var", "/srv/www"]
hosts:
- web01.example.com
- host: web02.example.com
port: 2222- Unknown keys are errors, not no-ops. A typo like
group:instead ofgroups:fails the load rather than silently doing nothing. - Lists replace, they do not concatenate. A host setting
extra_mounts: ["/data"]overriding a group's["/var", "/srv"]ends up with exactly["/data"]. Concatenation would make it impossible to narrow a list at host level. - Selecting an unknown host or group is an error, never a silent empty result. A typo in
-Hshould not look like a successful run against nothing. -Hand-gtogether are a union, not an intersection.- A host in two groups appears once, with both group names recorded. The later group
wins on conflicting keys, and
source_of()tells you which one. boolis not an integer here.port: trueis rejected rather than resolving to port 1.
version: 1 is the only supported schema. The loader refuses anything else rather than
guessing. Consumers should pin a compatible release:
linux-fleet-common>=1.0,<2.0
pip install -e ".[dev]"
pytest
ruff check .CI additionally runs the linux-audit and linux-harden suites against this build. The extraction is only correct if it is behaviour-neutral, so any diff in resolved inventory output in a consumer is a bug here.
MIT. See LICENSE.