Skip to content

Core Concepts

Effects as values

Carina treats infrastructure operations as data. Instead of immediately creating or deleting resources, it builds a Plan — a collection of Effects that describe what would happen:

EffectMeaning
CreateProvision a new resource
UpdateModify an existing resource in place
DeleteRemove a resource
ReplaceDelete and recreate a resource (when a create-only property changes)
ReadQuery an existing resource without managing it (data source)

Effects are values you can inspect before anything is executed. Running carina plan produces a Plan; running carina apply executes it.

Plan before apply

The workflow is always:

  1. Validatecarina validate . checks syntax and schema without cloud access
  2. Plancarina plan . computes the diff between desired state (.crn files) and current state
  3. Applycarina apply . executes the plan

This separation ensures you always see what will change before it happens.

Provider architecture

Providers are WASM components loaded at runtime. Each provider runs in a sandboxed environment with:

  • HTTP allow-list — providers can only call pre-approved API endpoints
  • Environment variable restriction — only explicitly passed variables are visible
  • Resource limits — memory and execution bounds

Configure a provider in your .crn file:

provider awscc {
source = 'file:///path/to/carina_provider_awscc.wasm'
version = '0.3.0'
region = 'ap-northeast-1'
}

Multiple providers can be used in the same file:

provider awscc {
region = awscc.Region.ap_northeast_1
}
provider aws {
region = aws.Region.ap_northeast_1
}

State management

Carina records managed resources in a JSON state file (carina.state.json by default). The state tracks:

  • Resource identifiers (cloud provider IDs)
  • Current attribute values
  • Resource dependencies

On each run, Carina compares the desired configuration against the state to determine what needs to change. For team usage, configure an S3 backend to share state.

DSL syntax

Carina uses .crn files with a purpose-built DSL. Key constructs:

Provider block

provider awscc {
region = awscc.Region.ap_northeast_1
}

Anonymous resources

When no other resource needs to reference it:

awscc.ec2.vpc {
cidr_block = '10.0.0.0/16'
}

Named resources with let

When you need to reference a resource’s attributes:

let vpc = awscc.ec2.vpc {
cidr_block = '10.0.0.0/16'
}
awscc.ec2.subnet {
vpc_id = vpc.vpc_id
cidr_block = '10.0.1.0/24'
}

Data sources with read

Query existing resources without managing them:

let caller = read aws.sts.caller_identity {}

Lifecycle blocks

Control resource behavior during updates and deletions:

awscc.s3.bucket {
bucket_name = 'my-bucket'
lifecycle {
force_delete = true
}
}

Available lifecycle options:

OptionDefaultEffect
force_deletefalseForce-delete the resource (e.g., non-empty S3 buckets)
create_before_destroyfalseCreate the replacement before destroying the old resource
prevent_destroyfalseBlock any plan that would destroy this resource