terraform-aws-modules/terraform-aws-autoscaling examples/complete (tag v9.3.0), its only/flagship example

Source: https://github.com/terraform-aws-modules/terraform-aws-autoscaling.git at v9.3.0.

Set: core. Lane: terraform-popular.

Why it is in the core set: a most-downloaded terraform-aws-modules example, pinned by tag; the shape most people deploy

Not clear yet.

StageVerdictDetail
Cold deploypassApply complete! Resources: 68 added, 0 changed, 0 destroyed.; 0 objects carry tofu-estate=autoscaling-complete-crossing before migration
Migratepass41 resource(s) newly stamped, 0 already stamped, 0 newly recorded, 0 re-recorded for sensitivity only, 0 already recorded, 0 failed, 27 skipped; 41 objects carry tofu-estate=autoscaling-complete-crossing
Replan from nothingpassempty plan; identity re-check unchanged: module.complete.aws_launch_template.this:0, aws_iam_role.ssm
No-op applypassgenuine no-op: 41 objects before, 41 after, no state file either time
Drift and reconvergepassone object tampered (SQS queue ‘complete’s Example tag), plan proposed fixing exactly one object, apply changed 1 and reconverged the tag
Renamepassmoved block: module.asg_sg renamed with zero churn (0 add, 1 change, 0 destroy), marker rewritten in place on its security group; live-mv: aws_sqs_queue.this renamed with zero churn, marker rewritten in place; stock oracle over the same two-object rename on cold_deploy’s own state also shows zero churn (0 add, 0 change, 0 destroy); both live ids unchanged, read via the AWS CLI
Remove a blockpasschoudoufu: deleting module.default’s block proposed exactly 2 destroys (0 add, 0 change, 2 destroy), matching the stock oracle’s own count and applied cleanly; the live ASG count dropped by exactly one and the tagged object count dropped too, both confirmed via the AWS CLI, not through choudoufu’s own report; the next plan proposes no resource action; stock oracle on cold_deploy’s own state (D-REMOVE-ORACLE) also proposes exactly 2 destroys for the same module
Change count (planned)not run
Replace with create_before_destroynot run
Crash between create and destroy (planned)not run
Teardown (planned)not run
Plan, review, apply (planned)not run
Greenfield applypass68 resources from nothing, matching stock’s own cold-deploy count (68); the sqs queue’s markers verified via the AWS CLI; 68 records in the local record store including the untaggable ASGs (#364 A2); replan empty; the asg_sg security group’s rule counts match stock’s cold deploy structurally, via the AWS CLI on both endpoints, marker tags never compared; 41 objects carry the estate tag
Strict profile (planned)not run

Last run at commit df0cc6a075 on 2026-08-25T17:28:03Z, exit code 0.

RE-CROSSED FOR REAL 2026-08-21 at dbc5ebf575 (GitHub issue #346’s fix), real Docker/floci/terraform/AWS CLI throughout. STAGES UNCHANGED at 2 of 5 and BOTH stage-3 diagnostics are unchanged, verbatim - #346’s fix does not move this estate. Stage 1: ‘Apply complete! Resources: 68 added, 0 changed, 0 destroyed’. Stage 2: ‘41 of 68 eligible’; ‘41 stamped, 0 already stamped, 0 newly recorded, 0 failed, 27 skipped’; markers asserted by value through the AWS CLI (launch template lt-0e04ccd955a0a5071 = module.complete.aws_launch_template.this:0, IAM role ‘complete’ = aws_iam_role.ssm), and the ASG itself confirmed carrying 0 tofu-* tags as the marker vocabulary requires. Stage 3 fails on exactly 2: (1) ‘Non-static identity argument’ on module.complete.aws_autoscaling_traffic_source_attachment.this[’ex-alb’].identifier (main.tf:1102, identifier = each.value.traffic_source_identifier), same file, same line, same text as before; (2) ‘Ambiguous list-valued identity argument’ on module.asg_sg.aws_security_group_rule.computed_ingress_with_source_security_group_id[0].prefix_list_ids, which ‘has 0 elements’ - the Component.SoleElement refusal, deliberate per its own registry text and never in scope for #346. Diagnostic (1) sits on the each.value route #346’s fix does touch, but it refuses at a different point: ‘Non-static identity argument’ is stringValueIn’s !IsWhollyKnown branch, so the value EVALUATED and came back unknown rather than the selection refusing. The unknown is the ALB target group’s ARN arriving through a tolerant module-argument rebuild - the same value-shaped route corpus-rds-complete-postgres and corpus-ecs-fargate hit, reached from the other side. Filed with them. PRIOR HISTORY BELOW. RE-CROSSED 2026-08-21 TWICE, at commit 7aea0eef95 (GitHub issue #353, provisioners admitted under a record_store), worktree live/provisioner-support-353, real Docker/floci/terraform/AWS CLI throughout, image ghcr.io/lex00/floci@sha256:d65baf42, hashicorp/aws 6.59.0. Both runs are this script’s own output, not inferred. STAGES ARE UNCHANGED at 2 of 5 - cold_deploy pass, migrate pass, test_plan fail - and that is the honest headline: #353 removed this estate’s SOLE stage-3 diagnostic and did not move its stage outcome, because two more stand behind it. What changed, measured: RUN 1 (the script exactly as it stood, live block declaring only the estate name): stage 3 fails on exactly ONE diagnostic, ‘Provisioners are not available under live resource markers’ on aws_iam_service_linked_role.autoscaling (main.tf:889, the example’s own ‘sleep 10’). RUN 2 (the script’s migration edit now also declares record_store “local” - the supported way past that wall, and what an operator migrating this estate would actually write; the delta is documented in the script’s own header): that diagnostic is GONE and stage 3 fails on exactly TWO, which are the two the 2026-08-20 pass predicted by measuring past the wall on a scratch copy, now confirmed for real. (1) ‘Non-static identity argument’ on module.complete.aws_autoscaling_traffic_source_attachment.this[“ex-alb”].identifier (main.tf:1102, identifier = each.value.traffic_source_identifier, reaching module.complete_alb’s target-group ARN) - #346’s wall, one spelling further out than the corpus-vpc-complete form, unresolved by maintainer decision and needing a design pass rather than code. (2) ‘Ambiguous list-valued identity argument’ on module.asg_sg.aws_security_group_rule.computed_ingress_with_source_security_group_id[0].prefix_list_ids, which ‘has 0 elements’ - the Component.SoleElement refusal, deliberate per its own registry text. Stages 1 and 2 are byte-for-byte the same in both runs: ‘Apply complete! Resources: 68 added, 0 changed, 0 destroyed’ from 0 pre-existing marked objects; ‘41 of 68 resource instance(s) are eligible for stamping’; ‘41 resource(s) newly stamped, 0 already stamped, 0 newly recorded, 0 already recorded, 0 failed, 27 skipped’; 41 objects carrying tofu-estate afterwards. Declaring the record_store did not change the migrate summary line at all, which is the expected answer - this estate has no record-backed type, so the store’s only job here is to hold a provisioner’s tainted bit if one ever fails. test_apply and drift_reconverge stay not_run: running them against a refused plan would prove nothing. PRIOR HISTORY BELOW. RE-CROSSED 2026-08-20 against the #84 pin, worktree live/floci-warmpool-recross, real Docker/floci/terraform/AWS CLI throughout, image ghcr.io/lex00/floci@sha256:120b6783 (the b9e5a593 PutWarmPool build already pinned in live/floci-image). Every figure below was computed on a base of local main dd22a50669, and the whole script was re-run there after the rebase with an identical result - not carried over from the pre-rebase run. lex00/floci#84 is CONFIRMED FIXED: module.warm_pool’s warm_pool block no longer errors, and this estate moves 0 of 5 to 2 of 5. Numbers read off the script’s own lines, not inferred: STAGE 1 ‘Apply complete! Resources: 68 added, 0 changed, 0 destroyed’ with 0 objects carrying tofu-estate beforehand; STAGE 2 dry run ‘41 of 68 resource instance(s) are eligible for stamping’, -approve ‘41 resource(s) newly stamped, 0 already stamped, 0 newly recorded, 0 already recorded, 0 failed, 27 skipped’, 41 objects carrying tofu-estate afterwards. All 27 skips sit under UNTAGGABLE with no UNADMITTED_TYPE section at all - 8 aws_autoscaling_group, 6 aws_route_table_association, 5 aws_autoscaling_policy, 3 aws_autoscaling_schedule, 2 aws_security_group_rule, and one each of aws_autoscaling_traffic_source_attachment, aws_iam_role_policy_attachment and aws_route - the invariant working rather than a gap. THREE SELF-INFLICTED SCRIPT BUGS FOUND AND FIXED, none of which had ever run because stage 1 had never passed: (1) stage 2 asserted a tofu-address TAG on ASG ‘complete’, which can never exist - an aws_autoscaling_group’s tags are tag nested blocks, not the top-level tags map internal/live/markers.TagSurface requires, so Taggable() refuses it from the schema and markers.go’s own doc comment names this exact type as the shape it will not stamp; the assertion also read through autoscaling describe-tags, which floci does not implement at all (‘UnsupportedOperation: Operation DescribeTags is not supported’), with the CLI error swallowed by a 2>/dev/null and read back as an empty tag. Fixed in the harness, not in floci, same call as #345: the ASG’s identity is now asserted out of live-import’s own UNTAGGABLE row, which prints the resolved address beside the live id it bound to (‘module.complete.aws_autoscaling_group.idc[0] … live id: complete’), plus a separate assertion that the live ASG carries ZERO tofu-* tags, since a marker written into a tag block would be the wrong-marker failure this repository ranks above a missing one. That row is also what now exercises the count-is-zero-per-instance fix for real - .idc[0] resolves, .this resolves to no instance at all. (2) the launch-template assertion looked up describe-launch-templates --launch-template-names complete, but module.complete builds its launch template from a name_prefix, so the live name carries a provider-minted suffix (‘complete-53747ea039642590a26cff220b’) and the lookup returned None; it now finds the object BY ITS MARKER (ec2 describe-tags on key=tofu-address, value=module.complete.aws_launch_template.this:0) and asserts the resulting name starts with ‘complete-’. (3) both that assertion and the IAM-role one compared a tag value against OpenTofu’s BRACKET spelling when a tag value can never carry ‘[’ - the escaped form is ‘:0’ per internal/live/markers.EscapeKey - and the role assertion additionally had the wrong resource: the role named exactly ‘complete’ is the example’s ROOT-LEVEL aws_iam_role.ssm (name = local.name), not module.complete’s own role, which lands as ‘complete-5c82d83cf70f48587a1e0817dc’. Same vacuous-comparison bug corpus-vpc-complete, corpus-iam-policy and corpus-iam-read-only-policy each shipped once; bracket and colon forms are now separate variables, with the bracket form used only where stage 5 reads a plan diff header. BREAK=1 re-run confirms the rewritten role assertion is still load-bearing (fails on ’the IAM role carries tofu-address=aws_iam_role.ssm, not module.complete.aws_iam_role.this:0’). A REAL CHOUDOUFU CRASH found and fixed on the way, not a script bug: running live-import a SECOND time against the already-stamped estate - a supported thing to do, ‘already stamped’ is one of the outcomes the summary line counts - panicked with ‘value is null’ at internal/live/liveimport/tags.go, equivalent(). Its zeroish allowance forgives null-against-empty, but null against a POPULATED collection fell through to the collection arms, which call LengthInt/ElementIterator/GetAttr, all of which panic on null, reaching the operator as an OpenTofu crash report instead of a diagnostic. Guarded, with internal/live/liveimport/tags_test.go pinning both the crash cases and the null-vs-empty allowance the guard must not eat; the re-run now completes and correctly reports DRIFTED (41), the markers the state file does not know about. STAGE 3 fails on EXACTLY ONE diagnostic: provisioner “local-exec” on aws_iam_service_linked_role.autoscaling (main.tf:889 - the example’s own ‘sleep 10’ comment says ‘Sometimes good sleep is required to have some IAM resources created before they can be used’). PARITY LABEL, stated first: ‘OpenTofu succeeds, choudoufu refuses’. Stock terraform ran this provisioner in stage 1 of this very script, so the label is not in doubt. It is NOT filed as a new defect, because it is already enumerated in live/LIMITATIONS.md under ‘Enforced today’ with a forwarding address (RuleProvisioner, internal/live/lint/lint.go’s checkProvisioners, fixture live/e2e/limits/local-exec/): a provisioner runs an effect, and whether it already ran is knowable only from a stored record, which is exactly the authority live markers give up. What IS new information is the cost: this is the first POPULAR, real, terraform-aws-modules estate blocked by that ban outright, versus sumaform’s, which was dead code (a provisioner-less connection block). Whether the store test should stay absolute for a provisioner whose effect is a sleep is a maintainer call and was not forced here. MEASURED PAST THE WALL, on a scratch copy with the provisioner block deleted - a diagnostic only, deliberately NOT a delta in the landed script, which routes around nothing: exactly two further diagnostics stand behind it, no more. First, ‘Non-static identity argument’ on module.complete.aws_autoscaling_traffic_source_attachment.this[“ex-alb”].identifier - each.value.traffic_source_identifier is module.complete_alb’s target group ARN, a non-identity attribute of another managed resource, which is the same wall #346 is filed for on corpus-vpc-complete, one spelling further out. Second, ‘Ambiguous list-valued identity argument’ on module.asg_sg.aws_security_group_rule.computed_ingress_with_source_security_group_id[0].prefix_list_ids, which ‘has 0 elements’ - the Component.SoleElement refusal whose own registry text (internal/live/identity/refusals.go) already says zero elements and more than one are both refused, so it is deliberate rather than a new find; the zero case is arguably distinguishable from the many case and was left alone rather than widened on this pass. So even with the provisioner gone this estate would still fail stage 3, on two identity walls neither of which is specific to autoscaling. test_apply and drift_reconverge remain not_run: attempting them against a refused plan would prove nothing. PRIOR HISTORY - Landed 521941f77e (2026-08-18), 80 resources across 12 module calls - the largest crossing tonight (mixed instances, warm pools, EFA interfaces, attribute-based instance requirements, external launch templates, lifecycle hooks, scheduled actions, scaling policies, the count-is-zero-per-instance admission fix genuinely exercised for real via the ignore_desired_capacity_changes-gated aws_autoscaling_group.this/.idc pair). lex00/floci#64 (CreateCapacityReservation/DescribeCapacityReservations/ModifyCapacityReservation/CancelCapacityReservation entirely unimplemented) is now FIXED and merged to floci main (1ad8d39b), CI and GHCR-publish both green as of e970328 (published sha256:dcb25c00), and live/floci-image is re-pinned to it with the capability manifest regenerated to match (749 types, same shape as the prior digest). Re-ran this script for real 2026-08-20 against the new pin: aws_ec2_capacity_reservation.targeted no longer errors - #64 confirmed fixed. cold_deploy is still recorded fail because a SECOND, previously-masked gap surfaces immediately after: module.warm_pool’s aws_autoscaling_group.this[0] declares a warm_pool block, and PutWarmPool is entirely unimplemented in floci’s AutoScaling service (grepped AutoScalingQueryHandler/AutoScalingService/model - zero occurrences of “WarmPool”) - ‘UnsupportedOperation: Operation PutWarmPool is not supported.’ This was masked until now because CreateCapacityReservation failed first in the same cold-deploy run, on a different resource earlier in the module graph. Filed as lex00/floci#84 (PutWarmPool/DescribeWarmPool/DeleteWarmPool), verified against botocore’s own autoscaling/2011-01-01/service-2.json wire model - not attempted in this session, a second AutoScaling-side feature comparable in size to #64, left as a clean follow-up. #84 is now the sole cold_deploy blocker for this estate; #310 (the traffic-source-attachment admission gap, since fixed per its own issue - see that issue for verification) and the rest of this crossing’s stage-3+ picture remain unverified against a real cold deploy until #84 lands.

Reproduce it#

go run ./tools/gauntlet run corpus-autoscaling-complete

Needs Docker (the emulator is pulled at the pinned digest), the AWS CLI, and a stock terraform or tofu binary on PATH for the cold deploy. The script is live/e2e/corpus-autoscaling-complete/run.sh; BREAK=1 corrupts its assertions to show they are load-bearing.