Conditional Logic
Using Advanced
match_onandmatch_withOperators
Advanced Conditional Logic with match_on and match_with
The match_on key is used in both models and compliance files to apply rules conditionally. While simple equality
checks are common, it supports a range of operators and complex logical structures.
Match Operators
A match_on or match_with block is an array of condition objects. All conditions in the array must be true for the rule to apply
(AND logic). Each condition object can use one of the following operators:
| Key | Type | Description |
|---|---|---|
property |
String | Mandatory. The name of the property to match against. |
value |
String, Bool, Num | Performs an exact match. Supports Tera templating. |
not |
String, Bool, Num | Matches if the property’s value is not equal to this. Supports Tera templating. |
contains |
String | For string properties, checks for a substring. For array properties, checks if the array contains this value as an element. Supports Tera templating. |
excludes |
String | For string properties, checks for a substring. For array properties, checks if the array does not contains this value as an element. Supports Tera templating. |
exists |
Boolean | If true, matches if the property exists and is not empty/null. If false, matches if it does not exist or is empty/null. |
empty |
Boolean | If true, matches if the property is missing, null, an empty string (""), or an empty array ([]). |
greater |
Number | For numeric properties, checks if the value is > this number. |
lower |
Number | For numeric properties, checks if the value is < this number. |
expression |
String | A Tera expression that must render to the exact string "true" to match. Unlocks complex inline logic using and, or, and tests. It is evaluated in addition to any other keys present in the same object. |
regexp |
String | For string properties, checks if its value matches the provided regular expression. The value supports Tera templating. |
Complex Logic with or
To model OR conditions, you can use a special or block inside the match_on or match_with array. There are two supported formats for this block.
1. Simplified OR List
For simple OR conditions where any one of a list of criteria should match, you can provide a flat list of condition objects.
Structure: { or = [ { condition A }, { condition B } ] } (Equivalent to A OR B)
match_on = [
{ property = "status", value = "active" },
{ or = [
{ property = "function", value = "infrastructure" },
{ property = "function", value = "platform" }
]
}
]
2. Disjunctive Normal Form (DNF)
For complex logic like (A AND B) OR (C AND D), use a nested list structure. Each inner array is an AND-group, and the outer array connects them with OR logic.
Structure: { or = [ [ { A }, { B } ], [ { C }, { D } ] ] }
Goal: Create a resource if an application is active AND (it has more than 8 cores OR it is not a
legacy_system).
data/models/advanced_sla.toml
origin_resource = "application"
[[create_resource]]
match_on = [
# First top-level AND condition
{ property = "status", value = "active" },
# Second top-level AND condition, which contains an OR block
{ or = [
[ { property = "cores", greater = 8 }, { property = "memory", greater = 192 } ], # First OR case
[ { property = "legacy_system", value = "false" } ] # Second OR case
]
}
]
resource_type = "sla"
relation_type = "HAS_SLA"
name = "gold_sla_for_{{origin_resource.name}}"
[create_resource.properties]
level = "Gold"
This powerful combination of AND and OR logic allows you to model highly specific architectural and compliance rules declaratively.
Matching with Regular Expressions (regexp)
For powerful string pattern matching, the regexp operator allows you to use regular expressions. This is more
flexible than contains and more concise than a complex expression.
The regular expression is evaluated using Rust’s regex crate, which supports a large subset of PCRE features.
Simple Example: Static Pattern Matching
The most common use is to match against a fixed pattern.
Goal: Create a special network policy only for resources whose fqdn property ends in .internal.example.com.
[[create_resource]]
match_on = [
{ property = "fqdn", regexp = "\\.internal\\.example\\.com$" }
]
resource_type = "internal_network_policy"
name = "internal_policy_for_{{origin_resource.name}}"
- The
$is an anchor that matches the end of the string. - The
.characters are escaped with double backslashes (\\.). This is because the value is a TOML string, where a single backslash is an escape character.\\in TOML becomes a literal\for the regex engine.
Complex Example: Dynamic Pattern with Templating
The regexp operator supports Tera templating, allowing you to build dynamic regular expressions based on properties of the resource or its relatives.
Goal: Tag servers as “regional” if their hostname follows a pattern that includes the region of their parent subscription. For example, if a subscription has region = "us-west-2", this rule should match a linked server with hostname "app-db-us-west-2-az1".
This example assumes server resources are linked to subscription resources.
data/models/tagging.toml
origin_resource = "server"
[[create_resource]]
# Creates a 'regional_deployment' tag for any server whose hostname contains
# the region code of its parent subscription.
match_on = [
# The regex pattern is built dynamically.
# If origin_resource.subscription.region is "us-west-2", the regex becomes ".*-us-west-2-.*".
{ property = "hostname", regexp = ".*-{{ origin_resource.subscription.region }}-.*" }
]
resource_type = "tag"
relation_type = "HAS_TAG"
name = "regional_tag_for_{{origin_resource.name}}"
[create_resource.properties]
value = "regional_deployment"
This combination of regexp and templating enables highly contextual pattern matching that adapts to the relationships within your graph.
Ultimate Flexibility with expression
For conditions that are too complex for the standard operators or or blocks, the expression key provides direct
access to the full power of the Tera templating engine. It allows you to write a single,
self-contained condition with arbitrary logic.
Key Characteristics:
-
Single Tera Expression: The value is a string containing a Tera template.
-
Boolean Evaluation: The rule is considered a match only if the template renders to the exact string
"true". Any other output (including an empty string) is a non-match. -
Full Power: Use any of Tera’s features, including tests (
is containing), logic (and,or), and mathematical comparisons. -
It is evaluated as an additional AND condition alongside any other keys in the same object (like
property,value,contains). -
Context in
match_withandtarget_resource: When used inside amatch_withblock in a[[link_resources]]rule, the expression gains access to two special variables for powerful cross-resource comparisons:origin_resource: The resource from the main iteration set (defined by the file’sorigin_resourcekey).target_resource: The candidate resource from thewithset that is currently being evaluated.
For each
origin_resource,rescileiterates through every potentialtarget_resourcefrom thewithset. The expression is evaluated for each pair. The firsttarget_resourcethat results in a"true"render is considered a match.
Goal: Create a high-performance resource only if the origin resource’s name contains 'xXx' AND its core count is
greater than 8.
[[create_resource]]
match_on = [
{ property = "name", contains = "xXx", expression = "{% if origin_resource.cores > 8 %}true{% endif %}" }
]
resource_type = "high_performance_node"
name = "hp_node_for_{{origin_resource.name}}"
[create_resource.properties]
performance_tier = "extreme"
Goal (in link_resources): For each request (origin_resource), find a server (with resource) that has enough free memory to satisfy the request. The target_resource variable refers to the server being checked.
[[link_resources]]
with = "server"
match_with = [
{ expression = "{% if origin_resource.requested_memory < target_resource.free_memory %}true{% endif %}" }
]
Advanced Matching on JSON with jmespath
When a resource property contains complex structured data (like a JSON object or array), you can use the expression operator combined with the jmespath filter for powerful, targeted matching.
The condition is considered true if the jmespath query returns a “truthy” result. In JMESPath, truthy values are anything other than null, false, an empty string, an empty array, or an empty object. This means a query that finds one or more matching elements will cause the rule to apply.
Goal: Apply a backup policy only to databases that have a tag with key of “env” and value of “prod”. The tags are stored in a nested JSON structure available in a global variable.
database_details = {
"db-prod-01" = { "tags" = { "tags" = [{ "key" = "env", "value" = "prod" }] } },
# ...
}
[[create_resource]]
match_on = [
# The expression is true if the JMESPath query returns a non-empty result.
{ expression = "{% if database_details[origin_resource.name].tags | jmespath(query=`tags[?key == 'env' && value == 'prod']`) %}true{% endif %}" }
]
resource_type = "backup_policy"
name = "backup_policy_for_{{ origin_resource.name }}"
In this example, the jmespath filter queries the nested tag data. The surrounding {% if ... %} block checks if the filter returns a non-empty array. If it does, the expression renders “true”, and the rule is applied. This pattern provides a flexible way to match on arbitrarily complex data structures.