Reference

Tera Function & Filter Reference

Complete reference for Tera functions and filters added by rescile, including CIDR helpers, JMESPath, HMAC signing, and base64 encoding — with examples.

Tera Function & Filter Reference

Custom functions and filters added by rescile to the standard Tera templating engine.

rescile extends Tera with custom logic for infrastructure modeling. These can be used in any templated string value across models/, compliance/, and output/ files. For an overview of how templating fits into the overall data context, see Templating & Data.


Functions

counter(key=value)

Returns a stateful, zero-based incrementing integer for a given unique key. Each unique key has its own independent counter, reset on every importer run. This is more powerful than the built-in origin_resource_counter variable when you need independent counters per group.

Parameter Description
key A value uniquely identifying the counter. Can be a string, number, boolean, an object with a name property, or an array of such types (which will be sorted and joined).

Example — allocate /24 subnets per region, restarting the index for each:

origin_resource = "department"

[[create_resource]]
resource_type = "subnet"
relation_type = "HAS_SUBNET"
[create_resource.properties]
# For departments in '10.0.0.0/16', counter goes 0, 1, 2...
# For departments in '10.1.0.0/16', counter independently goes 0, 1, 2...
subnet_cidr = "{{ origin_resource.region[0].cidr | cidr_nth_subnet(prefix=24, nth=counter(key=origin_resource.region)) }}"

calculate_cidr(ips=[...])

Calculates the smallest possible CIDR block that contains a given list of IP addresses.

Parameter Description
ips An array of strings, each a valid IPv4 or IPv6 address.

Example — summarize server IPs into a containing CIDR:

origin_resource = "application"

[[create_resource]]
resource_type = "network_summary"
name = "summary_for_{{ origin_resource.name }}"
[create_resource.properties]
# map(attribute='ip_address') extracts each server's IP, then calculate_cidr wraps them.
# For ips=["10.1.5.10", "10.1.5.25"] → "10.1.5.0/27"
summary_cidr = "{{ calculate_cidr(ips=origin_resource.server | map(attribute='ip_address')) }}"

allocate_subnets(cidr="string", host_map={...})

Dynamically plans a subnet layout. Takes a parent CIDR block and a map of subnet names to required host counts. Calculates the smallest possible subnet for each entry and allocates them sequentially. Keys are sorted deterministically before allocation.

Parameter Description
cidr The parent CIDR block from which to allocate.
host_map A dictionary mapping subnet names to required host counts.

Example — auto-plan a three-tier network layout:

origin_resource = "network"

required_subnets = { dmz = 10, app = 100, db = 50 }

[[create_resource]]
match_on = [{ property = "name", value = "core_network" }]
resource_type = "network_layout"
name = "layout_for_{{ origin_resource.name }}"
[create_resource.properties]
# Keys are sorted (app, db, dmz) before allocation for determinism.
# For cidr="10.0.0.0/16":
# → { "app": "10.0.0.0/25", "db": "10.0.0.128/26", "dmz": "10.0.0.192/28" }
allocated_cidrs = "{{ allocate_subnets(cidr=origin_resource.cidr, host_map=required_subnets) }}"

The result is a JSON object that can be used in subsequent models to create the actual subnet resources.


Filters

cidr_nth_subnet(prefix=int, nth=int)

Extracts a specific zero-indexed subnet from a parent CIDR block. The prefix parameter is the absolute prefix length of the desired subnet, not the number of bits to add.

Parameter Description
prefix Absolute target prefix length (e.g., 24 for /24 subnets). Must be larger than or equal to the parent CIDR’s prefix.
nth Zero-based index of the subnet to select.

Example — allocate ordered /24 subnets from a /16 block:

origin_resource = "department"

[[create_resource]]
resource_type = "subnet"
relation_type = "HAS_SUBNET"
[create_resource.properties]
# origin_resource_counter is 0 for the first department, 1 for the second, etc.
# Result: "10.0.0.0/24", "10.0.1.0/24", "10.0.2.0/24", ...
subnet_cidr = "{{ '10.0.0.0/16' | cidr_nth_subnet(prefix=24, nth=origin_resource_counter) }}"

cidr_split_n(n=int)

Splits a CIDR block into n equal-sized subnets. The count is rounded up to the next power of two. Returns an array of CIDR strings.

Parameter Description
n Desired number of subnets. Rounded up to next power of two.

Example — divide a /16 into 4 equal /18 subnets:

origin_resource = "vpc"

[[create_resource]]
resource_type = "network_layout"
name = "layout_for_{{ origin_resource.name }}"
[create_resource.properties]
# For origin_resource.cidr = "10.10.0.0/16":
# → ["10.10.0.0/18", "10.10.64.0/18", "10.10.128.0/18", "10.10.192.0/18"]
regional_subnets = "{{ origin_resource.cidr | cidr_split_n(n=4) }}"

jmespath(query="string")

Executes a JMESPath query against a JSON-compatible value (object, array, or string). Returns the query result. If no match is found, returns an empty value (falsy).

This is useful both for extracting nested data in templates and for filtering in match_on expressions. See Matching on JSON with jmespath for the match_on usage pattern.

Parameter Description
query A valid JMESPath expression string.

Example — extract a nested property:

[create_resource.properties]
# origin_resource.config = { "storage": { "class": "premium-ssd" } }
storage_class = "{{ origin_resource.config | jmespath(query='storage.class') }}"
# → "premium-ssd"

Example — pre-filter JSON data in the file header:

# Load SLAs and select only the first critical-level policy before the loop starts.
critical_sla = { "json!" = "slas.json", jmespath = "policies[?level == 'critical'] | [0]" }

[[create_resource]]
[create_resource.properties]
backup_frequency = "{{ critical_sla.backup_frequency }}"

Example — match_on expression with jmespath:

[[create_resource]]
match_on = [
  {
    expression = """
      {%- set tags = origin_resource.config
                     | jmespath(query="tags[?key == 'env' && value == 'prod']") -%}
      {% if tags %}true{% endif %}
    """
  }
]
resource_type = "backup_policy"
name = "backup_policy_for_{{ origin_resource.name }}"

select(from="string", match="key=value")

Filters an array of objects by a condition and extracts a specific property from each matching object. Can also operate on a single object, returning the property value if the condition matches or null otherwise.

Parameter Description
from Property name to extract from matching objects. Supports dot-notation (e.g., "config.name").
match Condition in "key.path=value" format. Dot-notation supported. If the target property is an array, the filter checks whether it contains the value.

Example — extract names of active servers:

[create_resource.properties]
# origin_resource.server = [{name: "srv1", status: "active"}, {name: "srv2", status: "inactive"}]
# select extracts 'name' where status=active → ["srv1"]
# join converts the array → "srv1"
active_servers = "{{ origin_resource.server | select(from='name', match='status=active') | join(sep=',') }}"

Example — single object:

# origin_resource.primary_db = { name: "db1", role: "primary" }
primary_db_name = "{{ origin_resource.primary_db | select(from='name', match='role=primary') }}"
# → "db1"

intersect(with=[...])

Returns a new array containing only elements present in both the input array and the with array. Duplicates are removed from the result.

Parameter Description
with The second array to intersect with.

Example — find common tags:

[create_resource.properties]
# application.tags = ["frontend", "web", "prod"]
# server.tags      = ["web", "api", "prod"]
# → ["web", "prod"]
common_tags = "{{ origin_resource.tags | intersect(with=origin_resource.server[0].tags) }}"

regexp(expr="s/pattern/replacement/flags")

Applies a sed-style regular-expression substitution to a string. The delimiter is the character immediately following the leading s and can be any character (commonly / or |).

Parameter Description
expr (alias: pattern) A sed substitution expression, e.g. s/foo/bar/gi.

Flags:

Flag Meaning
g Global — replace all occurrences, not just the first.
i / I Case-insensitive matching.

Replacement syntax:

Token Expands to
\1\9 Captured group N.
& Entire match.
\n \t \r Newline, tab, carriage return.
\\ Literal backslash.
\<delim> Literal delimiter character.

Example — strip a domain suffix:

[create_resource.properties]
# "WebServer01.corp.example.com" → "webserver01"
short_name = "{{ origin_resource.fqdn | regexp(expr='s/\\.corp\\.example\\.com$//i') | lower }}"

Example — backreferences:

[create_resource.properties]
# "10.0.0.0/16" → "net_10.0.0.0_prefix16"
label = "{{ origin_resource.cidr | regexp(expr='s/([0-9.]+)\\/([0-9]+)/net_\\1_prefix\\2/') }}"

Example — custom delimiter to avoid escaping slashes:

[create_resource.properties]
# "a/b/c" → "a-b-c"
safe_path = "{{ origin_resource.path | regexp(expr='s|/|-|g') }}"

Tip: When your pattern or replacement contains the / character, use an alternative delimiter (like |, #, or @) to keep the expression readable: s|old/path|new/path|g instead of s/old\/path/new\/path/g.


sha256

Computes the SHA-256 hash of a value. Strings are hashed directly; complex types (arrays, objects) are first serialized to JSON. Returns a lowercase hexadecimal string.

Example — create a unique, deterministic ID:

[create_resource.properties]
# Combine address and port into a stable hash to avoid name collisions.
unique_id = "{{ [origin_resource.address, origin_resource.port] | json_encode | sha256 }}"

base64_encode

Encodes a value using standard Base64. Strings are encoded directly; complex types are serialized to JSON first.

Example — encode a startup script for cloud-init:

[create_resource.properties]
user_data = "{{ origin_resource.startup_script | base64_encode }}"

hmac_sha256(key="secret", encoding="hex"|"base64")

Computes HMAC-SHA256 of a value using the given key. Returns a hex string by default; pass encoding="base64" for Base64 output.

Parameter Description
key The secret key for the HMAC computation. Supports {{ env.VAR }} expansion.
encoding Output encoding: "hex" (default) or "base64".

This filter is primarily used in proxy.toml for request signing, but is available everywhere.

Example — sign a payload for API authentication:

[create_resource.properties]
signature = "{{ origin_resource.payload | hmac_sha256(key=env.API_SECRET, encoding=\"base64\") }}"

Example — Exoscale API request signing in proxy.toml:

# app/proxy.toml
[[route]]
path = "/api/exoscale"
target = "https://api-ch-dk-2.exoscale.com/v2"
forward_headers = ["Accept", "User-Agent"]
[route.inject_headers]
"Content-Type" = "application/json"
"Authorization" = """
{%- set expires = request.timestamp + 600 -%}
{%- set msg = request.method ~ " " ~ request.path ~ "\n" ~ request.body ~ "\n" ~ request.query_values ~ "\n\n" ~ expires -%}
{%- set sig = msg | hmac_sha256(key=env.EXOSCALE_API_SECRET, encoding="base64") -%}
EXO2-HMAC-SHA256 credential={{ env.EXOSCALE_API_KEY }},expires={{ expires }},signature={{ sig -}}
"""

For the full proxy configuration reference, see proxy.toml Reference.


Standard Tera Features Used in rescile

In addition to the custom extensions above, rescile configurations make heavy use of standard Tera features. The full list is in the Tera documentation.

Commonly Used Built-in Filters

Filter Example Description
upper / lower {{ name | upper }} Change string case.
replace(from, to) {{ name | replace(from=".", to="-") }} Replace substrings.
default(value) {{ x | default(value="n/a") }} Fallback when value is undefined.
split(pat) {{ v | split(pat=".") | first }} Split a string and pick an element.
join(sep) {{ arr | join(sep=",") }} Join array elements into a string.
map(attribute) {{ servers | map(attribute="ip") }} Extract one property from each object in an array.
json_encode {{ obj | json_encode | safe }} Serialize to JSON string (use safe to avoid escaping).
length {{ items | length }} Count items in an array or string.
first / last {{ arr | first }} Pick first or last array element.

Conditionals and Loops

[create_resource.properties]
# Inline conditional
sla = "{% if origin_resource.environment == 'prod' %}Gold{% else %}Silver{% endif %}"

# Loop to build a comma-separated list
tag_list = "{% for t in origin_resource.tags %}{{ t | upper }}{% if not loop.last %},{% endif %}{% endfor %}"

# Default filter to avoid undefined errors
region = "{{ origin_resource.region | default(value='us-east-1') }}"

Traversing relationships in templates uses dot notation. Multi-valued relations are arrays:

[create_resource.properties]
# First related database's version
db_version      = "{{ origin_resource.database[0].version }}"
# Property on the connecting edge
connection_type = "{{ origin_resource.database[0]._relation.label }}"
# Collect all volumes from related applications
volumes = "{{ origin_resource.application | map(attribute='volume') | json_encode | safe }}"

Quick Reference

Name Type Signature Description
counter Function counter(key=value) Stateful per-key incrementing integer.
calculate_cidr Function calculate_cidr(ips=[...]) Smallest CIDR containing given IPs.
allocate_subnets Function allocate_subnets(cidr="...", host_map={...}) Dynamic subnet planning from host counts.
cidr_nth_subnet Filter | cidr_nth_subnet(prefix=int, nth=int) Extract the Nth subnet of a given prefix size.
cidr_split_n Filter | cidr_split_n(n=int) Split CIDR into N equal subnets.
jmespath Filter | jmespath(query="string") JMESPath query against a JSON structure.
select Filter | select(from="prop", match="k=v") Filter array and extract a property.
regexp Filter | regexp(expr="s/pat/repl/flags") Sed-style regex substitution.
intersect Filter | intersect(with=[...]) Common elements of two arrays.
sha256 Filter | sha256 SHA-256 hex hash.
base64_encode Filter | base64_encode Base64 encoding.
hmac_sha256 Filter | hmac_sha256(key="...", encoding="hex"|"base64") HMAC-SHA256 signature.