Imports und Schleifen
Konfiguration wächst: mit Imports auf Dateien verteilen, und Wiederkehrendes mit Schleifen erzeugen, statt es zu kopieren.
Imports
import "shared/logging.casc"
import "config/{base,dev}/**.casc"
import "env/${APP_ENV:dev}.casc"
import "vault://secret/base"- Ein Pfad ist relativ zur importierenden Datei.
- Klammern
{a,b}und Globs*,**werden expandiert; die Treffer laden in lexikografischer Reihenfolge. - Ein Pfad darf mit
${NAME}oder${NAME:default}die Umgebung lesen — sonst nichts, ein Import hängt also nie von der Konfiguration ab, zu der er gehört. - Ein Pfad mit
scheme://geht an einen Loader, den die Anwendung registriert. - Ein Pfad ohne Treffer ist ein Fehler, ebenso ein Import-Zyklus, gemeldet mit der ganzen Kette.
- Jede importierte Datei hat ihre eigene Versionszeile.
Ein Import mischt die Anweisungen der Datei an seiner eigenen Position ein, nach den üblichen Regeln: Späteres gewinnt. Imports gehören daher an den Anfang, damit die eigenen Anweisungen der Datei das Importierte überschreiben.
Schleifen
for <bindings> [from <template>] as <destination> { <body> }Eine Schleife schreibt ihren Rumpf einmal pro Element, jedes Mal an einen Zielpfad, der das Element meist interpoliert. Bindungen:
@x in @{list}bindet jedes Element; mindestens eine solche Bindung ist Pflicht.- Mehrere Element-Bindungen laufen ihre Listen parallel ab (gezippt, nicht jede Kombination). Die Listen müssen gleich lang sein.
- Ein nacktes
@ibindet den Index, ab 0. - Iteriert wird über
@{…}-Variablen; ein%{…}-Verweis kann keine Quelle sein, weil er erst nach dem Expandieren der Schleifen aufgelöst wird. - Bindungen existieren nur im Rumpf und verdecken äußere Variablen.
@domains = ["us-east.example.com", "eu-west.example.com"]
@ports = [8443, 8444]
for @idx, @domain in @{domains}, @port in @{ports} as endpoints."domain-@{idx}" {
url = "https://@{domain}:@{port}"
}%{"endpoints" => %{
"domain-0" => %{"url" => "https://us-east.example.com:8443"},
"domain-1" => %{"url" => "https://eu-west.example.com:8444"}}}Vorlagen
from <pfad> beginnt jeden erzeugten Block als Kopie eines anderen Schlüssels und wendet den Rumpf darauf an. Die Vorlage selbst bleibt, wo sie ist.
defaults.replica {
cpu = 1
memory = 512MiB
}
@instances = ["a", "b"]
for @name in @{instances} from defaults.replica as replicas."@{name}" {
cpu = 2
}%{"defaults" => %{"replica" => %{"cpu" => 1, "memory" => {:bytes, 536870912}}},
"replicas" => %{
"a" => %{"cpu" => 2, "memory" => {:bytes, 536870912}},
"b" => %{"cpu" => 2, "memory" => {:bytes, 536870912}}}}Ein vollständiges Beispiel
Alles zusammen, so wie ein Dienst sich konfigurieren könnte. Die Datei lädt neben einer env/dev.casc, die server.port = 4000 setzt.
#@version = 1.0
# Shared values first, so every imported file can see them.
@region = ${REGION:"eu-west"}
@*suffix = ".internal"
@shards = ["a", "b", "c"]
@weights = [3, 2, 1]
import "env/${APP_ENV:dev}.casc"
server {
host = "0.0.0.0"
port = !int(${PORT:8080})
tags = ["web", "api"]
location = (52.5200, 13.4050)
}
database {
host = "db.@{region}@{suffix}"
*password = ${DB_PASSWORD:?"DB_PASSWORD is required"}
pool_size = 10
timeout = 500ms
idle_ttl = 1h30m
cache = 512MiB
allow = [10.0.0.0/8, ::1/128]
}
logger {
level = info
format = ${LOG_FORMAT:"text" | downcase}
started = 2026-09-29T08:00:00Z
}
motd = """
Welcome to the service.
Maintenance window: Sundays.
"""
${?ENABLE_METRICS}
metrics.url = "http://%{server.host}:%{server.port}/metrics"
defaults.replica { cpu = 1, memory = 256MiB }
for @i, @shard in @{shards}, @w in @{weights} from defaults.replica as replicas."shard-@{shard}" {
weight = @{w}
index = @{i}
}
+server.tags = ["internal"]
#legacy.enabled = trueMit gesetztem DB_PASSWORD, ENABLE_METRICS=1 und LOG_FORMAT=JSON behält der Server Port 8080 (sein Block steht nach dem Import), seine Tags werden ["web", "api", "internal"], der Datenbank-Host ist "db.eu-west.internal" mit geschwärztem Passwort, das Log-Format ist "json", die Metrics-URL "http://0.0.0.0:8080/metrics", drei Replikas shard-a bis shard-c beginnen jeweils bei der Vorlage, und legacy fehlt.