Auto generated integers or passwords inside module that is using for_each

Dear All,

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

Hi @vtzan,

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.

@apparentlymart thank you very much for your fast response.
Yes same resource in the for_each makes sense now.

Is there any ${count.index} like function in the for_each function?

thank you in advance

Vasilios Tzanoudakis

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.

Dear @apparentlymart,

Thank you very much for your support and explanations on this case.

Best Regards
Vasilios Tzanoudakis