Skip to main content

infrahub_sdk.node.node

Classes

InfrahubNode

Asynchronous Infrahub node bound to an :class:InfrahubClient.

Provides full CRUD against the backend (:meth:save, :meth:create, :meth:update, :meth:delete) along with relationship traversal (:meth:get_flat_value, :meth:extract), feature-gated artifact and resource-pool helpers (:meth:artifact_generate, :meth:get_pool_allocated_resources), and file upload or download for nodes inheriting from CoreFileObject.

Attributes and relationships defined on the schema are exposed as instance attributes via attribute-style access (node.name.value, node.parent).

Methods:

from_graphql

from_graphql(cls, client: InfrahubClient, branch: str, data: dict, schema: MainSchemaTypesAPI | None = None, timeout: int | None = None) -> Self

Build an :class:InfrahubNode from a raw GraphQL response.

When no schema is provided, the node kind is read from __typename in the payload and the schema is fetched from the client.

Args:

  • client: The client used to interact with the backend.
  • branch: The branch the node belongs to.
  • data: The GraphQL payload describing the node.
  • schema: Pre-fetched schema for the node kind. Skips the schema lookup when provided.
  • timeout: Overrides the default timeout used when fetching the schema. Specified in seconds.

Returns:

  • The hydrated node instance.

Raises:

  • ValueError: If __typename is missing from data and no schema was provided.

generate

generate(self, nodes: list[str] | None = None) -> None

Trigger artifact generation for this artifact definition.

Only available on nodes whose kind is CoreArtifactDefinition.

Args:

  • nodes: The IDs of target nodes to generate artifacts for. When omitted, generation runs for all targets matched by the definition.

Raises:

  • FeatureNotSupportedError: If this node is not a CoreArtifactDefinition.

artifact_generate

artifact_generate(self, name: str) -> None

Regenerate a named artifact targeting this node.

Looks up the CoreArtifact named name for this node, then calls :meth:generate on the related definition with this artifact's ID.

Args:

  • name: The name of the artifact to regenerate.

Raises:

  • FeatureNotSupportedError: If this node does not inherit from CoreArtifactTarget.

artifact_fetch

artifact_fetch(self, name: str) -> str | dict[str, Any]

Fetch the stored content of a named artifact for this node.

Args:

  • name: The name of the artifact to fetch.

Returns:

  • str | dict[str, Any]: The artifact content. Returns a parsed object for
  • JSON-typed artifacts and a string for text-typed artifacts.

Raises:

  • FeatureNotSupportedError: If this node does not inherit from CoreArtifactTarget.

download_file

download_file(self, dest: None = None, skip_if_unchanged: bool = ...) -> bytes
Show 2 other overloads

download_file

download_file(self, dest: Path, skip_if_unchanged: bool = ...) -> int

download_file

download_file(self, dest: Path | None = None, skip_if_unchanged: bool = False) -> bytes | int

Download the file content from this FileObject node.

This method is only available for nodes that inherit from CoreFileObject. The node must have been saved (have an id) before calling this method.

Args:

  • dest: Optional destination path. If provided, the file will be streamed directly to this path (memory-efficient for large files) and the number of bytes written will be returned. If not provided, the file content will be returned as bytes.
  • skip_if_unchanged: When True, compute the SHA-1 of the file at dest (which must be provided) and compare against the node's checksum attribute. If they match, return 0 without hitting the network. The checksum is the value loaded when this node was fetched — a later server-side change to the file will not be detected unless the caller re-fetches the node first.

Returns:

  • If dest is None: The file content as bytes.
  • If dest is provided: The number of bytes written to the file.
  • If skip_if_unchanged=True and the local file matches the server checksum: 0.

Raises:

  • FeatureNotSupportedError: If this node doesn't inherit from CoreFileObject.
  • ValueError: If the node hasn't been saved yet, file not found, or skip_if_unchanged=True was passed without a dest.
  • AuthenticationError: If authentication fails.

Examples:

>>> # Download to memory
>>> content = await contract.download_file()
>>> # Stream to file (memory-efficient for large files)
>>> bytes_written = await contract.download_file(dest=Path("/tmp/contract.pdf"))
>>> # Skip download if local file already matches server checksum
>>> bytes_written = await contract.download_file(
... dest=Path("/tmp/contract.pdf"), skip_if_unchanged=True
... )

matches_local_checksum

matches_local_checksum(self, source: bytes | Path | BinaryIO) -> bool

Return True if source's SHA-1 matches this node's server checksum.

Only available for nodes inheriting from CoreFileObject. Callers that want to branch on the comparison without invoking a transfer should use this primitive instead of reading node.checksum.value and hashing source themselves, so the hashing convention stays centralised in the SDK.

The comparison is against the checksum attribute as loaded when this node was retrieved from the server. If the server's file has been replaced since the node was fetched, this method will not see that change — re-fetch the node to refresh the checksum before comparing.

Args:

  • source: Local content to hash and compare. Accepts the same shapes as :func:infrahub_sdk.file_handler.sha1_of_source.

Returns:

  • True if the local digest equals the server's stored checksum.

Raises:

  • FeatureNotSupportedError: Node is not a CoreFileObject.
  • ValueError: Node has no server-side checksum yet (unsaved or file never attached).

upload_if_changed

upload_if_changed(self, source: bytes | Path | BinaryIO, name: str | None = None) -> UploadResult

Upload source only if its SHA-1 differs from the server checksum.

Composes :meth:matches_local_checksum with :meth:upload_from_path (or :meth:upload_from_bytes) and :meth:save. For unsaved nodes or nodes that have no prior server-side file, the upload is always performed — there is nothing to compare against.

Idempotency is content-only: when the local SHA-1 matches the server checksum the upload is skipped even if name differs from the server-side filename. Use a regular :meth:upload_from_path / :meth:save round-trip if you need to rename without changing content.

Args:

  • source: Content to upload. bytes and BinaryIO sources must supply name; for a Path the filename is derived from source.name when name is omitted.
  • name: Filename to use on the server. Required for bytes / BinaryIO sources.

Returns:

  • class:UploadResult with was_uploaded=False (skipped) or
  • was_uploaded=True (transfer occurred), and the resulting server
  • checksum (None only when no server checksum was available
  • after the operation).

Raises:

  • FeatureNotSupportedError: Node is not a CoreFileObject.
  • ValueError: source is bytes or BinaryIO and no name was supplied.

delete

delete(self, timeout: int | None = None, request_context: RequestContext | None = None) -> None

Delete this node on the backend.

Args:

  • timeout: Overrides the default timeout used when querying the GraphQL API. Specified in seconds.
  • request_context: Request-level context passed through to the mutation. When omitted, the client's request context is used.

save

save(self, allow_upsert: bool = False, update_group_context: bool | None = None, timeout: int | None = None, request_context: RequestContext | None = None) -> None

Persist this node to the backend, creating or updating it as appropriate.

New nodes are created (or upserted when allow_upsert is set), and existing nodes are updated with only the modified fields. After a successful save, the node is added to the client store and, when applicable, to the active group context for tracking.

Args:

  • allow_upsert: When True, an existing node is upserted instead of failing with a duplicate. Defaults to False.
  • update_group_context: Whether to update the group context with this node. When None and the client is in tracking mode, defaults to True.
  • timeout: Overrides the default timeout used when querying the GraphQL API. Specified in seconds.
  • request_context: Request-level context passed through to the mutation. When omitted, the client's request context is used.

generate_query_data

generate_query_data(self, filters: dict[str, Any] | None = None, offset: int | None = None, limit: int | None = None, include: list[str] | None = None, exclude: list[str] | None = None, fragment: bool = False, prefetch_relationships: bool = False, partial_match: bool = False, property: bool = False, order: Order | None = None, include_metadata: bool = False) -> dict[str, Any | dict]

Generate the full GraphQL query payload for this node kind.

The returned dict combines :meth:generate_query_data_init with :meth:generate_query_data_node. When the node is a generic and fragment is True, ...on Kind fragments are added for every implementing kind so the relevant attributes are returned alongside the generic fields.

Args:

  • filters: Filters to apply to the query.
  • offset: Pagination offset.
  • limit: Pagination limit.
  • include: Attributes or relationships to include.
  • exclude: Attributes or relationships to exclude.
  • fragment: When True and the schema is a generic, emit ...on Kind fragments for each implementing kind. Defaults to False.
  • prefetch_relationships: When True, pre-fetch related node data instead of returning only their identifiers. Defaults to False.
  • partial_match: When True, allow partial matches on filter criteria. Defaults to False.
  • property: When True, include attribute and relationship properties (source, owner, is_protected, ...). Defaults to False.
  • order: Ordering options to apply to the query.
  • include_metadata: When True, include node_metadata and relationship_metadata in the result. Defaults to False.

Returns:

  • dict[str, Any | dict]: A query payload keyed by the node kind, ready to be
  • rendered as GraphQL.

generate_query_data_node

generate_query_data_node(self, include: list[str] | None = None, exclude: list[str] | None = None, inherited: bool = True, insert_alias: bool = False, prefetch_relationships: bool = False, property: bool = False, include_metadata: bool = False) -> dict[str, Any | dict]

Generate the node part of a GraphQL Query with attributes and nodes.

Args:

  • include: List of attributes or relationships to include. Defaults to None.
  • exclude: List of attributes or relationships to exclude. Defaults to None.
  • inherited: Indicated of the attributes and the relationships inherited from generics should be included as well. Defaults to True.
  • insert_alias: If True, inserts aliases in the query for each attribute or relationship.
  • prefetch_relationships: If True, pre-fetches relationship data as part of the query.
  • include_metadata: If True, includes node_metadata and relationship_metadata in the query.

Returns:

  • dict[str, Union[Any, Dict]]: GraphQL query in dictionary format

add_relationships

add_relationships(self, relation_to_update: str, related_nodes: list[str]) -> None

Add peers to a cardinality-many relationship through a dedicated mutation.

Unlike :meth:save, this method targets a single relationship and only adds peers, leaving every other field untouched.

Args:

  • relation_to_update: The name of the relationship to update.
  • related_nodes: The IDs of the peers to add.

remove_relationships

remove_relationships(self, relation_to_update: str, related_nodes: list[str]) -> None

Remove peers from a cardinality-many relationship through a dedicated mutation.

Unlike :meth:save, this method targets a single relationship and only removes the listed peers, leaving every other field untouched.

Args:

  • relation_to_update: The name of the relationship to update.
  • related_nodes: The IDs of the peers to remove.

create

create(self, allow_upsert: bool = False, timeout: int | None = None, request_context: RequestContext | None = None) -> None

Create this node on the backend.

For nodes inheriting from CoreFileObject, the file content set with :meth:upload_from_path or :meth:upload_from_bytes is uploaded as part of the mutation and cleared from the node afterward.

Prefer :meth:save over calling create() directly so existing-vs-new logic is handled for you.

Args:

  • allow_upsert: When True, the operation upserts instead of erroring on a duplicate. Defaults to False.
  • timeout: Overrides the default timeout used when querying the GraphQL API. Specified in seconds.
  • request_context: Request-level context passed through to the mutation. When omitted, the client's request context is used.

Raises:

  • ValueError: If this is a file-object node and no file content has been set.

update

update(self, do_full_update: bool = False, timeout: int | None = None, request_context: RequestContext | None = None) -> None

Update this node on the backend.

By default only the modified attributes and relationships are sent so the server can compute a minimal diff. Setting do_full_update re-sends every field even when unchanged, which is useful when forcing relationship reconciliation.

Prefer :meth:save over calling update() directly so existing-vs-new logic is handled for you.

Args:

  • do_full_update: When True, send every field even when unmodified. Defaults to False.
  • timeout: Overrides the default timeout used when querying the GraphQL API. Specified in seconds.
  • request_context: Request-level context passed through to the mutation. When omitted, the client's request context is used.

get_pool_allocated_resources

get_pool_allocated_resources(self, resource: InfrahubNode) -> list[InfrahubNode]

Fetch all nodes that were allocated for the pool and a given resource.

Args:

  • resource: The resource from which the nodes were allocated.

Returns:

  • list[InfrahubNode]: The allocated nodes.

Raises:

  • ValueError: If the node is not a resource pool.

get_pool_resources_utilization

get_pool_resources_utilization(self) -> list[dict[str, Any]]

Fetch the utilization of each resource for the pool.

Returns:

  • list[dict[str, Any]]: A list containing the allocation numbers for each resource of the pool.

Raises:

  • ValueError: If the node is not a resource pool.

get_flat_value

get_flat_value(self, key: str, separator: str = '__') -> Any

Resolve a value addressed by a flat key over this node and its related nodes.

Walks attributes on this node, descending through cardinality-one relationships (which are fetched on demand) until the final component is reached. Each relationship hop incurs a backend call, so this is intended for ad-hoc lookups rather than bulk traversal.

Args:

  • key: The flat key to resolve (for example "name__value" or "site__name__value").
  • separator: Component separator in key. Defaults to "__".

Returns:

  • The resolved value.

Raises:

  • ValueError: If a component does not match an attribute or relationship, or if a relationship hop targets a non cardinality-one relationship.

Examples:

name__value module.object.value

extract

extract(self, params: dict[str, str]) -> dict[str, Any]

Extract several values addressed by flat keys into a labeled dict.

Each value in params is resolved with :meth:get_flat_value, and the corresponding key is preserved as the output label.

Args:

  • params: A mapping of output label to flat key to resolve.

Returns:

  • dict[str, Any]: The resolved values keyed by their output label.

InfrahubNodeSync

Synchronous Infrahub node bound to an :class:InfrahubClientSync.

Synchronous counterpart of :class:InfrahubNode. Provides full CRUD against the backend (:meth:save, :meth:create, :meth:update, :meth:delete) along with relationship traversal (:meth:get_flat_value, :meth:extract), feature-gated artifact and resource-pool helpers (:meth:artifact_generate, :meth:get_pool_allocated_resources), and file upload or download for nodes inheriting from CoreFileObject.

Attributes and relationships defined on the schema are exposed as instance attributes via attribute-style access (node.name.value, node.parent).

Methods:

from_graphql

from_graphql(cls, client: InfrahubClientSync, branch: str, data: dict, schema: MainSchemaTypesAPI | None = None, timeout: int | None = None) -> Self

Build an :class:InfrahubNodeSync from a raw GraphQL response.

When no schema is provided, the node kind is read from __typename in the payload and the schema is fetched from the client.

Args:

  • client: The client used to interact with the backend.
  • branch: The branch the node belongs to.
  • data: The GraphQL payload describing the node.
  • schema: Pre-fetched schema for the node kind. Skips the schema lookup when provided.
  • timeout: Overrides the default timeout used when fetching the schema. Specified in seconds.

Returns:

  • The hydrated node instance.

Raises:

  • ValueError: If __typename is missing from data and no schema was provided.

generate

generate(self, nodes: list[str] | None = None) -> None

Trigger artifact generation for this artifact definition.

Only available on nodes whose kind is CoreArtifactDefinition.

Args:

  • nodes: The IDs of target nodes to generate artifacts for. When omitted, generation runs for all targets matched by the definition.

Raises:

  • FeatureNotSupportedError: If this node is not a CoreArtifactDefinition.

artifact_generate

artifact_generate(self, name: str) -> None

Regenerate a named artifact targeting this node.

Looks up the CoreArtifact named name for this node, then calls :meth:generate on the related definition with this artifact's ID.

Args:

  • name: The name of the artifact to regenerate.

Raises:

  • FeatureNotSupportedError: If this node does not inherit from CoreArtifactTarget.

artifact_fetch

artifact_fetch(self, name: str) -> str | dict[str, Any]

Fetch the stored content of a named artifact for this node.

Args:

  • name: The name of the artifact to fetch.

Returns:

  • str | dict[str, Any]: The artifact content. Returns a parsed object for
  • JSON-typed artifacts and a string for text-typed artifacts.

Raises:

  • FeatureNotSupportedError: If this node does not inherit from CoreArtifactTarget.

download_file

download_file(self, dest: None = None, skip_if_unchanged: bool = ...) -> bytes
Show 2 other overloads

download_file

download_file(self, dest: Path, skip_if_unchanged: bool = ...) -> int

download_file

download_file(self, dest: Path | None = None, skip_if_unchanged: bool = False) -> bytes | int

Download the file content from this FileObject node.

This method is only available for nodes that inherit from CoreFileObject. The node must have been saved (have an id) before calling this method.

Args:

  • dest: Optional destination path. If provided, the file will be streamed directly to this path (memory-efficient for large files) and the number of bytes written will be returned. If not provided, the file content will be returned as bytes.
  • skip_if_unchanged: When True, compute the SHA-1 of the file at dest (which must be provided) and compare against the node's checksum attribute. If they match, return 0 without hitting the network. The checksum is the value loaded when this node was fetched — a later server-side change to the file will not be detected unless the caller re-fetches the node first.

Returns:

  • If dest is None: The file content as bytes.
  • If dest is provided: The number of bytes written to the file.
  • If skip_if_unchanged=True and the local file matches the server checksum: 0.

Raises:

  • FeatureNotSupportedError: If this node doesn't inherit from CoreFileObject.
  • ValueError: If the node hasn't been saved yet, file not found, or skip_if_unchanged=True was passed without a dest.
  • AuthenticationError: If authentication fails.

Examples:

>>> # Download to memory
>>> content = contract.download_file()
>>> # Stream to file (memory-efficient for large files)
>>> bytes_written = contract.download_file(dest=Path("/tmp/contract.pdf"))
>>> # Skip download if local file already matches server checksum
>>> bytes_written = contract.download_file(
... dest=Path("/tmp/contract.pdf"), skip_if_unchanged=True
... )

matches_local_checksum

matches_local_checksum(self, source: bytes | Path | BinaryIO) -> bool

Return True if source's SHA-1 matches this node's server checksum.

Only available for nodes inheriting from CoreFileObject. Callers that want to branch on the comparison without invoking a transfer should use this primitive instead of reading node.checksum.value and hashing source themselves, so the hashing convention stays centralised in the SDK.

The comparison is against the checksum attribute as loaded when this node was retrieved from the server. If the server's file has been replaced since the node was fetched, this method will not see that change — re-fetch the node to refresh the checksum before comparing.

Args:

  • source: Local content to hash and compare. Accepts the same shapes as :func:infrahub_sdk.file_handler.sha1_of_source.

Returns:

  • True if the local digest equals the server's stored checksum.

Raises:

  • FeatureNotSupportedError: Node is not a CoreFileObject.
  • ValueError: Node has no server-side checksum yet (unsaved or file never attached).

upload_if_changed

upload_if_changed(self, source: bytes | Path | BinaryIO, name: str | None = None) -> UploadResult

Upload source only if its SHA-1 differs from the server checksum.

Composes :meth:matches_local_checksum with :meth:upload_from_path (or :meth:upload_from_bytes) and :meth:save. For unsaved nodes or nodes that have no prior server-side file, the upload is always performed — there is nothing to compare against.

Idempotency is content-only: when the local SHA-1 matches the server checksum the upload is skipped even if name differs from the server-side filename. Use a regular :meth:upload_from_path / :meth:save round-trip if you need to rename without changing content.

Args:

  • source: Content to upload. bytes and BinaryIO sources must supply name; for a Path the filename is derived from source.name when name is omitted.
  • name: Filename to use on the server. Required for bytes / BinaryIO sources.

Returns:

  • class:UploadResult with was_uploaded=False (skipped) or
  • was_uploaded=True (transfer occurred), and the resulting server
  • checksum (None only when no server checksum was available
  • after the operation).

Raises:

  • FeatureNotSupportedError: Node is not a CoreFileObject.
  • ValueError: source is bytes or BinaryIO and no name was supplied.

delete

delete(self, timeout: int | None = None, request_context: RequestContext | None = None) -> None

Delete this node on the backend.

Args:

  • timeout: Overrides the default timeout used when querying the GraphQL API. Specified in seconds.
  • request_context: Request-level context passed through to the mutation. When omitted, the client's request context is used.

save

save(self, allow_upsert: bool = False, update_group_context: bool | None = None, timeout: int | None = None, request_context: RequestContext | None = None) -> None

Persist this node to the backend, creating or updating it as appropriate.

New nodes are created (or upserted when allow_upsert is set), and existing nodes are updated with only the modified fields. After a successful save, the node is added to the client store and, when applicable, to the active group context for tracking.

Args:

  • allow_upsert: When True, an existing node is upserted instead of failing with a duplicate. Defaults to False.
  • update_group_context: Whether to update the group context with this node. When None and the client is in tracking mode, defaults to True.
  • timeout: Overrides the default timeout used when querying the GraphQL API. Specified in seconds.
  • request_context: Request-level context passed through to the mutation. When omitted, the client's request context is used.

generate_query_data

generate_query_data(self, filters: dict[str, Any] | None = None, offset: int | None = None, limit: int | None = None, include: list[str] | None = None, exclude: list[str] | None = None, fragment: bool = False, prefetch_relationships: bool = False, partial_match: bool = False, property: bool = False, order: Order | None = None, include_metadata: bool = False) -> dict[str, Any | dict]

Generate the full GraphQL query payload for this node kind.

The returned dict combines :meth:generate_query_data_init with :meth:generate_query_data_node. When the node is a generic and fragment is True, ...on Kind fragments are added for every implementing kind so the relevant attributes are returned alongside the generic fields.

Args:

  • filters: Filters to apply to the query.
  • offset: Pagination offset.
  • limit: Pagination limit.
  • include: Attributes or relationships to include.
  • exclude: Attributes or relationships to exclude.
  • fragment: When True and the schema is a generic, emit ...on Kind fragments for each implementing kind. Defaults to False.
  • prefetch_relationships: When True, pre-fetch related node data instead of returning only their identifiers. Defaults to False.
  • partial_match: When True, allow partial matches on filter criteria. Defaults to False.
  • property: When True, include attribute and relationship properties (source, owner, is_protected, ...). Defaults to False.
  • order: Ordering options to apply to the query.
  • include_metadata: When True, include node_metadata and relationship_metadata in the result. Defaults to False.

Returns:

  • dict[str, Any | dict]: A query payload keyed by the node kind, ready to be
  • rendered as GraphQL.

generate_query_data_node

generate_query_data_node(self, include: list[str] | None = None, exclude: list[str] | None = None, inherited: bool = True, insert_alias: bool = False, prefetch_relationships: bool = False, property: bool = False, include_metadata: bool = False) -> dict[str, Any | dict]

Generate the node part of a GraphQL Query with attributes and nodes.

Args:

  • include: List of attributes or relationships to include. Defaults to None.
  • exclude: List of attributes or relationships to exclude. Defaults to None.
  • inherited: Indicated of the attributes and the relationships inherited from generics should be included as well. Defaults to True.
  • insert_alias: If True, inserts aliases in the query for each attribute or relationship.
  • prefetch_relationships: If True, pre-fetches relationship data as part of the query.
  • include_metadata: If True, includes node_metadata and relationship_metadata in the query.

Returns:

  • dict[str, Union[Any, Dict]]: GraphQL query in dictionary format

add_relationships

add_relationships(self, relation_to_update: str, related_nodes: list[str]) -> None

Add peers to a cardinality-many relationship through a dedicated mutation.

Unlike :meth:save, this method targets a single relationship and only adds peers, leaving every other field untouched.

Args:

  • relation_to_update: The name of the relationship to update.
  • related_nodes: The IDs of the peers to add.

remove_relationships

remove_relationships(self, relation_to_update: str, related_nodes: list[str]) -> None

Remove peers from a cardinality-many relationship through a dedicated mutation.

Unlike :meth:save, this method targets a single relationship and only removes the listed peers, leaving every other field untouched.

Args:

  • relation_to_update: The name of the relationship to update.
  • related_nodes: The IDs of the peers to remove.

create

create(self, allow_upsert: bool = False, timeout: int | None = None, request_context: RequestContext | None = None) -> None

Create this node on the backend.

For nodes inheriting from CoreFileObject, the file content set with :meth:upload_from_path or :meth:upload_from_bytes is uploaded as part of the mutation and cleared from the node afterward.

Prefer :meth:save over calling create() directly so existing-vs-new logic is handled for you.

Args:

  • allow_upsert: When True, the operation upserts instead of erroring on a duplicate. Defaults to False.
  • timeout: Overrides the default timeout used when querying the GraphQL API. Specified in seconds.
  • request_context: Request-level context passed through to the mutation. When omitted, the client's request context is used.

Raises:

  • ValueError: If this is a file-object node and no file content has been set.

update

update(self, do_full_update: bool = False, timeout: int | None = None, request_context: RequestContext | None = None) -> None

Update this node on the backend.

By default only the modified attributes and relationships are sent so the server can compute a minimal diff. Setting do_full_update re-sends every field even when unchanged, which is useful when forcing relationship reconciliation.

Prefer :meth:save over calling update() directly so existing-vs-new logic is handled for you.

Args:

  • do_full_update: When True, send every field even when unmodified. Defaults to False.
  • timeout: Overrides the default timeout used when querying the GraphQL API. Specified in seconds.
  • request_context: Request-level context passed through to the mutation. When omitted, the client's request context is used.

get_pool_allocated_resources

get_pool_allocated_resources(self, resource: InfrahubNodeSync) -> list[InfrahubNodeSync]

Fetch all nodes that were allocated for the pool and a given resource.

Args:

  • resource: The resource from which the nodes were allocated.

Returns:

  • list[InfrahubNodeSync]: The allocated nodes.

Raises:

  • ValueError: If the node is not a resource pool.

get_pool_resources_utilization

get_pool_resources_utilization(self) -> list[dict[str, Any]]

Fetch the utilization of each resource for the pool.

Returns:

  • list[dict[str, Any]]: A list containing the allocation numbers for each resource of the pool.

Raises:

  • ValueError: If the node is not a resource pool.

get_flat_value

get_flat_value(self, key: str, separator: str = '__') -> Any

Resolve a value addressed by a flat key over this node and its related nodes.

Walks attributes on this node, descending through cardinality-one relationships (which are fetched on demand) until the final component is reached. Each relationship hop incurs a backend call, so this is intended for ad-hoc lookups rather than bulk traversal.

Args:

  • key: The flat key to resolve (for example "name__value" or "site__name__value").
  • separator: Component separator in key. Defaults to "__".

Returns:

  • The resolved value.

Raises:

  • ValueError: If a component does not match an attribute or relationship, or if a relationship hop targets a non cardinality-one relationship.

Examples:

name__value module.object.value

extract

extract(self, params: dict[str, str]) -> dict[str, Any]

Extract several values addressed by flat keys into a labeled dict.

Each value in params is resolved with :meth:get_flat_value, and the corresponding key is preserved as the output label.

Args:

  • params: A mapping of output label to flat key to resolve.

Returns:

  • dict[str, Any]: The resolved values keyed by their output label.

UploadResult

Outcome of an idempotent upload attempt.

Returned by :meth:InfrahubNode.upload_if_changed and its sync twin. was_uploaded tells the caller whether a network transfer actually happened; checksum carries the SHA-1 of the content held on the server after the operation — on skip paths that is the server's pre-existing value, on upload paths it is the locally-computed SHA-1 used as a proxy (which matches what a standard CoreFileObject server stores, since the server computes SHA-1 of received bytes). None only when no server checksum was available (either the node was unsaved and nothing was transferred, or the save returned no checksum value).

The comparison used by upload_if_changed reads the node's checksum attribute, which was populated when the node was fetched via client.get(...). A server-side change to the file between the fetch and the call will not be detected unless the caller re-fetches the node first.

InfrahubNodeBase

Base class for :class:InfrahubNode and :class:InfrahubNodeSync.

Owns the schema-driven state shared between the async and sync clients: attributes, relationships, identity (id, hfid), node metadata, and the helpers that turn the in-memory state into GraphQL query and mutation payloads. This class is not meant to be instantiated directly; use :class:InfrahubNode or :class:InfrahubNodeSync instead.

Attributes:

  • id: The unique identifier of the node, when known.
  • display_label: Human-readable label of the node.
  • typename: The GraphQL __typename of the node.

Methods:

get_branch

get_branch(self) -> str

Return the branch this node is bound to.

Returns:

  • The name of the branch.

get_path_value

get_path_value(self, path: str) -> Any

Resolve a value addressed by a dunder-separated path on this node.

The path can target an attribute (name__value, name__source), a cardinality-one related node (parent), an attribute of that related node (parent__name__value), or a property of one of its attributes (parent__name__source).

Args:

  • path: A path with components separated by __.

Returns:

  • The resolved value, or None when any path component cannot be
  • resolved (for example, an unfetched related node not present in the store).

get_human_friendly_id

get_human_friendly_id(self) -> list[str] | None

Compute the human-friendly ID for this node from its schema.

The HFID is composed of the values addressed by the schema's human_friendly_id paths. When any component cannot be resolved, the HFID is considered invalid and None is returned.

Returns:

  • list[str] | None: The HFID as a list of stringified components, or None
  • when the schema does not define an HFID or a component is missing.

get_human_friendly_id_as_string

get_human_friendly_id_as_string(self, include_kind: bool = False) -> str | None

Return the human-friendly ID joined into a single string.

Args:

  • include_kind: When True, the node kind is prepended as the first component of the resulting string. Defaults to False.

Returns:

  • str | None: The HFID joined with the HFID separator, or None when no
  • HFID is available.

hfid

hfid(self) -> list[str] | None

Return the human-friendly ID of this node as a list of components.

Returns:

  • list[str] | None: The HFID components, or None when unavailable.

hfid_str

hfid_str(self) -> str | None

Return the human-friendly ID of this node as a string, including the kind prefix.

Returns:

  • str | None: The HFID as Kind__part1__part2, or None when unavailable.

get_node_metadata

get_node_metadata(self) -> NodeMetadata | None

Return the node metadata (created_at, created_by, updated_at, updated_by).

The metadata is populated only when the parent query was executed with include_metadata=True.

Returns:

  • NodeMetadata | None: The node metadata if fetched, otherwise None.

get_kind

get_kind(self) -> str

Return the schema kind of this node.

Returns:

  • The schema kind (for example "CoreAccount").

get_all_kinds

get_all_kinds(self) -> list[str]

Return this node's kind plus all generic kinds it inherits from.

Returns:

  • list[str]: The node's own kind followed by the inherited kinds, in the order
  • declared on the schema.

is_ip_prefix

is_ip_prefix(self) -> bool

Return whether this node represents an IP prefix.

Returns:

  • True when the node kind is BuiltinIPPrefix or inherits from it.

is_ip_address

is_ip_address(self) -> bool

Return whether this node represents an IP address.

Returns:

  • True when the node kind is BuiltinIPAddress or inherits from it.

is_resource_pool

is_resource_pool(self) -> bool

Return whether this node is a resource pool.

Returns:

  • True when the node inherits from CoreResourcePool.

is_file_object

is_file_object(self) -> bool

Return whether this node inherits from CoreFileObject and supports file uploads.

Returns:

  • True when file upload/download operations are supported on this node.

upload_from_path

upload_from_path(self, path: Path) -> None

Set a file from disk to be uploaded when saving this FileObject node.

The file will be streamed during upload, avoiding loading the entire file into memory.

Args:

  • path: Path to the file on disk.

Raises:

  • FeatureNotSupportedError: If this node doesn't inherit from CoreFileObject.

upload_from_bytes

upload_from_bytes(self, content: bytes | BinaryIO, name: str) -> None

Set content to be uploaded when saving this FileObject node.

The content can be provided as bytes or a file-like object. Using BinaryIO is recommended for large content to stream during upload.

Args:

  • content: The file content as bytes or a file-like object.
  • name: The filename to use for the uploaded file.

Raises:

  • FeatureNotSupportedError: If this node doesn't inherit from CoreFileObject.

Examples:

>>> # Using bytes (for small files)
>>> node.upload_from_bytes(content=b"file content", name="example.txt")
>>> # Using file-like object (for large files)
>>> with open("/path/to/file.bin", "rb") as f:
... node.upload_from_bytes(content=f, name="file.bin")

clear_file

clear_file(self) -> None

Clear any pending file content.

get_raw_graphql_data

get_raw_graphql_data(self) -> dict | None

Return the raw GraphQL payload used to build this node.

Returns:

  • dict | None: The original GraphQL data, or None when the node was
  • constructed without payload (for example, a brand-new node).

generate_query_data_init

generate_query_data_init(self, filters: dict[str, Any] | None = None, offset: int | None = None, limit: int | None = None, include: list[str] | None = None, exclude: list[str] | None = None, partial_match: bool = False, order: Order | None = None, include_metadata: bool = False) -> dict[str, Any | dict]

Build the top-level count/edges skeleton of a GraphQL query for this kind.

The returned dict is the outer structure consumed by :meth:generate_query_data; it carries the @filters block and the empty edges.node placeholder that will later be filled by the caller.

Args:

  • filters: Filters to apply to the query.
  • offset: Pagination offset.
  • limit: Pagination limit.
  • include: Attributes or relationships to include.
  • exclude: Attributes or relationships to exclude.
  • partial_match: When True, allow partial matches on filter criteria. Defaults to False.
  • order: Ordering options to apply to the query.
  • include_metadata: When True, include node_metadata in the result. Defaults to False.

Returns:

  • dict[str, Any | dict]: The query skeleton ready to be combined with node-level
  • attributes and relationships.

Raises:

  • ValueError: If the same name appears in both include and exclude.