Node Operations and Data Model
Relevant source files
The following files were used as context for generating this wiki page:
The Infrahub Python SDK abstracts infrastructure data as native Python objects called Nodes. This data model allows developers to interact with the Infrahub database using built-in authentication, batching, and tracking, rather than raw API calls.
Nodes represent specific instances of infrastructure components defined in the Infrahub schema. Every interaction with infrastructure data—whether querying, creating, or modifying—revolves around the InfrahubNode object and its associated attributes and relationships.
Sources: AGENTS.md:3-5, dev/specs/001-end-user-cli/research.md:32-34
Core Data Model Entities
The data model consists of four primary entities that define how infrastructure information is structured and stored.
| Entity | Description |
|---|---|
| Kind | A type definition in the schema (e.g., InfraDevice). Defines namespace, attributes, and relationships. |
| Node | A specific instance of a Kind. Contains an ID, attribute values, and relationship connections. |
| Attribute | A named property on a Kind with a specific type and constraints. |
| Relationship | A typed connection between two Nodes, defined by cardinality and direction in the schema. |
Sources: dev/specs/001-end-user-cli/spec.md:144-150
Node Composition
An InfrahubNode contains metadata, attributes, and relationships. Metadata includes the object's unique identifier (UUID), its human-friendly ID (HFID), and branch information. Attributes store simple values like strings or integers, while relationships link the node to other nodes.
The diagram shows the internal composition of a Node, highlighting how it aggregates metadata, attributes, and relationships.
Sources: dev/specs/001-end-user-cli/research.md:32-38, infrahub_sdk/node/node.py
Node Operations (CRUD)
Node operations are performed using the InfrahubClient (async) or InfrahubClientSync (sync). Both clients provide parity for all public features.
Sources: dev/constitution.md:28-31
Querying Data
The SDK provides multiple methods to retrieve nodes from the database.
client.all(): Retrieves all nodes of a specific Kind. It supports parameters likeoffset,limit, andorder.client.get(): Retrieves a single node using either its UUID or its Human-Friendly ID (HFID).client.filters(): Applies specific filters based on attribute values or relationship IDs.
# Example of querying a node by kind and filtering by attribute
nodes = await client.all(kind="NetworkDevice", name__value="spine01")
Sources: dev/specs/001-end-user-cli/research.md:28-31, AGENTS.md:52-54
Creating and Updating Nodes
Creating a node involves instantiating it with a kind and a data dictionary, then calling the save() method. The save() method handles both the initial creation and subsequent updates (upserts).
- Instantiate: Use
client.create(kind=kind, data=data). - Modify: Set attribute values via
node.<attribute>.value. - Persist: Call
await node.save().
Sources: dev/specs/001-end-user-cli/research.md:65-69, AGENTS.md:55
Deletion
Deleting a node requires fetching the object first and then executing the delete() method. The system identifies dependencies and raises errors if a deletion conflict occurs.
Sources: dev/specs/001-end-user-cli/research.md:70-71, dev/specs/001-end-user-cli/spec.md:72-75
Relationship Management
Relationships are managed through the SDK's RelationshipManager. The SDK handles the resolution of target nodes automatically when an HFID or UUID is provided.
- Cardinality-One: A single target node or identifier.
- Cardinality-Many: Represented as a list of target nodes. In CLI operations, these are specified using JSON array-of-HFID-arrays syntax, such as
[["Cisco"], ["Juniper"]].
The flow shows how the SDK resolves different identifier types into related nodes.
Sources: dev/specs/001-end-user-cli/research.md:80-95
CLI Mapping to Node Operations
The infrahubctl CLI acts as a thin layer over these SDK methods, translating user commands into Node operations.
| CLI Command | SDK Method | Purpose |
|---|---|---|
get <kind> | client.all() | Lists all instances of a kind in a table. |
get <kind> <id> | client.get() | Shows detailed view of attributes and metadata. |
create --set x=y | client.create() | Generates a new node instance. |
update --set x=z | node.save() | Modifies existing node attributes. |
delete <id> | node.delete() | Removes the node instance. |
Sources: dev/specs/001-end-user-cli/tasks.md:63-125, dev/specs/001-end-user-cli/research.md:24-27
Summary
The node system provides a structured, object-oriented way to manage infrastructure. By encapsulating metadata, attributes, and relationships into a unified InfrahubNode class, the SDK ensures that data operations are consistent across the CLI, Ansible collections, and custom Python applications. All operations support both asynchronous and synchronous execution to accommodate different development environments.
Sources: dev/constitution.md:14-18, AGENTS.md:11-15