Developing a Task Plugin
Relevant source files
The following files were used as context for generating this wiki page:
Task plugins in nornir-infrahub are synchronous Python functions that execute against a Nornir host to interact with Infrahub. These plugins reside in nornir_infrahub/plugins/tasks/ and allow developers to manage Infrahub artifacts, file objects, and node data within an automated workflow.
Each task relies on a specific contract: it reads the source Infrahub node from the host's data storage, specifically host.data["InfrahubNode"]. This architecture ensures that tasks reuse the authenticated SDK client established by the inventory plugin.
Sources: dev/guides/developing-a-task-plugin.md:1-5, dev/knowledge/architecture.md:8-10, dev/knowledge/infrahub-sdk-integration.md:65-68
Plugin Architecture and Data Flow
The task plugin operates as the second stage of the Nornir workflow. First, the InfrahubInventory plugin fetches nodes from Infrahub and populates the Nornir inventory. Each Nornir Host object stores its corresponding InfrahubNodeSync object. The task plugin then accesses this node to perform operations via the Infrahub SDK.
Task Execution Flow
The following diagram illustrates how a task plugin accesses Infrahub data through the Nornir Host object.
The diagram shows the sequence where a task retrieves the Infrahub node from host data and uses the bound SDK client to communicate with the API.
Sources: dev/knowledge/architecture.md:94-118, dev/guides/developing-a-task-plugin.md:17-21
Task Implementation Requirements
To develop a valid task plugin, you must follow these implementation standards:
Function Signature
A task is a plain Python function where the first parameter is task: Task. Any additional arguments required for the operation should follow the task parameter. You must type-hint all public functions, parameters, and return values.
Sources: dev/guides/developing-a-task-plugin.md:8-15, dev/guidelines/python.md:27-28
Accessing Infrahub
You access the Infrahub node via task.host.data["InfrahubNode"]. This object is an InfrahubNodeSync instance. To reach the SDK client, use the private attribute node._client. The runtime code must remain synchronous; do not use async def or asynchronous SDK calls.
Sources: dev/guides/developing-a-task-plugin.md:17-26, dev/guidelines/python.md:46-50, dev/knowledge/infrahub-sdk-integration.md:73-75
Returning Results
Every task must return a Nornir Result object. The state of the operation is communicated through specific fields:
| Field | Requirement |
|---|---|
host | Must be set to task.host. |
failed | False for success; True for failures. |
changed | True if the task mutated Infrahub state; False otherwise. |
result | Contains the payload on success or the exception string on failure. |
Sources: dev/guides/developing-a-task-plugin.md:28-36, dev/knowledge/architecture.md:84-90
Development Workflow
1. Write the Task
Define your function in a module under nornir_infrahub/plugins/tasks/. Group related tasks into the same file.
from nornir.core.task import Result, Task
def get_node_name(task: Task) -> Result:
"""Fetch the name of the host's Infrahub node."""
node = task.host.data["InfrahubNode"]
return Result(host=task.host, failed=False, result=node.name.value)
Sources: dev/guides/developing-a-task-plugin.md:8-15, AGENTS.md:75-76
2. Export the Plugin
Add the function to nornir_infrahub/plugins/tasks/__init__.py. You must add the function name to the __all__ tuple to make it available for direct import by users. Unlike inventory plugins, task plugins do not require registration in pyproject.toml entry points.
Sources: dev/guides/developing-a-task-plugin.md:42-45, dev/knowledge/architecture.md:92
3. Generate Documentation
Reference documentation is automatically generated from docstrings. Ensure your docstrings include Args:, Returns:, Raises:, and an Example: block. Run the following command to update the documentation:
invoke generate-docs
Sources: dev/guides/developing-a-task-plugin.md:14-15, tasks.py:166-224, dev/guidelines/python.md:38-41
Testing Guidelines
Task plugins require unit tests located in tests/unit/. Unit tests must not require Docker or network access.
Mocking Strategy
Use unittest.mock.MagicMock to stub the Nornir task and the Infrahub node. Assert on the properties of the returned Result object.
The sequence shows the mocking pattern where the test function stubs the task object before passing it to the plugin.
Sources: dev/guides/developing-a-task-plugin.md:47-65, dev/guidelines/testing.md:24-34
Quality Gates
Before submitting a plugin, you must run the following formatting and linting tools:
invoke format: Formats code usingruff.invoke lint: Runs all linters (ruff, pylint, ty, yamllint, rumdl).pytest: Executes unit tests.
Sources: tasks.py:22-77, dev/guides/developing-a-task-plugin.md:68-69, AGENTS.md:38-48
Summary
Developing a task plugin for nornir-infrahub involves creating synchronous Python functions that leverage the InfrahubNodeSync object stored in Nornir host data. By adhering to the Result return contract and maintaining thorough docstrings and unit tests, developers can extend the framework's capabilities while ensuring compatibility with the existing Infrahub SDK integration.