Nodes & attributes
A Node is the fundamental unit of the schema — it represents a concrete object in your infrastructure model such as a device, interface, or IP address. Nodes are composed of Attributes (direct values) and Relationships (links to other nodes). This page covers how to define nodes and attributes, what kinds are available, and how to configure identifiers, constraints, and display.
Nodes vs. generics
Use a Node when you need to represent a concrete object in your infrastructure model with specific attributes and relationships.
Use a Generic when you want to share common attributes or relationships across multiple node types. This helps to avoid redundancy and ensures consistency across your schema. For example, if you have different types of network interfaces (physical, logical) that share common attributes like name and description, you can define a Generic interface with these attributes and have the specific interface types inherit from it.
Generics can also be used to connect multiple types of Nodes to the same relationship.
A Generic cannot exist independently; it must be instantiated by at least one Node.
See Generics & inheritance for a full guide on generics.
Node example
In the example below, the node Person has 2 attributes (name and description) and the node Car has 1 attribute (model) and 1 relationship to Person, identified by owner.
nodes:
- name: Person
namespace: Example1
attributes:
- name: name
kind: Text
unique: true
- name: description
kind: Text
optional: true
- name: Car
namespace: Example1
attributes:
- name: model
kind: Text
relationships:
- name: owner
peer: Example1Person
optional: false
cardinality: one
kind: Attribute
Node, Attribute, and Relationship are defined by their kind. While the name and the namespace of the node are up to the creator of the schema, the kinds for the attributes and the relationships are coming from Infrahub. The kind of an attribute, or a relationship, is important because it defines how each element is represented in GraphQL and the UI.
The kind of a model is generated by concatenating the namespace and the name.
Attribute kinds
Text: Standard TextNumber: Standard NumberNumberPool: Standard Number that creates aCoreNumberPoolResource Manager tied to the attributeTextArea: Long-form Text that can span multiple linesDateTime: A Date and a TimeDropdown: A list of choices, each choice can have a color and descriptionEmail: Email addressPassword: A Text String that should be obfuscated but which can be read with enough right in the UIHashedPassword: Similar to Password but it will not be shown in the UI and can't be re-read.URL: An URL to a website or a resource over HTTPFile: Path to a file on the filesystemMacAddress: Mac Address following the format (XX:XX:XX:XX:XX:XX)Color: An HTML colorBoolean: Flag that can be either True or FalseBandwidth: Bandwidth in kbpsIPHost: IP Address in either IPV4 or IPv6 formatIPNetwork: IP Network in either IPV4 or IPv6 formatCheckbox: Duplicate ofBooleanList: List of any valueJSON: Any data structure compatible with JSONAny: Can be anything
Attribute kinds behavior in the UI
| Kind | Display in List View | Display in Detailed View |
|---|---|---|
ID | No | Yes |
Text | Yes | Yes |
Number | Yes | Yes |
NumberPool | Yes | Yes |
Boolean | Yes | Yes |
Dropdown | Yes | Yes |
TextArea | No | Yes |
DateTime | No | Yes |
Email | Yes | Yes |
Password | No | Yes |
URL | Yes | Yes |
File | Yes | Yes |
MacAddress | Yes | Yes |
Color | Yes | Yes |
Bandwidth | Yes | Yes |
IPHost | Yes | Yes |
IPNetwork | Yes | Yes |
Checkbox | No | Yes |
List | No | Yes |
JSON | No | Yes |
Any | No | Yes |
Attribute parameters
There are some attribute kinds that allow optional parameters to be defined to control the behavior of the attribute. Below are the attribute kinds and their accepted parameters.
- Number
- NumberPool
- Text
- TextArea
| Parameter | Default |
|---|---|
| min_value | None |
| max_value | None |
| excluded_values | None |
| Parameter | Default |
|---|---|
| end_range | 9223372036854775807 |
| start_range | 1 |
| Parameter | Default |
|---|---|
| regex | None |
| min_length | None |
| max_length | None |
| Parameter | Default |
|---|---|
| regex | None |
| min_length | None |
| max_length | None |
Uniqueness constraints
More complex uniqueness constraints, composed of multiple attributes and/or relationships, can be defined at the Node or Generic level with the property uniqueness_constraints.
It's possible to define multiple uniqueness constraints and each of them will be evaluated individually.
In the example below, the node schema ExampleCar, ["owner", "model__value"] guarantees that a car will be unique based on the owner and the model of the car.
uniqueness_constraints can be composed of a list of N number of attributes or relationships of cardinality one:
- For an attribute, the valid format is
<attributename>__value. Currently only value is supported but in the future, the plan is to allow additional metadata to be used as well. - For a relationship, only the name of the relationship should be provided
<relationshipname>. Only relationships of cardinalityoneare supported and the relationship must be mandatory.
nodes:
- name: Person
namespace: Example
attributes:
- name: name
kind: Text
unique: true
- name: Car
namespace: Example
uniqueness_constraints:
- ["owner", "model__value"]
attributes:
- name: model
kind: Text
relationships:
- name: owner
peer: ExamplePerson
optional: false
cardinality: one
Optimizing uniqueness constraints
When defining uniqueness constraints, the order of the elements in each constraint array can significantly impact performance. The uniqueness checker processes constraints from left to right, so listing the most selective elements first can dramatically improve performance.
The uniqueness checker runs Cypher queries to validate constraints. When elements are ordered from most to least selective, the database can quickly eliminate non-matching candidates earlier in the query execution.
For example, consider an IP address model with a uniqueness constraint:
uniqueness_constraints:
- ["ip_namespace", "address__value"]
If many IP addresses share the same namespace but few share the same address value, this constraint would require checking all nodes with the same namespace before filtering by address. A more efficient ordering would be:
uniqueness_constraints:
- ["address__value", "ip_namespace"]
This allows the system to first filter by the more selective address value, resulting in fewer nodes to check against the namespace constraint.
Order uniqueness constraint elements from most selective (returning fewer matches) to least selective (returning more matches) to optimize database query performance.
Display label
The display_label property allows you to define a custom label for nodes in the Infrahub UI. This label is used in various parts of the interface, such as list views and detail views, to provide a more user-friendly representation of the node.
Human-friendly identifier (hfid)
In addition to the internal ID automatically generated for each object (UUID), Infrahub provides a way to define a set of fields that will constitute a human-friendly identifier (HFID).
The hfid is meant to be used to reference objects uniquely across systems, or even before an object has been created in Infrahub.
Having a human-friendly way to identify an object is very important to build robust data synchronization between systems and to provide true idempotent scripts.
In the network industry:
- The
hfidof a device could be itsname:atl1-edge01 - The
hfidof an interface could be the combination of the name of the device and the name of the interface: (atl1-edge01,Ethernet1)
In the example below, each ExamplePerson, will have a hfid composed of his/her lastname and firstname.
human_friendly_id can be composed of N number of attributes or relationships of cardinality one:
- For an attribute, the valid format is
<attributename>__value. Currently only value is supported but in the future, the plan is to allow additional metadata to be used as well. - For a relationship, the name of the relationship and the name of a unique attribute must be provided
<relationshipname>__<attributename>__value. Only relationships of cardinalityoneare supported and the relationship must be mandatory.
nodes:
- name: Person
namespace: Example
human_friendly_id: ["lastname__value", "firstname__value"]
attributes:
- name: firstname
kind: Text
- name: lastname
kind: Text
If a human_friendly_id is defined on a node but no uniqueness_constraints are present, a uniqueness constraint matching the human_friendly_id will be automatically created.
If at least one attribute is marked as unique, and human_friendly_id hasn't been defined, human_friendly_id will be automatically created.
hfid support in GraphQL
hfid can be used as an alternative to id in most places in GraphQL, including:
- Update Mutation
- Upsert Mutation
- Delete Mutation
- Related Node in all Mutations
Menu placement
At the node (or generic) level, three attributes control how a model appears in the frontend sidebar menu:
include_in_menu— Boolean to indicate if a given model should be displayed in the menu or not. By default, all models will be displayed directly underObjectsin the frontend.menu_placement— Makes it possible to create a nested structure within the menu to display a given model under another one.icon— Indicates which icon should be displayed next to the model in the menu. Any icon from the Material Design Icons library can be used. The full identifier of the icon must be used, for examplemdi:domain.
For detailed guidance on structuring the menu and worked examples, see Menu customization.
Field ordering
The order_weight property controls the position of attributes and relationships in the frontend. Lower values appear first; Infrahub assigns defaults in increments of 1000 when order_weight is not specified.
Reserved namespaces and attribute names
Some namespaces like Core, Infrahub, Profile, and Builtin are reserved and can't be used by users to define new Nodes and Generics.
In a similar fashion, some attribute names can't be used, like attribute or relationship.
Related concepts
- Relationships — Link nodes together with typed connections
- Generics & inheritance — Share attributes across node types
- Profiles — Apply default values across multiple node instances
- Templates — Blueprint-based object creation
- Labels — Human-friendly names for nodes and attributes
- Reference: Node — Full node property reference
- Reference: Attribute — Full attribute property reference