You have defined the keys of a for_each
using an attribute (id
) of another resource that is only known after that other resource has been created.
This will cause you trouble, as Terraform cannot complete a plan if for_each
keys are values which will only be known after apply - it is an architectural choice / limitation.
You should use some identifier that can be known before the aws_subnet
creations are applied.
To give more specific help on this point, you would have to show us your aws_subnet
resource block.
@jbardin has already pointed out that this is unnecessarily complicated.
As you have not adopted any changes suggested in that message, I guess you want more details:
length(aws_instance.web_server[*].id)
is an overly complicated way of arriving at the same result as length(aws_instance.web_server)
as the [*].id
just does a bunch of additional transformations which make no changes to the length.
element(aws_instance.web_server[*].id, count.index)
is an extremely over-complicated way of writing aws_instance.web_server[count.index].id
. As well as the needless use of [*]
, the element
function is effectively obsolete in modern Terraform - it is less readable and has surprising extra behaviour which may hide errors, compared to a simple square-bracketed index expression.
However neither of these really matter, because you should be using for_each
instead of count
here.
Never use count
unless all of the objects being created via the count are so identical, that you would not care which one was being destroyed during any future change.
The reason is that resource instances in a count
are identified only by their index.
Let us suppose, for sake of example, that you have subnets A, B, C, each with their webserver instance and LB attachment.
Let us now suppose subnet B is removed.
If you have used count
, Terraform does not know that the LB attachments are related to A, B, C. It only knows them as 0, 1, 2. As a result what it now does is:
- Delete the LB attachment at
count.index
2, for C
- Replace or update the LB attachment at
count.index
1, from being configured for B, to C
As a result, the change to remove B ends up messing with configuration for C.