I have a created a module to execute custom mysql queries to an rds using a bastion host.
I would like inside the mysql_query to have auto generated variables like random integers or e.g. random passwords. I am using for_each inside module and everything I tried with
resource “random_integer” for example I couldn’t make the module to create new integer every time it runs.
module "update_mysql" {
source = "../../../../modules/vl-tf-mysql-queries-bastion"
depends_on = [module.ecs_instances]
for_each = data.aws_instance.this
environment = local.ecs_environment
rds_cluster_name = local.rds_cluster_name
databases = split(",", data.aws_ssm_parameter.users.value)
bastion_ssh_private_key = local.bastion_ssh_private_key
bastion_ssh_user = local.bastion_ssh_user
# *** NOTE **** each query below will run multiple times on each DB set in databases
mysql_query = [
"INSERT INTO clusterer (cluster_id,node_id,url,state,no_ping_retries,priority,sip_addr,flags,password) VALUES (1,${here_I_need_a_++counter_on_each_run},'bin:${each.value["private_ip"]}:5555',1,3,50,'${each.value["public_ip"]}:65060','seed','${here_I_need_auto_generated_password}');"
]
}
thank you in advance for your support
Vasilios Tzanoudakis
In your example it seems like it’s the module caller’s responsibility to generate the random number, rather than the module itself encapsulating it. That means that the caller would need to include a resource "random_password" ... block that has the same for_each expression as this module, to generate one random password per element of data.aws_instance.this.
For example:
resource "random_password" "example" {
for_each = data.aws_instance.this
# (and the other random_password arguments you need)
}
module "update_mysql" {
source = "../../../../modules/vl-tf-mysql-queries-bastion"
depends_on = [module.ecs_instances]
for_each = data.aws_instance.this
environment = local.ecs_environment
rds_cluster_name = local.rds_cluster_name
databases = split(",", data.aws_ssm_parameter.users.value)
bastion_ssh_private_key = local.bastion_ssh_private_key
bastion_ssh_user = local.bastion_ssh_user
# *** NOTE **** each query below will run multiple times on each DB set in databases
mysql_query = [
"INSERT INTO clusterer (cluster_id,node_id,url,state,no_ping_retries,priority,sip_addr,flags,password) VALUES (1,placeholder,'bin:${each.value["private_ip"]}:5555',1,3,50,'${each.value["public_ip"]}:65060','seed','${random_password.example[each.key].result}');"
]
}
I only included a password here just to keep this example simple, but the same principle would apply to a random_integer resource too. Notice that the mysql_query argument here includes a reference to random_password.example[each.key].result, which is the password that was generated for the instance described by each.value.
Another option to consider would be to change the abstraction so that the mysql_query string is generated inside the module rather than outside of the module. I can’t say whether that’s appropriate for the system architecture you’re implementing, but if it were then you could put a resource "random_password" and a resource "random_integer" block inside the module and it would get repeated along with everything else in the module as a result of the module having for_each set.
The equivalent of count.index in a resource with for_each is each.key, which produces the map key of the current element or (if you’re using a set of strings) the current string value.
There is no way to get a current numeric index because a key requirement for for_each is that the various objects it creates don’t have any particular ordering relationship relative to each other, and thus you can freely add and remove items over time without affecting the list indices of existing items.