Architectural Models

Advanced Conditional Logic

Reference for match_on operators, OR/DNF logic, regexp matching, and expression-based conditions in rescile.

Conditional Logic

Using Advanced match_on and match_with Operators

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_with and target_resource: When used inside a match_with block 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’s origin_resource key).
    • target_resource: The candidate resource from the with set that is currently being evaluated.

    For each origin_resource, rescile iterates through every potential target_resource from the with set. The expression is evaluated for each pair. The first target_resource that 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.