HI @jessmar.nunez,
So the error message you are getting here is pretty descriptive:
The "for_each" map includes keys derived from resource attributes that cannot be determined until apply, and so Terraform cannot determine the full set of keys that will identify the instances of this
│ resource.
│
│ When working with unknown values in for_each, it's better to define the map keys statically in your configuration and place apply-time results only in the map values.
What this is basically saying is that the ‘key’ values that you are using for your local.patchgroup map are unknown and therefore terraform does not know what the keys for the map ought to be:
aws_ssm_patch_baseline.WindowsBaseline.id
aws_ssm_patch_baseline.UbuntuBaseline.id
... # etc.
With these resources also being created within the same module.
Therefore, as these ‘keys’ are required to be resolved at plan time to identify the instances of this resource it cannot proceed as the aws_ssm_patch_baseline resources do not yet exist and the ID is generated/returned by the cloud provider and not predictable by Terraform (And it is this ID you want to use for the keys of your map).
The suggested fixes are as follows (in reverse order from the error message):
Firstly:
use the -target planning option to first apply only the resources that the for_each value depends on, and then apply a second time to fully converge
This is suggesting that you plan and apply using the -target option to direct Terraform to first deploy the aws_ssm_patch_baseline.xxxxx.id resources. Then a subsequent plan/apply will be able to retrieve those resources id’s for use in your map’s key as they will then be known and stored in the Terraform state.
Note: This is generally a bad approach and should be reserved for very specific circumstances (which I don’t think this is)
Secondly:
When working with unknown values in for_each, it's better to define the map keys statically in your configuration and place apply-time results only in the map values.
This is suggesting you use something other than an attribute from the resources as the key, and the values for the key be statically defined in the module. Therefore the keys will not change or be subject to being created prior to the plan in order for them to be known at plan time.
In this instance, something similar to the following should work:
locals {
patchgroup = {
WindowsBaseline = {
baseline_id = aws_ssm_patch_baseline.WindowsBaseline.id
patch_group = "is-patch"
}
UbuntuBaseline = {
baseline_id = aws_ssm_patch_baseline.UbuntuBaseline.id
patch_group = "is-patch"
}
AmazonLinux2Baseline = {
baseline_id = aws_ssm_patch_baseline.AmazonLinux2Baseline.id
patch_group = "is-patch"
}
AmazonLinuxBaseline = {
baseline_id = aws_ssm_patch_baseline.AmazonLinuxBaseline.id
patch_group = "is-patch"
}
RedHatBaseline = {
baseline_id = aws_ssm_patch_baseline.RedHatBaseline.id
patch_group = "is-patch"
}
}
}
resource "aws_ssm_patch_group" "patchgroup" {
for_each = local.patchgroup
baseline_id = each.value.baseline_id
patch_group = each.value.patch_group
}
As you can see, the map keys within local.patchgroup are now known at plan time. Terraform can resolve them and understand that there will be 5 resources configured based upon the for_each with defined keys:
aws_ssm_patch_group.aws_ssm_patch_group["WindowsBaseline"]
aws_ssm_patch_group.aws_ssm_patch_group["UbuntuBaseline"]
... # etc.
Which in your original example it is not possible to know unless the aws_ssm_patch_baseline resources have already been deployed and the resource id is therefore known.
Hope that helps!
Happy Terraforming