AWS Plugin Release Notes

0.1.8

Fix: ECS Service creation no longer fails with target group <arn> does not have an associated load balancer when the Service and its Listener are scheduled together in the same apply. The plugin now treats that specific CloudControl error (InvalidRequest + matching message text, on Create operations only) as a transient in-progress state; the PluginOperator's existing status-poll loop absorbs the race until the Listener finishes wiring the target group to the load balancer. No PKL change needed — direct tg.res.targetGroupArn references keep working and don't have to be rewritten through listener.res.targetGroupArn to avoid the race.

Fix: Inverts the destroy edge between an ECS Service and its target groups via attachesTo field hints on Service.LoadBalancer.targetGroupArn and Service.VpcLatticeConfiguration.targetGroupArn. AWS rejects target-group deletion while a Service is still attached; without the annotation, the Service tore down in parallel with the listener chain, and any plugin-target driving CRUD through the Service's listener URL (Grafana, Loki, Tempo, and similar) wedged mid-tear-down with no URL backing it. With the annotation, the Service is destroyed before its target group. Requires formae 0.85.0+ to take effect: 0.84.0 agents silently ignore the annotation (the plugin still installs and every other fix applies, but the destroy-edge inversion no-ops). The plugin's minFormaeVersion stays at 0.84.0 deliberately — sibling plugins built against the same SDK family work fine on 0.84.0 and forcing an agent upgrade for one annotation isn't worth the disruption.


0.1.7

New: Amazon SES support for outbound transactional email. AWS::SES::EmailIdentity covers verified sending domains or addresses (with bundled MAIL FROM, feedback, and Easy DKIM attributes). AWS::SES::ConfigurationSet and AWS::SES::ConfigurationSetEventDestination route bounce/complaint/delivery events to SNS, Kinesis Firehose, EventBridge, or CloudWatch — exactly one of the four destination types is enforced at PKL evaluation time, so bad shapes fail at pkl eval rather than at apply time. AWS::SES::EmailIdentityVerification is a polling gate downstream consumers depend on for send-readiness; it sits between the identity (and the DNS records that verify it) and any resource that needs to send mail, breaking the apply-time deadlock where verification needs DNS, DNS depends on the identity, and the identity can't wait on either.

New: EmailIdentity.res.requiredDnsRecords is a typed listing resolvable that exposes the DNS records SES expects — 3 DKIM CNAMEs, plus an MX and SPF TXT for MAIL FROM when configured. A forma drives Route53 (or any DNS plugin) directly off id.res.requiredDnsRecords.at(N).name and .values, with no manual token extraction. See examples/ses-basic/main.pkl in the plugin repo for the full pattern. Terraform, Pulumi, and Crossplane all force users to extract verification_token/dkim_tokens[] strings and hand-author the records; this is the first IaC tool to wire them automatically.

Fix: AWS::EC2::PlacementGroup's spreadLevel is now marked hasProviderDefault. AWS auto-populates SpreadLevel after a partition-strategy create even when not specified, which previously caused replace flows (where the user switches strategy from spread to partition) to fail with Property SpreadLevel is not expected and not a provider default. The field stays createOnly.

Fix: Container-level changes on AWS::ECS::TaskDefinition are no longer silently dropped from the diff. 19 user-canonical sub-fields on ContainerDefinition — including environment, portMappings, mountPoints, secrets, command, entryPoint, dependsOn, extraHosts, and dockerLabels — were previously annotated hasProviderDefault, which symmetrically stripped them from both the desired and actual sides before comparison. Any real change to those fields produced an empty plan on formae apply, forcing operators into out-of-band aws ecs register-task-definition workarounds (which then showed up as drift on the next reconcile). The annotation is now scoped to the genuinely cloud-defaulted scalars (cpu, essential, versionConsistency).

Fix: AWS::Lambda::LayerVersion's compatibleArchitectures, compatibleRuntimes, and description are now marked hasProviderDefault. AWS Read returns empty values for these when the user omits them in PKL, and because every LayerVersion field is createOnly, the resulting phantom drift would schedule a destroy + create on every reapply.


0.1.6

Fix: Updating an AWS::Lambda::EventInvokeConfig no longer fails with Model validation failed: required key [Destination] not found. CloudControl's update handler for this resource type re-validates the full server-side state on every patch, even fields the patch doesn't touch — and AWS materialises empty DestinationConfig.OnFailure / OnSuccess sub-objects into the response on Read whether or not the caller ever set them, which then fail the schema's "if present, Destination is required" rule. Updates that only changed MaximumRetryAttempts or MaximumEventAgeInSeconds would still get rejected on the server side. Updates now route through the Lambda UpdateFunctionEventInvokeConfig API directly, which has no such cross-field re-validation.

Fix: ELBv2 Listener.defaultActions[*].forwardConfig and ECS Cluster.clusterSettings are now marked hasProviderDefault. ELBv2 derives ForwardConfig (target groups + stickiness defaults) on Read from the action's TargetGroupArn when the user specifies a simple forward target, and ECS populates clusterSettings with default entries like containerInsights: disabled when none are configured. Without the annotations, every reapply emitted a no-op patch on these fields that surfaced as a spurious update.


0.1.5

Per-field config mutability: The profile field is now mutable — changing it updates the target in place without recreating resources. The region field remains immutable; changing it triggers a full target replace as before. See Per-field config mutability for details.

New: Complete EKS resource coverage. Addon, AccessEntry, FargateProfile, PodIdentityAssociation, and IdentityProviderConfig are now first-class resources alongside Cluster and Nodegroup, enabling end-to-end EKS cluster management (including discovery of cluster-child resources) from a single forma.

New: ECS ExpressGatewayService support. Express Gateway services can now be managed through formae. Uses the native ECS SDK because the CloudControl handler for this type is broken server-side.

Fix: ECS Service and TaskSet discovery no longer spam InvalidRequestException: Missing Or Invalid ResourceModel property errors on every cycle. Service is now discovered as a child of Cluster (its list handler requires a Cluster filter), and TaskSet is enumerated via the ECS SDK's DescribeServices because its CloudControl list handler demands an Id and is effectively a Read.

New: ALB Listener URL resolvable — Listeners now expose a computed url property that combines the parent ALB's DNS name with the Listener's protocol and port. Use listener.res.url to wire load balancer endpoints into target configs without manual URL construction.

Fix: TaskDefinition was missing its resolvable wiring — taskDef.res.taskDefinitionArn now works as expected, enabling ECS Services to reference task definitions via resolvables.

Fix: EFSVolumeConfiguration.filesystemId now accepts resolvable references, so ECS tasks can reference EFS filesystems created in the same forma.

Fix: VPCGatewayAttachment now exposes resolvable references (igwAttach.res.internetGatewayId). Routes should reference the gateway ID through the attachment — not the gateway directly — to ensure correct destroy ordering. Without this, destroying a stack with Routes and an IGW attachment could hang for hours because formae tried to detach the IGW before deleting the routes that use it.

Fix: Listener now exposes listener.res.targetGroupArn, resolving to the target-group ARN attached via the listener's first default action. ECS Services (and any other consumer that needs the target group already wired to the load balancer) should reference this instead of tg.res.targetGroupArn — without it, AWS rejects ECS service creation with "target group does not have an associated load balancer" when formae schedules the service before the listener attaches the TG. Same pattern as igwAttach.res.internetGatewayId for routes/IGW.

Fix: ~225 reference-bearing properties (IDs, ARNs, names) across 77 schema files now accept formae.Resolvable, and all resources with Resolvable classes now have hidden res wired up.

Fix: Patch-mode updates to resources with optional nested objects (for example, Lambda EventInvokeConfig.DestinationConfig) could fail with CloudControl errors like required key [Destination] not found when the nested object was empty. The plugin now strips empty sub-objects from replace operations the same way it already did for add operations, so these updates succeed.

Fix: Reapplying an unchanged forma containing an ECS Service no longer spuriously replaces the service. AWS fills in default port-mapping values on awsvpc tasks that the user didn't set, which previously made the planner think the task definition had changed. Those fields are now recognised as provider-populated and ignored during comparison. Requires formae 0.84.0.

Fix: EFSVolumeConfiguration.rootDirectory no longer causes phantom replacements. CloudControl returns RootDirectory as "/" even when it was never set, which made the planner see a change on every reapply.

Fix: ECS Service and TaskSet no longer produce spurious replacements when the Cluster field is referenced via ARN. CloudControl normalises the Cluster to a short name on Read, which flipped the createOnly field and triggered a full replace. ARN-vs-short-name differences are now normalised before comparison.

Fix: TaskSet updates no longer hang indefinitely. CloudControl's update handler for TaskSet Scale never returns; a custom ECS SDK update provisioner is used instead.


0.1.4

Fix: Route53 RecordSets with the same name but different types (e.g., SOA and NS for the same domain) were discovered with identical labels, causing duplicate entries that churned on every sync cycle. Labels now include the record type, producing unique entries like example.com.-SOA and example.com.-NS.

Fix: Resources with composite CloudControl identifiers (e.g., ECS Services, Lambda EventInvokeConfigs) could show up as duplicates in inventory — one from the initial create and another from discovery. This happened because AWS CloudControl returns full ARNs during create but short names during list. Identifiers are now normalized so the resource created by apply and the resource found by discovery are correctly recognized as the same thing.

Fix: Discovery of subnet route table associations could cause apply commands to get permanently stuck. AWS returns VPC-level (main) route table associations in discovery results that cannot be read, which triggered a cascade of internal failures. These associations are now filtered out during discovery.

Fix: Updates to resources with provider-default nested objects (e.g. Lambda EventInvokeConfig destination config) could fail with CloudControl validation errors. Empty nested objects left behind after stripping unused fields were not being removed, causing required-field violations.


0.1.3

Conformance test coverage for 88 resource types across EC2, ECS, EKS, ELBv2, Elastic Beanstalk, Lambda, API Gateway, RDS, Route53, S3, SQS, IAM, KMS, EFS, ECR, CloudWatch Logs, Secrets Manager, and DynamoDB — validating the full create, read, update, delete, sync, and discovery lifecycle.

Resource fixes: Several resource types had broken operations through AWS CloudControl that are now fixed:

  • S3 BucketPolicy — reads were broken, now works correctly
  • S3 StorageLensGroup — updates were missing resource properties in the response
  • SQS QueuePolicy — was not provisionable through CloudControl, now works via direct SQS API
  • IAM Policy — was not provisionable through CloudControl, now works via direct IAM API
  • IAM AccessKey — was not provisionable through CloudControl, now works via direct IAM API
  • IAM InstanceProfile — suffered from a 60-second propagation delay through CloudControl, now works via direct IAM API
  • EC2 NetworkAclEntry — was not supported through CloudControl, now works via direct EC2 API
  • Elastic Beanstalk ConfigurationTemplate — updates through CloudControl injected CloudFormation references, now works via direct EB API

Cross-resource references: TransitGateway, FlowLog, ResourcePolicy, ConfigurationTemplate, NetworkAclEntry, and TargetGroupTuple fields now support resolvable references, enabling correct dependency ordering during apply.

Fix: Spurious diffs during updates and synchronization for resources where AWS populates default values (e.g. LoadBalancer attributes, ECS container defaults, Lambda runtime settings). Over 130 fields across 54 resource schemas now correctly distinguish user-specified values from provider defaults.

Fix: Newly created resources could appear with missing identifiers or properties in the inventory until the next sync.

Fix: Empty optional fields could cause apply failures with CloudControl validation errors (e.g. Lambda Architectures, ECS container definitions). Optional fields that are not set are now correctly omitted.

Fix: Elastic Beanstalk ConfigurationTemplates deleted outside of formae were not correctly detected during synchronization.

Fix: CloudControl status polling now correctly handles ELBv2 update semantics and prevents extract crashes on resources with complex nested properties.


0.1.2

Conformance tests: Phase 1 conformance tests covering 32 standalone resources, validating the full CRUD and discovery lifecycle.

Schema: Expanded Route53 HealthCheck schema with fully typed HealthCheckConfig and AlarmIdentifier sub-resources, enabling richer health check definitions in Pkl.

Schema: Added ResourceLifecycleConfig fields to ElasticBeanstalk environments and configuration templates.

Rename: Renamed apprunner/service.pkl to apprunner/apprunnerservice.pkl for consistency with the naming convention used across other resource schemas.

Example: Added an AppRunner example demonstrating a simple web service deployment.

Fix: Extract now correctly filters ListResults, preventing unrelated resources from appearing in extracted Pkl output.


0.1.1

Feature: Added support for AppRunner resources (AWS::AppRunner::Service), enabling management of AppRunner web services through formae.

Fix: Added missing af-south-1 availability zone pattern. The Region typealias already included af-south-1, but the AvailabilityZone constraint was missing it, causing Pkl evaluation failures for resources in that region.


0.1.0

Initial release of the AWS plugin as a standalone package built on the formae Plugin SDK.