Authoring desired state
This guide explains how to author the desired state in MechCloud Stateless IaC for AWS. You define your infrastructure using a clean, hierarchical YAML format that is inspired by CloudFormation but significantly simpler — no logical IDs, no !Ref, no state files, and no PascalCase. Instead, you use nesting for relationships, snake_case for properties, and ref: syntax for cross-resource references.
Key Principles
Hierarchy = Relationship
Nest resources to define parent-child relationships (e.g., subnet inside VPC).
Unique Relative Paths
Every resource must have a unique path (e.g., vpc1/subnet1/instance1). You are responsible for ensuring uniqueness.
snake_case Properties
All keys use lowercase with underscores (e.g., cidr_block, not CidrBlock).
No Parent IDs
Do not include vpc_id, subnet_id, etc. — MechCloud infers them from nesting.
Sibling References
Use ref:<name> only if both resources are in the same resources: block.
Non-Sibling References
Use ref:<full_path> to reference resources outside the current parent.
Step-by-Step: From CloudFormation to MechCloud
Let’s convert a simple CloudFormation stack into a MechCloud desired state.
CloudFormation (Original)
Resources:
VPC1:
Type: AWS::EC2::VPC
Properties:
CidrBlock: "10.2.0.0/16"
SGWeb:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref VPC1
GroupDescription: "Allow HTTP from internet"
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: "0.0.0.0/0"
SGService:
Type: AWS::EC2::SecurityGroup
Properties:
VpcId: !Ref VPC1
GroupDescription: "Allow app traffic only from web1 SG"
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 8080
ToPort: 8080
SourceSecurityGroupId: !Ref SGWeb
Subnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC1
CidrBlock: "10.2.1.0/24"
Service1:
Type: AWS::EC2::Instance
Properties:
ImageId: "ami-0bc691261a82b32bc"
InstanceType: "t3.small"
SubnetId: !Ref Subnet1
SecurityGroupIds:
- !Ref SGService
Web1:
Type: AWS::EC2::Instance
Properties:
ImageId: "ami-0bc691261a82b32bc"
InstanceType: "t3.small"
SubnetId: !Ref Subnet1
SecurityGroupIds:
- !Ref SGWebMechCloud Desired State (Converted)
resources:
- type: aws_ec2_vpc
name: vpc1
props:
cidr_block: "10.2.0.0/16"
resources:
- type: aws_ec2_security_group
name: sg_web
props:
group_description: "Allow HTTP from internet"
security_group_ingress:
- ip_protocol: tcp
from_port: 80
to_port: 80
cidr_ip: "0.0.0.0/0"
- type: aws_ec2_security_group
name: sg_service
props:
group_description: "Allow app traffic only from web1 SG"
security_group_ingress:
- ip_protocol: tcp
from_port: 8080
to_port: 8080
source_security_group_id: "ref:sg_web"
- type: aws_ec2_subnet
name: subnet1
props:
cidr_block: "10.2.1.0/24"
resources:
- type: aws_ec2_instance
name: web1
props:
image_id: "ami-0bc691261a82b32bc"
instance_type: "t3.micro"
security_group_ids:
- "ref:vpc1/sg_web"
- type: aws_ec2_instance
name: service1
props:
image_id: "ami-0bc691261a82b32bc"
instance_type: "t3.small"
security_group_ids:
- "ref:vpc1/sg_service"This template contains two security groups (sg_web and sg_service) that are declared together under the same parent resource (vpc1). sg_service needs to refer to the ID of sg_web in its ingress rule (AWS expects an actual security-group ID like sg-0123456789). Because that ID is only known once the security group is created, MechCloud lets you refer to the other resource by name using the special ref:<name> syntax.
The EC2 instances (web1 and service1) are nested under subnet1, which is a different resources: block (a different parent) than the security groups. They therefore cannot use the short ref:sg_name form (which resolves only among siblings in the same resources: block). Instead they must use the full relative path to the security group so MechCloud can uniquely locate it across the hierarchy:
source_security_group_id: "ref:sg_web"— used insidesg_servicebecausesg_webandsg_serviceare siblings undervpc1; this referencessg_web’s ID for the security-group ingress rule.security_group_ids: ["ref:vpc1/sg_web"]and["ref:vpc1/sg_service"]— used on the EC2 instances because the instances live undervpc1/subnet1. The full path (vpc1/sg_web) tells MechCloud exactly which security-group resource to resolve and then substitute its actual ID into the instance’sSecurityGroupIdsproperty.
In short: ref:<name> (short form) points to a sibling resource in the same resources: block; ref:<full_path> (path form) is required when the target resource lives under a different parent. MechCloud resolves either form at plan/apply time to the underlying AWS ID that CloudFormation/AWS expects.
Conversion Rules
Tip: Use hyphens in names for readability (e.g.,
my-vpc), but avoid spaces or special characters.
Type: AWS::EC2::VPC
→
type: aws_ec2_vpc
CidrBlock
→
cidr_block
VpcId: !Ref MyVPC
→
Remove — use nesting
Logical ID MyVPC
→
name: my-vpc
SecurityGroupIds: [!Ref MySG]
→
security_group_ids: ["ref:my-sg"]
SecurityGroupIngress SourceSecurityGroupId
→
security_group_ingress source_security_group_id
SecurityGroupIngress SourceSecurityGroupOwnerId
→
security_group_ingress source_security_group_owner_id
Notes and clarifications for the example template
snake_caseis mandatory in MechCloud YAML. MechCloud translates these property names to the AWS/CloudFormation property names when making provider calls (for examplesource_security_group_id→SourceSecurityGroupId).There are two kinds of
ref:forms used in the example:Short name (sibling) form:
ref:<name>— used when one resource needs the ID of another resource that is declared together under the same parent. In the example bothsg_webandsg_serviceare siblings undervpc1, sosg_serviceuses:source_security_group_id: "ref:sg_web"MechCloud resolves
ref:sg_webat plan/apply time to the actual security-group ID (for AWS).Full-path (non-sibling) form:
ref:<relative_path>— used when the referencing resource is in a different part of the hierarchy (different parent). In the example EC2 instances live undervpc1/subnet1, so they must reference the security groups by full relative path:security_group_ids: - "ref:vpc1/sg_web" - "ref:vpc1/sg_service"The full path disambiguates the target resource for MechCloud so it can resolve it to the AWS GroupId.
Use
source_security_group_owner_idwhen referencing a security group that belongs to a different AWS account (this maps to CloudFormationSourceSecurityGroupOwnerId).Always ensure the
ref:target resolves to a security-group resource (so MechCloud can substitute the runtime GroupId). If aref:points to a non-existent path/name, plan will fail with an unresolved reference error.
Resource Paths (Must Be Unique)
Each resource gets a unique relative path based on its nesting within the hierarchy.
This path allows MechCloud to resolve references (ref:) precisely at plan and apply time.
VPC
vpc1
Security Group — Web
vpc1/sg_web
Security Group — Service
vpc1/sg_service
Subnet
vpc1/subnet1
Instance — Web
vpc1/subnet1/web1
Instance — Service
vpc1/subnet1/service1
Each resource’s path must be unique across the entire desired state file.
Next Steps
Select Execution Context At the top of the MechCloud console, select the execution context for your operation:
Team — e.g.,
Academy (User 2)AWS Account — e.g.,
Test1 (User 2)Region — e.g.,
Europe (Ireland)Context — e.g.,
app1-dev1
Generate the Plan Click Plan to generate an execution plan. MechCloud compares the desired state (defined in YAML) with the actual AWS infrastructure and determines which resources require changes.
Review Plan Actions Each resource in the plan shows an
actionindicating how MechCloud will reconcile it:create— the resource does not exist and will be created.update— the resource exists but properties differ and will be updated.delete— the resource exists but is no longer in the desired state and will be removed.recreate— the resource will be deleted and then created again (for non-updatable property changes).none— the resource is already in the desired state; no action required.
Apply the Plan (When Changes Exist)
The Apply button becomes visible only when the plan includes at least one resource whose
actionis notnone.Click Apply to provision or update resources as per the plan.
MechCloud will execute the required operations and bring your AWS environment to match the desired state.
Verify Post-Apply State
Once the apply completes, click Plan again to re-run the comparison.
If all resources now display
action: none, the desired and actual states are in sync.In this case, the Apply button will not be visible because no further changes are required.
Handle Errors (If Any)
If any errors occur during the apply step, re-run Plan to refresh dependencies and reconcile state.
Then click Apply again to retry provisioning with the updated plan.
Last updated
Was this helpful?