Hi,
I use a list to create the resource,
list_zones = [
"us-east1-a",
"us-west2-c",
]
And a map to create the local-exec provisioner
flat_zones = [
{
env_name = "stg-a1"
zone = "us-east1-a"
},
{
env_name = "stg-a1"
zone = "us-west2-c"
},
{
env_name = "stg-b1"
zone = "us-west2-c"
},
]
Here’s the resource creation code,
resource "google_apigee_instance" "apigee" {
for_each = toset(local.list_zones)
name = "${each.value}-${random_id.random.dec}"
location = each.value
provisioner "local-exec" {
for_each = { for idx, record in local.flat_zones : idx => record }
when = create
command = <<EOF
curl -i -H "Authorization: Bearer ${data.google_client_config.current.access_token}"\
"https://apigee.googleapis.com/v1/organizations/${var.project}/instances/${each.value.zone}-${random_id.random.dec}/attachments" \
-X POST -H "content-type:application/json" \
-d '{"environment":"${each.value.env_name}"}'
EOF
}
depends_on = [google_apigee_environment.apigee]
}
I know the for_each inside a provisioner is not allowed, but that’s just to show I need additional fields from the map to fulfill the curl.
Also, I am OK to use a null_resource as long as that null_resource gets executed as soon as the respective instance is created and not wait for all the instances to get created.
How to achieve this behavior?
Any help is appreciated.
Thanks,
Arun
I think the most practical answer to this question is to use a single local-exec
provisioner with more than one statement in command
, perhaps like this:
resource "google_apigee_instance" "apigee" {
for_each = toset(local.list_zones)
# ...
provisioner "local-exec" {
command = <<-EOF
%{ for record in local.flat_zones }%{ if record.zone == each.key ~}
curl -i ... "https://apigee.googleapis.com/v1/organizations/${var.project}/instances/${record.zone}-${random_id.random.dec}/attachments" ... \
-d '{"environment":"${record.env_name}"}'
%{ endif }%{ endfor ~}
EOF
}
}
I simplified this just to show the general structure I have in mind without repeating all of the stuff that’s unchanged here, but the general idea here is to make this generate a single script that has multiple curl
calls. The structure of local.flat_zones
made this a bit awkward, requiring an extra if
directive, so if you can restructure that to be a more convenient data structure (e.g. a map where the keys are the zones) then you could simplify the template a little.
Yes, that’s a great suggestion and yes, I will simplify flat_zones, currently it’s
flat_zones = flatten([
for zone_key, zone in var.deployments: flatten([
for group_key, group in zone: [
for env_key, env in group.envs: {
env_name = env
zone = zone_key
}
]
])
])
Any easy way to make that a map like you suggested?
If you are too busy to answer that’s fine, I will google, that should be pretty simple.
Thanks,
Arun
If I’m understanding that expression correctly, it seems like you already have a suitable data structure for this in var.deployments
, without the need to build this derived one:
provisioner "local-exec" {
command = <<-EOF
%{ for env in var.deployments[each.key] }
curl -i ... "https://apigee.googleapis.com/v1/organizations/${var.project}/instances/${each.key}-${random_id.random.dec}/attachments" ... \
-d '{"environment":"${env}"}'
%{ endfor ~}
EOF
}
For this I’m making the assumption that var.deployments
is a data structure shaped like this:
{
"us-east1-a" = {
"stg-a1" = "something"
}
"us-west2-c" = {
"stg-a1" = "something"
"stg-b1" = "something"
}
}
Even if I didn’t get that exactly right, hopefully it’s close enough that you can see what I mean.
Hi @apparentlymart, yes, thank you, makes sense. Appreciate your help.