Creating Resources
Using
[[create_resource]]to Build the Graph
Creating Derived Resources: [[create_resource]]
This is the primary directive for creating new resources. It transforms a single origin_resource into one or more new, derived resources, forming the backbone of your architectural model. [[create_resource]] is versatile and supports several distinct patterns for generating your graph:
- Direct Derivation: Creating a new resource based on the existence of an
origin_resource(e.g., aserverfor everyapplication). This can be unconditional or made conditional withmatch_on. - Data-Driven Derivation: Creating new resources based on the data inside a property of an
origin_resource(usingcreate_from). This is a powerful convention-over-configuration pattern for creating multiple resources from a list or string. - Generation from a Data Source: Creating new resources by iterating over an abstract list of data from the header (using
create_from). This is ideal for bootstrapping parts of a graph from configuration.
The following sections explain each pattern in detail.
Unconditional Creation
This rule creates one new resource for every origin_resource.
Goal: For every application, create a corresponding server resource.
# The model reads resources of type "application".
origin_resource = "application"
server_specs = { standard_cpu = 4, large_cpu = 8 }
[[create_resource]]
resource_type = "server"
relation_type = "HOSTED_ON"
name = "{{origin_resource.name}}_server"
[create_resource.properties]
os = "Linux"
cpu_cores = "{{ server_specs.standard_cpu }}" # Access data from header
managed_by = "{{origin_resource.owner}}" # Inherit property from application
The [[create_resource]] block has several powerful options:
| Key | Mandatory | Description |
|---|---|---|
match_on |
No | An array of filter objects. The rule applies if all conditions match. |
resource_type |
Yes* | The type for the new resource. (*Optional when using create_from, which can infer the type.) |
relation_type |
Yes | The type for the relationship connecting the origin resource to the new resource. |
name |
Yes* | A template for the primary key of the new resource. (*Unless using create_from, which has defaults.) |
properties |
No | A key-value map of properties to add to the new resource. Values support templates. |
relation_properties |
No | A key-value map of properties to add to the new relationship. Values support templates. |
create_from |
No | Creates resources from a data source. Use { property = "..." } to create from a property’s value, or { list = "..." } to iterate a header variable. The resource type is determined with this priority: 1. the as key, 2. the top-level resource_type directive, 3. a default (the property or list name). The iterated item is available as {{ value }}. |
property_origin |
No | When using create_from, specifies a related resource type to read the property from. |
relation_origin |
No | When using create_from, controls the new relationship’s origin ("origin_resource" or "property_origin"). |
relation_properties: You can also add properties to the newly created relationship using a [create_resource.relation_properties] block.
[[create_resource]]
resource_type = "server"
relation_type = "HOSTED_ON"
name = "{{origin_resource.name}}_server"
[create_resource.properties]
# ... server properties
[create_resource.relation_properties]
source_app_env = "{{ origin_resource.environment }}"
managed = true
- Result: An
applicationnamedbilling-apiresults in a newservernamedbilling-api_server.(application:billing-api) -[HOSTED_ON]-> (server:billing-api_server)
This process can be visualized as follows:
graph TD
subgraph "Input & Rules"
A["Origin Resource: <code>application</code>"]
B["<code>[[create_resource]]</code> rule<br/>to create a <code>server</code>"]
end
subgraph "rescile Process"
C{"For each <code>application</code>..."}
D["1. Render <code>name</code>, <code>properties</code>, and <code>relation_properties</code> from templates"]
E["2. Create new <code>server</code> resource"]
F["3. Create <code>HOSTED_ON</code> relationship with its properties"]
end
subgraph "Output Graph"
G(application: billing-api)
H(server: billing-api_server)
G -- "HOSTED_ON<br/>{ source_app_env: 'prod', ... }" --> H
end
A & B --> C --> D --> E --> F
F --> G & H
Conditional Creation with match_on
Goal: For every application running in the prod environment, create a corresponding classification resource to label it as restricted.
# In data/models/classification.toml
origin_resource = "application"
[[create_resource]]
match_on = [
{ property = "environment", value = "prod" }
]
resource_type = "classification"
relation_type = "IS_CLASSIFIED_AS"
name = "{{origin_resource.name}}_prod"
[create_resource.properties]
level = "Restricted"
- Result: An
applicationwithenvironment: "prod"will be linked to a newclassificationresource named<app_name>_prodwithlevel: "Restricted". Applications in other environments will be ignored by this rule.
The match_on block supports several operators:
| Operator | Type | Description |
|---|---|---|
property |
String | Mandatory. The name of the property on the source resource to match against. |
value |
String, Bool, Num | Performs an exact, type-aware match on the property’s value. |
not |
String, Bool, Num | The condition is true if the property’s value is not equal to this value. |
contains |
String | For a string property, checks if it contains the substring. For an array property, checks if it contains this value as an element. |
exists |
Boolean | If true, the condition is true if the property exists and is not null/empty. If false, it’s true if the property does not exist or is null/empty. |
empty |
Boolean | If true, the condition is true if the property is missing, null, an empty string (""), or an empty array ([]). false if it has a value. |
greater |
Number | For a numeric property, checks if its value is greater than this number (>). |
lower |
Number | For a numeric property, checks if its value is less than this number (<). |
To express OR logic, use a nested or block:
origin_resource = "server"
match_on = [
{ property = "status", value = "active" }, # Must be active AND...
{ or = [ [ { property = "cores", greater = 8 } ], [ { property = "legacy_system", value = "false" } ] ] } # (...have >8 cores OR not be a legacy system)
]