Modules, Providers and for_each (sorry to bring this up again) - Best Workarounds?

Hi,

This kinda follows the point raised here. What I’m looking to solve is what is the best workaround for this limitation? What do most folks generally do?

To explain the background… what I want to do is, with the AWS provider, deploy some IAM policies to every account in our AWS organisation (there are a lot of AWS accounts). This is probably very similar to what others need to solve - or a variation on the theme.

What I’d ideally liked to have done is (but, before you say anything, I know this doesn’t work :confounded: )…

  1. Read in all the accounts and make a handy map of names to account IDs:
data "aws_organizations_organization" "org" {}

locals {
  aws_account_map = {
    for account in data.aws_organizations_organization.org.accounts : "${account.name}" => account.id
  }
} 
  1. Call a module for each account in the map:
module "iam_policies" {
  for_each = local.aws_account_map
  account = { name = each.key, id=each.value }
  source = ... etc. etc.
}
  1. Within the module source, set a default provider with a profile that matches the account name (assumes I have a config with all these configured, of course):
provider "aws" {
  profile = var.account.name
  ... etc. etc.
}

That would, I think, have worked a treat, but returns the…

Error: Module is incompatible with count, for_each, and depends_on
The module is a legacy module which contains its own local provider configurations, and so calls to it may not use the count, for_each, or depends_on arguments.
If you also control the module, consider updating this module to instead expect provider configurations to be passed by its caller.


So the options appear to be (considering we have a large and ever-changing number of AWS accounts - so manually creating & maintaining all the separate providers and module blocks isn’t an option):

  1. Instead of using TF to deploy the policies, instead use TF to deploy a CloudFormation Stack Set to do it. But that kinda seems like “crossing the streams” somewhat - and difficult for other resources to use those policies without reading them as separate data (and requiring some pause or separation for CloudFormation to do its thing).
  2. Create some “pre-plan” script with generates the root-level Terraform - with separate providers and module blocks (no for_each) for each account. But this seems messy and repetitive (well, repeated resulting HCL anyway).
  3. A few searches suggest Terragrunt might handle this. But I’m not sure - I’ve not used it.

Anyone using any other good solutions for this?

Any good hints or tips? Your favourite workaround?

Thanks :slight_smile:

PS - some “solutions” proposed here: Error: Module is incompatible with count, for_each, and depends_on – HashiCorp Help Center
But these involve a lot of repetition :frowning: which I’m trying to avoid.