Output Generation

Creating Structured Data Artifacts from Your Graph


4. Output Generation (data/output/*.toml)

Output files, located in data/output/, are the final step in the processing pipeline. They allow you to query the fully constructed graph and generate new, structured data resources. This is ideal for creating artifacts like compliance summaries, service catalogs, or inputs for other automation systems.

Unlike models, which typically create one new resource per matching origin resource, an [[output]] rule creates a single, aggregate resource. The properties of this resource are a collection of rendered templates, one for each origin_resource that matched the rule’s criteria.

File Header & Rule Structure

Key Scope Mandatory Description
origin_resource Top Level Yes The resource type to iterate over (e.g., application).
(any name) Top Level No Custom data for use in templates, such as { "json!" = "path/to/file.json" }.
[[output]] Top Level Yes An array of rules, each defining an aggregate output resource to generate.

Each [[output]] block defines a rule for creating a single aggregate resource.

Key Scope Mandatory Description
resource_type [[output]] Yes The type for the new aggregate resource. This value is also used as the resource’s primary key (name).
name [[output]] Yes A template for the property keys within the aggregate resource. It is rendered once for each matching origin_resource to create a unique key for that resource’s data.
match_on [[output]] No An array of filter objects. The rule is applied only if the origin_resource matches all conditions.
template [[output]] Yes A multiline string template that renders a JSON object. This rendered string becomes the property value associated with the key generated by the name template.

Example: Generating a Service Summary

This example generates a single service_summary resource. This resource will contain properties for every application that is on the edge network.

data/output/service_summary.toml

origin_resource = "application"

# Define some static data available to the template
output_metadata = { version = "1.1", author = "security-team" }

[[output]]
resource_type = "service_summary"
name = "summary-for-{{ origin_resource.name }}"
match_on = [
  { property = "network_zone", value = "edge" }
]
# The template renders a complete JSON object as a string.
template = """
{
  "output_author": "{{ output_metadata.author }}",
  "application_name": "{{ origin_resource.name }}",
  "owner": "{{ origin_resource.has_responsibility[0].node.name }}",
  "hosting_details": {
    "platform": "{{ origin_resource.runs_on[0].node.name }}"
  }
}
"""
  • Graph Impact:
    1. The importer finds all application resources that match the match_on criteria (e.g., app-1 and app-2).

    2. It creates a single new resource of type service_summary. This resource’s primary key (name) is also set to service_summary.

    3. For each matching application (app-1, app-2): a. The name template is rendered to create a property key (e.g., summary-for-app-1). b. The template is rendered to create a JSON string property value.

    4. The properties of this new resource will be:

      {
        "name": "service_summary",
        "summary-for-app-1": "{ \"output_author\": \"security-team\", ... }",
        "summary-for-app-2": "{ \"output_author\": \"security-team\", ... }"
      }
      
    5. Finally, a DESCRIBED_BY relationship is created from each matching application (app-1, app-2) to the new aggregate service_summary resource.

This mechanism allows you to generate structured reports or data exports that can be easily queried and retrieved via the GraphQL API.