template-model
Parses CloudFormation JSON/YAML templates into a rich semantic model. Resolves all intrinsic functions, builds a reference graph with cycle detection, and models conditions with a SAT solver. Has zero knowledge of CloudFormation resource schemas - it is purely a modeling library.
How It Works
bytes ──▶ Parse (JSON/YAML) ──▶ Resolve intrinsics ──▶ Build reference graph ──▶ SemanticModel
- Parse - Reads JSON or YAML (auto-detected), extracts all template sections (Parameters, Mappings, Conditions, Resources, Outputs, Rules, Metadata, Transforms, Globals).
- Resolve - Walks each resource and output, resolving all intrinsic functions into
ResolvedValuevariants. - Validate - Builds a reference graph, detects cycles, validates intrinsic function nesting, and emits parse-time
diagnostics (
F3004cycles,E1028undefined conditions,E1101invalid nesting,W8003tautological conditions).
Intrinsic Function Support
All CloudFormation intrinsic functions are resolved:
Ref, Fn::GetAtt, Fn::Sub, Fn::Join, Fn::Select, Fn::If, Fn::FindInMap (with optional default),
Fn::Split, Fn::Base64, Fn::Cidr, Fn::GetAZs, Fn::ImportValue, Fn::Transform, Fn::And, Fn::Or,
Fn::Not, Fn::Equals, Fn::ToJsonString, Fn::Length, Fn::ForEach.
Rules-section intrinsics: Fn::ValueOf, Fn::ValueOfAll, Fn::RefAll, Fn::Contains, Fn::EachMemberEquals,
Fn::EachMemberIn.
ResolvedValue
Each property resolves to one of these variants:
| Variant | Meaning |
|---|---|
Concrete |
Fully resolved JSON value |
List |
Array with mixed resolved/unresolved elements |
Map |
Object with mixed resolved/unresolved values |
Enum |
Set of possible values (from AllowedValues or FindInMap) |
Conditional |
Value depends on a condition (carries both branches) |
Reference |
Unresolved reference to another resource (Ref, GetAtt, Sub, DependsOn) |
Dynamic |
Cannot resolve statically (e.g., Transform output, cross-stack import) |
TypedDynamic |
Like Dynamic but carries the parameter's declared type |
SemanticModel API
Creating a Model
let bytes = read.unwrap;
let model = from_bytes.unwrap;
With configuration:
use HashMap;
use ;
let config = ParseConfig ;
let result = parse.unwrap;
let model = result.model;
Query Methods
| Method | Purpose |
|---|---|
parse(bytes, config) |
Full parse pipeline with configuration |
from_bytes(bytes) |
Parse with default config |
resource(id) |
Look up a ResolvedResource by logical ID |
resources_of_type(type_name) |
All logical IDs of a given resource type |
resolve(resource_id, path) |
Top-level property lookup |
resolve_deep(resource_id, path) |
Nested path traversal |
resolve_scenarios(resource_id, path) |
All (value, condition_map) pairs for a property |
resolve_scenarios_json(resource_id, path) |
Scenarios filtered to concrete JSON values with SAT checking |
follow_ref(resource_id, path) |
Follow a Ref/GetAtt to its target resource |
is_from_parameter(resource_id, path) |
Check if a property originates from a parameter reference |
is_from_intrinsic(resource_id, path) |
Check if a property originates from an intrinsic function |
source_location(path) |
Source span for a template path |
resource_span(resource_id, prop_path) |
Source span for a resource property |
estimated_string_length_bounds(resource_id, path) |
Shortest and longest resolved string length for constraint checking, or None when the length cannot be pinned for every possibility |
Key Fields
| Field | Type / Purpose |
|---|---|
format_version |
Option<String> - AWSTemplateFormatVersion value |
description |
Option<String> - template Description |
transforms |
Vec<String> - declared transforms |
parameters |
HashMap<String, ParameterInfo> - parsed parameter definitions |
mappings |
3-level MappingData HashMap |
conditions |
ConditionModel with SAT solver |
resources |
HashMap<String, ResolvedResource> - resolved resources with diagnostics |
outputs |
HashMap<String, ResolvedOutput> - resolved outputs |
graph |
ReferenceGraph with cycle information |
resources_by_type |
HashMap<String, Vec<String>> - logical IDs grouped by resource type |
diagnostics |
All parse-time findings, as plain ParseDefect values |
template_metadata |
Raw JSON of the Metadata section |
ParseConfig
| Field | Default | Effect |
|---|---|---|
parameters |
empty HashMap |
Parameter overrides - Ref resolves to Concrete instead of Enum/TypedDynamic |
pseudo_parameters |
all None (uses defaults) |
Override AWS::Region (us-east-1), AWS::AccountId (123456789012), AWS::Partition, etc. |
Supports AWS SAM templates with automatic handling of SAM transforms and implicit resources.
Commands
inspect (example binary)
Prints a detailed human-readable dump of the semantic model for a template or directory of templates.
cargo run -p cloudformation-validate-template-model --example inspect -- <TEMPLATE|DIR>