Skip to content

Commit 0629c5a

Browse files
authored
Merge pull request #934 from opsmill/develop
Merge develop into infrahub-develop
2 parents ddb1b2c + 729e8ef commit 0629c5a

27 files changed

Lines changed: 569 additions & 338 deletions

.vale/styles/spelling-exceptions.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,3 +139,4 @@ yamllint
139139
YouTube
140140
vscode
141141
VSCode
142+
walkthrough

AGENTS.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22

33
Infrahub Python SDK - async/sync client for Infrahub infrastructure management.
44

5+
## Product context
6+
7+
The SDK is the foundational library for programmatically interacting with Infrahub. It abstracts away the underlying API so developers can work with infrastructure data using native Python objects.
8+
9+
**Primary audience:** Network automation engineers and software developers.
10+
11+
**Three main use cases:**
12+
13+
- **Automate inside Infrahub** — Write transforms, generators, and checks that run as part of Infrahub's pipeline.
14+
- **Integrate with external systems** — Query and sync data between Infrahub and existing tools. `infrahubctl` and the Infrahub Ansible collection both use this SDK internally.
15+
- **Build custom applications** — Use Infrahub as a data backend for Python projects entirely outside of Infrahub's own pipeline.
16+
17+
**Why the SDK over direct API calls:** eliminates the need to learn Infrahub's API structure, provides Python-native interfaces with built-in auth, adds advanced capabilities (batching, caching, tracking), and reduces boilerplate.
18+
519
## Commands
620

721
```bash
@@ -73,6 +87,13 @@ Key rules:
7387
- Modify generated code (protocols.py)
7488
- Bypass type checking without justification
7589

90+
## Knowledge base
91+
92+
Deep-dive docs on architecture and workflows live in `dev/knowledge/`. Read these before making changes to the areas they cover.
93+
94+
- [dev/knowledge/cli-architecture.md](dev/knowledge/cli-architecture.md) - CLI command hierarchy and design rules
95+
- [dev/knowledge/doc-generation.md](dev/knowledge/doc-generation.md) - How docs are auto-generated from code
96+
7697
## Subdirectory guides
7798

7899
- [docs/AGENTS.md](docs/AGENTS.md) - Documentation (Docusaurus)

dev/knowledge/cli-architecture.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# CLI Architecture
2+
3+
The `infrahubctl` CLI is built with [Typer](https://typer.tiangolo.com/) via a custom `AsyncTyper` subclass that supports async command functions.
4+
5+
## Entry point
6+
7+
The main Typer app lives in `infrahub_sdk/ctl/cli_commands.py`. It is re-exported through `infrahub_sdk/ctl/cli.py` which adds the `infrahubctl` entry point name.
8+
9+
## Command hierarchy
10+
11+
Commands are organized in two tiers:
12+
13+
- **Root commands** are registered directly on the main app with `app.command()`. These are standalone operations that don't belong to a logical group (e.g. `dump`, `load`, `check`, `render`, `run`, `transform`, `protocols`, `version`, `info`).
14+
- **Subcommand groups** are separate `AsyncTyper()` instances registered with `app.add_typer(sub_app, name="group")`. Each group lives in its own module under `infrahub_sdk/ctl/`. Current groups: `branch`, `schema`, `validate`, `repository`, `menu`, `object`, `graphql`, `task`.
15+
16+
## Adding a new command
17+
18+
For a **root command**, define the function in the appropriate module and register it in `cli_commands.py`:
19+
20+
```python
21+
app.command(name="mycommand")(my_function)
22+
```
23+
24+
For a **subcommand**, add it to the relevant group's package or module. For example, object subcommands live in `infrahub_sdk/ctl/object/` and are registered on the object app in `__init__.py`.
25+
26+
## Group packages
27+
28+
When a subcommand group has multiple commands, it lives as a package (directory with `__init__.py`) rather than a single module file. The `object` group is the reference example:
29+
30+
```text
31+
infrahub_sdk/ctl/object/
32+
├── __init__.py # App, callback, load/validate commands, registers CRUD
33+
├── create.py # create subcommand
34+
├── delete.py # delete subcommand
35+
├── get.py # get subcommand
36+
├── update.py # update subcommand
37+
└── utils.py # Shared utilities (resolve_node, etc.)
38+
```
39+
40+
Each command file contains a single command function. Shared logic goes in `utils.py`. The `__init__.py` wires everything together by importing and registering commands on the group's `AsyncTyper` app. Other groups that grow beyond a single file should follow this same pattern.
41+
42+
## Decorators
43+
44+
- `@catch_exception(console=console)` wraps commands for consistent error handling via Rich.
45+
- Async commands work natively thanks to `AsyncTyper`.
46+
47+
## Design rules
48+
49+
**Always check if a new command belongs in an existing group before adding it at the root.** A command that operates on a specific resource type (objects, branches, schemas, etc.) should go under the matching subgroup, not at the top level. Root-level commands are reserved for cross-cutting or standalone operations (e.g. `run`, `version`, `info`).
50+
51+
When in doubt, look at what the command acts on and find the group that matches. For example, anything that creates, reads, updates, or deletes Infrahub objects belongs under `object`, not at the root.

dev/knowledge/doc-generation.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Documentation Generation
2+
3+
CLI and SDK documentation is auto-generated from code. Always regenerate after changing commands, config, or public docstrings.
4+
5+
## How to run
6+
7+
```bash
8+
uv run invoke docs-generate # Generate all docs (CLI + SDK)
9+
uv run invoke docs-validate # Verify generated docs match committed versions
10+
```
11+
12+
## CLI documentation
13+
14+
Defined in `tasks.py` (`_generate_infrahubctl_documentation`). The process:
15+
16+
1. Deletes all existing `infrahubctl-*.mdx` files in `docs/docs/infrahubctl/`.
17+
2. Iterates `app.registered_commands` and creates a `TyperSingleCommand` for each.
18+
3. Iterates `app.registered_groups` and creates a `TyperGroupCommand` for each.
19+
4. Each command object generates an mdx file via `typer ... utils docs`.
20+
21+
### How it maps to files
22+
23+
- A **root command** named `foo` produces `infrahubctl-foo.mdx` using:
24+
`uv run typer --func foo infrahub_sdk.ctl.cli_commands utils docs --name "infrahubctl foo"`
25+
- A **subcommand group** named `bar` produces `infrahubctl-bar.mdx` using:
26+
`uv run typer infrahub_sdk.ctl.bar utils docs --name "infrahubctl bar"`
27+
28+
The group variant documents all subcommands within that group automatically.
29+
30+
### Key implication
31+
32+
Moving a command from root to a group (or vice versa) changes which mdx files get generated. The old files are cleaned up automatically by the glob delete, but the new ones only appear after running `docs-generate`. Always regenerate and commit the result.
33+
34+
## SDK documentation
35+
36+
Other doc generators cover SDK config, compatibility matrix, templates, and API reference. These are independent of CLI structure and are also triggered by `docs-generate`.
37+
38+
## Validation in CI
39+
40+
`docs-validate` diffs the generated output against the committed files. If they don't match, CI fails. This ensures docs stay in sync with code.

docs/docs/infrahubctl/infrahubctl-create.mdx

Lines changed: 0 additions & 31 deletions
This file was deleted.

docs/docs/infrahubctl/infrahubctl-delete.mdx

Lines changed: 0 additions & 30 deletions
This file was deleted.

docs/docs/infrahubctl/infrahubctl-get.mdx

Lines changed: 0 additions & 41 deletions
This file was deleted.

docs/docs/infrahubctl/infrahubctl-object.mdx

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,112 @@ $ infrahubctl object [OPTIONS] COMMAND [ARGS]...
1616

1717
**Commands**:
1818

19+
* `create`: Create a new object in Infrahub.
20+
* `delete`: Delete an Infrahub object.
21+
* `get`: Query and display Infrahub objects.
1922
* `load`: Load one or multiple objects files into...
23+
* `update`: Update an existing object in Infrahub.
2024
* `validate`: Validate one or multiple objects files.
2125

26+
## `infrahubctl object create`
27+
28+
Create a new object in Infrahub.
29+
30+
Provide field values with repeatable --set flags or supply a
31+
JSON/YAML object file via --file. The two modes are mutually exclusive.
32+
33+
Examples:
34+
infrahubctl object create InfraDevice --set name=spine01 --set status=active
35+
infrahubctl object create InfraDevice --set name=spine01 --set location=DC1
36+
infrahubctl object create InfraDevice --file devices.yml
37+
38+
**Usage**:
39+
40+
```console
41+
$ infrahubctl object create [OPTIONS] KIND
42+
```
43+
44+
**Arguments**:
45+
46+
* `KIND`: Infrahub schema kind to create [required]
47+
48+
**Options**:
49+
50+
* `--set TEXT`: Field value in key=value format
51+
* `-f, --file PATH`: JSON or YAML file with object data
52+
* `-b, --branch TEXT`: Target branch
53+
* `--config-file TEXT`: [env var: INFRAHUBCTL_CONFIG; default: infrahubctl.toml]
54+
* `--help`: Show this message and exit.
55+
56+
## `infrahubctl object delete`
57+
58+
Delete an Infrahub object.
59+
60+
Fetches the object by KIND and IDENTIFIER, then deletes it.
61+
Unless --yes is provided, a confirmation prompt is shown first.
62+
63+
Examples:
64+
infrahubctl object delete InfraDevice spine01
65+
infrahubctl object delete InfraDevice spine01 --yes
66+
67+
**Usage**:
68+
69+
```console
70+
$ infrahubctl object delete [OPTIONS] KIND IDENTIFIER
71+
```
72+
73+
**Arguments**:
74+
75+
* `KIND`: Infrahub schema kind [required]
76+
* `IDENTIFIER`: UUID, name, or HFID (use / for multi-part, for example: Cisco/NX-OS) [required]
77+
78+
**Options**:
79+
80+
* `-y, --yes`: Skip confirmation prompt
81+
* `-b, --branch TEXT`: Target branch
82+
* `--config-file TEXT`: [env var: INFRAHUBCTL_CONFIG; default: infrahubctl.toml]
83+
* `--help`: Show this message and exit.
84+
85+
## `infrahubctl object get`
86+
87+
Query and display Infrahub objects.
88+
89+
When IDENTIFIER is omitted the command lists all objects of the given
90+
KIND. When IDENTIFIER is provided it displays a single object in
91+
detail view. Empty columns are hidden by default (use --all-columns).
92+
93+
Examples:
94+
infrahubctl object get InfraDevice
95+
infrahubctl object get InfraDevice spine01
96+
infrahubctl object get InfraDevice --filter name__value=spine01
97+
infrahubctl object get InfraDevice --output json
98+
infrahubctl object get InfraDevice --output yaml > backup.yml
99+
100+
Exit codes: 0 = results found, 1 = error (including not found in detail
101+
mode), 80 = list query succeeded but returned zero objects.
102+
103+
**Usage**:
104+
105+
```console
106+
$ infrahubctl object get [OPTIONS] KIND [IDENTIFIER]
107+
```
108+
109+
**Arguments**:
110+
111+
* `KIND`: Infrahub schema kind to query [required]
112+
* `[IDENTIFIER]`: UUID, name, or HFID (use / for multi-part, for example: Cisco/NX-OS)
113+
114+
**Options**:
115+
116+
* `--filter TEXT`: Filter in attr__value=x format
117+
* `-o, --output [table|json|csv|yaml]`: Output format
118+
* `-b, --branch TEXT`: Target branch
119+
* `--limit INTEGER`: Maximum results
120+
* `--offset INTEGER`: Skip first N results
121+
* `--all-columns`: Show all columns including empty ones
122+
* `--config-file TEXT`: [env var: INFRAHUBCTL_CONFIG; default: infrahubctl.toml]
123+
* `--help`: Show this message and exit.
124+
22125
## `infrahubctl object load`
23126

24127
Load one or multiple objects files into Infrahub.
@@ -40,6 +143,37 @@ $ infrahubctl object load [OPTIONS] PATHS...
40143
* `--config-file TEXT`: [env var: INFRAHUBCTL_CONFIG; default: infrahubctl.toml]
41144
* `--help`: Show this message and exit.
42145

146+
## `infrahubctl object update`
147+
148+
Update an existing object in Infrahub.
149+
150+
Fetches the object by KIND and IDENTIFIER, applies the requested
151+
changes, and saves back to the server. Use --set or --file.
152+
153+
Examples:
154+
infrahubctl object update InfraDevice spine01 --set status=active
155+
infrahubctl object update InfraDevice spine01 --set location=DC1
156+
infrahubctl object update InfraDevice spine01 --file updates.yml
157+
158+
**Usage**:
159+
160+
```console
161+
$ infrahubctl object update [OPTIONS] KIND IDENTIFIER
162+
```
163+
164+
**Arguments**:
165+
166+
* `KIND`: Infrahub schema kind [required]
167+
* `IDENTIFIER`: UUID, name, or HFID (use / for multi-part, for example: Cisco/NX-OS) [required]
168+
169+
**Options**:
170+
171+
* `--set TEXT`: Field value in key=value format
172+
* `-f, --file PATH`: JSON or YAML file with update data
173+
* `-b, --branch TEXT`: Target branch
174+
* `--config-file TEXT`: [env var: INFRAHUBCTL_CONFIG; default: infrahubctl.toml]
175+
* `--help`: Show this message and exit.
176+
43177
## `infrahubctl object validate`
44178

45179
Validate one or multiple objects files.

0 commit comments

Comments
 (0)