-
Notifications
You must be signed in to change notification settings - Fork 7
feat: add CRUD and schema discovery commands to infrahubctl #900
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: stable
Are you sure you want to change the base?
Changes from all commits
85502b4
8fba90d
94e3780
e71acb1
52c2b05
a941e57
b8d30b4
4f465f9
0c2ecc5
36332e3
7b7fb9f
c9119ea
ee6b73f
233ac0b
aca8c89
9f2813e
0c730be
db23a7d
4633713
0a3a408
4caff14
1b4b2bd
ff5c177
419b13b
f1b73c0
93634c6
fa3688f
52f77ce
432ba94
2a8fb43
03714b7
bc4bfb6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -133,6 +133,7 @@ validators | |
| Version Control | ||
| Vitest | ||
| VLANs | ||
| yaml | ||
| Yaml | ||
| yamllint | ||
| YouTube | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| # `infrahubctl create` | ||
|
|
||
| Create a new object in Infrahub. | ||
|
|
||
| Provide field values with repeatable --set flags or supply a | ||
| JSON/YAML object file via --file. The two modes are mutually exclusive. | ||
|
|
||
| Examples: | ||
| infrahubctl create InfraDevice --set name=spine01 --set status=active | ||
| infrahubctl create InfraDevice --set name=spine01 --set location=DC1 | ||
| infrahubctl create InfraDevice --file devices.yml | ||
|
|
||
| **Usage**: | ||
|
|
||
| ```console | ||
| $ infrahubctl create [OPTIONS] KIND | ||
| ``` | ||
|
|
||
| **Arguments**: | ||
|
|
||
| * `KIND`: Infrahub schema kind to create [required] | ||
|
|
||
| **Options**: | ||
|
|
||
| * `--set TEXT`: Field value in key=value format | ||
| * `-f, --file PATH`: JSON or YAML file with object data | ||
| * `-b, --branch TEXT`: Target branch | ||
| * `--config-file TEXT`: [env var: INFRAHUBCTL_CONFIG; default: infrahubctl.toml] | ||
| * `--install-completion`: Install completion for the current shell. | ||
| * `--show-completion`: Show completion for the current shell, to copy it or customize the installation. | ||
| * `--help`: Show this message and exit. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| # `infrahubctl delete` | ||
|
|
||
| Delete an Infrahub object. | ||
petercrocker marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| Fetches the object by KIND and IDENTIFIER, then deletes it. | ||
| Unless --yes is provided, a confirmation prompt is shown first. | ||
|
|
||
petercrocker marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Examples: | ||
| infrahubctl delete InfraDevice spine01 | ||
| infrahubctl delete InfraDevice spine01 --yes | ||
|
|
||
| **Usage**: | ||
|
|
||
| ```console | ||
| $ infrahubctl delete [OPTIONS] KIND IDENTIFIER | ||
| ``` | ||
|
|
||
| **Arguments**: | ||
|
|
||
| * `KIND`: Infrahub schema kind [required] | ||
| * `IDENTIFIER`: UUID, name, or HFID (use / for multi-part, e.g. Cisco/NX-OS) [required] | ||
|
|
||
| **Options**: | ||
|
|
||
| * `-y, --yes`: Skip confirmation prompt | ||
| * `-b, --branch TEXT`: Target branch | ||
| * `--config-file TEXT`: [env var: INFRAHUBCTL_CONFIG; default: infrahubctl.toml] | ||
| * `--install-completion`: Install completion for the current shell. | ||
| * `--show-completion`: Show completion for the current shell, to copy it or customize the installation. | ||
| * `--help`: Show this message and exit. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| # `infrahubctl get` | ||
|
|
||
| Query and display Infrahub objects. | ||
|
|
||
| When IDENTIFIER is omitted the command lists all objects of the given | ||
| KIND. When IDENTIFIER is provided it displays a single object in | ||
| detail view. Empty columns are hidden by default (use --all-columns). | ||
|
|
||
| Examples: | ||
petercrocker marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| infrahubctl get InfraDevice | ||
| infrahubctl get InfraDevice spine01 | ||
| infrahubctl get InfraDevice --filter name__value=spine01 | ||
| infrahubctl get InfraDevice --output json | ||
| infrahubctl get InfraDevice --output yaml > backup.yml | ||
|
|
||
| Exit codes: 0 = results found, 1 = error (including not found in detail | ||
| mode), 80 = list query succeeded but returned zero objects. | ||
|
|
||
| **Usage**: | ||
|
|
||
| ```console | ||
| $ infrahubctl get [OPTIONS] KIND [IDENTIFIER] | ||
| ``` | ||
|
|
||
| **Arguments**: | ||
|
|
||
| * `KIND`: Infrahub schema kind to query [required] | ||
| * `[IDENTIFIER]`: UUID, name, or HFID (use / for multi-part, e.g. Cisco/NX-OS) | ||
|
|
||
| **Options**: | ||
|
|
||
| * `--filter TEXT`: Filter in attr__value=x format | ||
| * `-o, --output [table|json|csv|yaml]`: Output format | ||
| * `-b, --branch TEXT`: Target branch | ||
| * `--limit INTEGER`: Maximum results | ||
| * `--offset INTEGER`: Skip first N results | ||
| * `--all-columns`: Show all columns including empty ones | ||
| * `--config-file TEXT`: [env var: INFRAHUBCTL_CONFIG; default: infrahubctl.toml] | ||
| * `--install-completion`: Install completion for the current shell. | ||
| * `--show-completion`: Show completion for the current shell, to copy it or customize the installation. | ||
| * `--help`: Show this message and exit. | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,33 @@ | ||||||||||||||||||||||||||||||||||||||||||||
| # `infrahubctl update` | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| Update an existing object in Infrahub. | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| Fetches the object by KIND and IDENTIFIER, applies the requested | ||||||||||||||||||||||||||||||||||||||||||||
| changes, and saves back to the server. Use --set or --file. | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| Examples: | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1
to
+9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add required frontmatter and remove the stray control character. This MDX page is missing a 🛠️ Proposed fix+---
+title: infrahubctl update
+---
+
# `infrahubctl update`
@@
-�
+
Examples:As per coding guidelines: 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||
| infrahubctl update InfraDevice spine01 --set status=active | ||||||||||||||||||||||||||||||||||||||||||||
| infrahubctl update InfraDevice spine01 --set location=DC1 | ||||||||||||||||||||||||||||||||||||||||||||
| infrahubctl update InfraDevice spine01 --file updates.yml | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| **Usage**: | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| ```console | ||||||||||||||||||||||||||||||||||||||||||||
| $ infrahubctl update [OPTIONS] KIND IDENTIFIER | ||||||||||||||||||||||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| **Arguments**: | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| * `KIND`: Infrahub schema kind [required] | ||||||||||||||||||||||||||||||||||||||||||||
| * `IDENTIFIER`: UUID, name, or HFID (use / for multi-part, e.g. Cisco/NX-OS) [required] | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| **Options**: | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| * `--set TEXT`: Field value in key=value format | ||||||||||||||||||||||||||||||||||||||||||||
| * `-f, --file PATH`: JSON or YAML file with update data | ||||||||||||||||||||||||||||||||||||||||||||
| * `-b, --branch TEXT`: Target branch | ||||||||||||||||||||||||||||||||||||||||||||
| * `--config-file TEXT`: [env var: INFRAHUBCTL_CONFIG; default: infrahubctl.toml] | ||||||||||||||||||||||||||||||||||||||||||||
| * `--install-completion`: Install completion for the current shell. | ||||||||||||||||||||||||||||||||||||||||||||
| * `--show-completion`: Show completion for the current shell, to copy it or customize the installation. | ||||||||||||||||||||||||||||||||||||||||||||
| * `--help`: Show this message and exit. | ||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| """Command modules for the ``infrahub`` end-user CLI.""" | ||
|
|
||
| from __future__ import annotations |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| """Command implementation for ``infrahub create``. | ||
|
|
||
| Creates a new object in Infrahub either from inline ``--set`` key=value | ||
| arguments or from a JSON/YAML object file specified via ``--file``. | ||
| """ | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| import contextlib | ||
| from pathlib import Path | ||
|
|
||
| import typer # pyright: ignore[reportMissingImports] | ||
| from rich.console import Console # pyright: ignore[reportMissingImports] | ||
|
|
||
| from infrahub_sdk.ctl.client import initialize_client | ||
| from infrahub_sdk.ctl.commands.utils import resolve_node, resolve_relationship_values | ||
| from infrahub_sdk.ctl.parameters import CONFIG_PARAM | ||
| from infrahub_sdk.ctl.parsers import parse_set_args, validate_set_fields | ||
| from infrahub_sdk.ctl.utils import catch_exception | ||
| from infrahub_sdk.spec.object import ObjectFile | ||
|
|
||
| console = Console() | ||
|
|
||
|
|
||
| @catch_exception(console=console) | ||
| async def create_command( | ||
| kind: str = typer.Argument(..., help="Infrahub schema kind to create"), | ||
| set_args: list[str] | None = typer.Option(None, "--set", help="Field value in key=value format"), | ||
| file: Path | None = typer.Option(None, "--file", "-f", help="JSON or YAML file with object data"), | ||
| branch: str | None = typer.Option(None, "--branch", "-b", help="Target branch"), | ||
| _: str = CONFIG_PARAM, | ||
|
Comment on lines
+27
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Validate
🛠️ Suggested fix if file:
files = ObjectFile.load_from_disk(paths=[file])
for obj_file in files:
+ if obj_file.spec.kind != kind:
+ console.print(
+ f"[red]Error: --file contains kind '{obj_file.spec.kind}', expected '{kind}'."
+ )
+ raise typer.Exit(code=1)
await obj_file.validate_format(client=client, branch=branch)
await obj_file.process(client=client, branch=branch)
object_count = len(obj_file.spec.data)
console.print(f"[green]Created {object_count} objects of kind {obj_file.spec.kind}")Also applies to: 54-60 🤖 Prompt for AI Agents |
||
| ) -> None: | ||
| """Create a new object in Infrahub. | ||
|
|
||
| Provide field values with repeatable --set flags or supply a | ||
| JSON/YAML object file via --file. The two modes are mutually exclusive. | ||
|
|
||
| \b | ||
| Examples: | ||
| infrahubctl create InfraDevice --set name=spine01 --set status=active | ||
| infrahubctl create InfraDevice --set name=spine01 --set location=DC1 | ||
| infrahubctl create InfraDevice --file devices.yml | ||
| """ | ||
| if set_args and file: | ||
| console.print("[red]Error: --set and --file are mutually exclusive.") | ||
| raise typer.Exit(code=1) | ||
| if not set_args and not file: | ||
| console.print("[red]Error: provide --set key=value or --file <path>.") | ||
| console.print("Example: infrahubctl create MyKind --set name=foo --set status=active") | ||
| raise typer.Exit(code=1) | ||
|
|
||
| client = initialize_client(branch=branch) | ||
|
|
||
| if file: | ||
| files = ObjectFile.load_from_disk(paths=[file]) | ||
| for obj_file in files: | ||
| await obj_file.validate_format(client=client, branch=branch) | ||
| await obj_file.process(client=client, branch=branch) | ||
| object_count = len(obj_file.spec.data) | ||
| console.print(f"[green]Created {object_count} objects of kind {obj_file.spec.kind}") | ||
| else: | ||
| data = parse_set_args(set_args) # type: ignore[arg-type] | ||
| schema = await client.schema.get(kind=kind, branch=branch) | ||
| validate_set_fields(data, schema.attribute_names, schema.relationship_names) | ||
| data = await resolve_relationship_values(client, data, schema, branch=branch) | ||
|
|
||
| # Check if node already exists to distinguish create from upsert | ||
| existing = None | ||
| name_value = data.get("name") | ||
| if name_value is not None: | ||
| with contextlib.suppress(Exception): | ||
| existing = await resolve_node(client, kind, str(name_value), schema=schema, branch=branch) | ||
|
|
||
| node = await client.create(kind=kind, data=data, branch=branch) | ||
| await node.save(allow_upsert=True) | ||
| label = node.display_label or name_value or node.id | ||
|
|
||
| if existing: | ||
| console.print(f"[yellow]Updated {kind} '{label}' (id: {node.id}) — already existed") | ||
| else: | ||
| console.print(f"[green]Created {kind} '{label}' (id: {node.id})") | ||
Uh oh!
There was an error while loading. Please reload this page.