Declare a variable of type list(object(...)) containing the attributes needed for each ingress rule such as protocol, from_port, to_port, and cidr_blocks
Add a lifecycle precondition block inside the resource to validate invariants on the input variable, such as rejecting port ranges where from_port exceeds to_port, with a clear error message
Write a dynamic ingress block inside the security group resource iterating over the variable with for_each and mapping each attribute to the corresponding block argument
Run terraform validate and terraform plan to confirm the dynamic block expands correctly and the precondition triggers on invalid input
Test edge cases including an empty list to verify the resource is created with no ingress rules rather than causing an error
Known gotchas
dynamic blocks use for_each with a collection and a content block; the iterator variable defaults to the dynamic block label (e.g., ingress) and must be referenced inside content — using each instead of the label name causes a reference error
Preconditions in lifecycle blocks are evaluated after the configuration is parsed but before the plan is applied; errors in precondition expressions themselves rather than failed conditions cause a confusing configuration error rather than a helpful validation message
An empty list passed to a dynamic block's for_each produces zero blocks, which is valid Terraform but may produce an invalid cloud resource if the provider requires at least one instance of that block — validate provider requirements separately
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp