Skip to main content
Transformations in Infrahub allow you to process and manipulate data retrieved from GraphQL queries. They are essential components for generating artifacts, creating computed attributes, and integrating with external systems.

What are Transformations?

Transformations take data from Infrahub’s graph database (via GraphQL queries) and transform it into a desired output format. This could be:
  • Configuration files for network devices
  • JSON/YAML data structures
  • Markdown documentation
  • Custom data formats for external systems

Types of Transformations

Infrahub supports two types of transformations:

1. Jinja2 Transformations

Template-based transformations using the Jinja2 templating engine. Ideal for:
  • Generating text-based configuration files
  • Creating structured output with familiar template syntax
  • Simple data manipulation and formatting
jinja2_transforms:
  - name: device_startup
    description: "Generate startup configuration for network devices"
    query: device_startup_info
    template_path: "templates/device_startup_config.tpl.j2"

2. Python Transformations

Code-based transformations using Python classes. Ideal for:
  • Complex data manipulation and business logic
  • Integration with external APIs or libraries
  • Type-safe transformations with validation
  • Reusable transformation logic
python_transforms:
  - name: OCInterfaces
    class_name: OCInterfaces
    file_path: "transforms/openconfig.py"

Transformation Workflow

The transformation process follows these steps:
  1. Define a GraphQL query to retrieve the data you need
  2. Create a transformation (Jinja2 template or Python class)
  3. Configure the transformation in .infrahub.yml
  4. Execute the transformation (manually, via artifact generation, or through generators)

Configuration in .infrahub.yml

Transformations are defined in your repository’s .infrahub.yml file:
# Define GraphQL queries
queries:
  - name: device_startup_info
    file_path: "templates/device_startup_info.gql"
  - name: person_with_cars
    file_path: "templates/person_with_cars.gql"

# Define Jinja2 transformations
jinja2_transforms:
  - name: device_startup
    description: "Template to generate startup configuration"
    query: device_startup_info
    template_path: "templates/device_startup_config.tpl.j2"

# Define Python transformations
python_transforms:
  - name: PersonWithCarsTransform
    class_name: PersonWithCarsTransform
    file_path: "transforms/person_with_cars_transform.py"
  - name: ConvertedPersonWithCarsTransform
    class_name: ConvertedPersonWith
    file_path: "transforms/converted_person_with_cars.py"
    convert_query_response: true

Key Configuration Options

Common Options

  • name: Unique identifier for the transformation
  • query: Name or ID of the GraphQL query to execute
  • timeout: Maximum execution time (default: 10 seconds)

Jinja2-Specific Options

  • template_path: Path to the Jinja2 template file within the repository
  • description: Human-readable description of the transformation

Python-Specific Options

  • file_path: Path to the Python file containing the transform class
  • class_name: Name of the Python class implementing InfrahubTransform
  • convert_query_response: Convert GraphQL response to InfrahubNode objects (default: false)

Query Response Conversion

By default, transformations receive raw GraphQL query responses as nested dictionaries. When convert_query_response: true is set for Python transforms, the response is automatically converted to InfrahubNode objects:
# Without conversion (default)
data = {
    "TestingPerson": {
        "edges": [{
            "node": {
                "name": {"value": "John"},
                "age": {"value": 30}
            }
        }]
    }
}

# With convert_query_response: true
person = self.store.get(key=node_id, kind="TestingPerson")
name = person.name.value  # Direct attribute access
age = person.age.value

Using Transformations

Transformations can be used in several contexts:

1. Artifact Definitions

Link transformations to artifact definitions to automatically generate artifacts:
artifact_definitions:
  - name: "Startup Config for Edge devices"
    artifact_name: "startup-config"
    parameters:
      device: "name__value"
    content_type: "text/plain"
    targets: "edge_router"
    transformation: "device_startup"  # References the transformation

2. Direct Execution

Transformations can be executed programmatically via the Infrahub SDK or API.

3. Computed Attributes

Python transforms can be used to compute derived values for schema attributes.

Timeouts and Performance

Transformations have configurable timeouts to prevent long-running operations:
# In Python transform class
class MyTransform(InfrahubTransform):
    query = "my_query"
    timeout = 30  # 30 seconds
# In .infrahub.yml (overrides class default)
python_transforms:
  - name: MyTransform
    class_name: MyTransform
    file_path: "transforms/my_transform.py"
    timeout: 60
Default timeout is 10 seconds if not specified.

Best Practices

  1. Keep transformations focused: Each transformation should have a single, clear purpose
  2. Use appropriate type: Choose Jinja2 for templates, Python for complex logic
  3. Handle errors gracefully: Include error handling in Python transforms
  4. Test transformations: Write tests for your transform logic
  5. Optimize queries: Retrieve only the data you need in your GraphQL queries
  6. Set reasonable timeouts: Balance between allowing complex operations and preventing hangs
  7. Document transformations: Use clear names and descriptions

Next Steps

Build docs developers (and LLMs) love