Why declaring different modules downloads as many registry modules locally + Error: Duplicate required providers configuration?

Just tried to create say 2 sets of resources using the same registry module which contains Oracle cloud compartments (multi level).
see Module link

  • I needed 2 subcompartments because set #2 is a child of set #1
    example :
    Terraform v1.0.3
module "main_compartment" {
 source                  = "oracle-terraform-modules/iam/oci//modules/iam-compartment"
  tenancy_ocid            = var.tenancy_ocid
  compartment_id          = var.tenancy_ocid # define the parent compartment. Creation at tenancy root if omitted
  compartment_name        = "mycomp"
  compartment_description = "main compartment at root level"
  compartment_create      = true 
  enable_delete           = true  
}
}
module "level_1_sub_compartments" {
  source                  = "oracle-terraform-modules/iam/oci//modules/iam-compartment"
  for_each = local.compartments.l1_subcomp
  compartment_id          = module.iam_compartment_main_compartment.compartment_id # define the parent compartment. Here we make reference to the previous module
  compartment_name        = each.value.compartment_name
  compartment_description = each.value.description
  compartment_create      = true # if false, a data source with a matching name is created instead
  enable_delete           = true # if false, on `terraform destroy`, compartment is deleted from the terraform state but not from oci 
}
...}

module "level_2_sub_compartments" {
  source                  = "oracle-terraform-modules/iam/oci//modules/iam-compartment"
  for_each = local.compartments.l2_subcomp
compartment_id          = data.oci_identity_compartments.compx.id # define the parent compartment. Here we make reference to one of the l1 subcomp created in the previous module
  compartment_name        = each.value.compartment_name
  compartment_description = each.value.description
  compartment_create      = true # if false, a data source with a matching name is created instead
  enable_delete           = true # if false, on `terraform destroy`, compartment is deleted from the terraform state but not from oci 

depends_on = [module.level_1_sub_compartments,]
....}
  • When I run a terraform init I get as many folders than module blocks ? why would I call them this way?
  • Why not download a single module manually and then reference it 3 times as local modules .
  • Or better off writing dynamic blocks in the main.tf using regular compartment resource ?
Initializing modules...
Downloading oracle-terraform-modules/iam/oci 2.0.2 for iam_compartment_main...
. main_compartment in .terraform/modules/main_compartment/modules/iam-compartment
Downloading oracle-terraform-modules/iam/oci 2.0.2 for level_1_sub_compartments...
. level_1_sub_compartments in .terraform/modules/level_1_sub_compartments/modules/iam-compartment
Downloading oracle-terraform-modules/iam/oci 2.0.2 for level_2_sub_compartments...
. level_2_sub_compartments in .terraform/modules/level_2_sub_compartments/modules/iam-compartment
There are some problems with the configuration, described below.

...(for each module)=> Error: Duplicate required providers configuration
A module may have only one required providers configuration. The required providers were previously configured at .terraform/modules/level_1_sub_compartments/modules/iam-compartment/main.tf:5,3-21.

What I wanted is to reuse one registry module through URL source but only have one physical folder in my working directory.
I just expected it to work but it seems local Modules are the only working option for this goal.If there is anything I’m doing wrong please let me know as the provider error is also coming from the fact that I have multiple directories having the same module config.
thank you

The reason for this error is that the module

apparently contains this bug, rendering it unusable at present!

No, it isn’t, it’s because the upstream module is broken, even if you only reference it once.


Yes, Terraform is kind of wasteful with local disk in this scenario. It is at least sensible enough to only download the module once, and then copy the content to the other remaining uses of the same module.

As I believe you already identified, you need separate module blocks if there are interdependencies between resources, as the Terraform dependency model only tracks dependencies between blocks, not between individual instances of a for_each expansion.

Because doing things manually costs human time.

Yes, I would do this. There is a style of Terraform programming where people try to make everything a module. I personally consider this to be an antipattern. Whenever a module contains only a single resource block, as this one does, I believe it is appropriate to question whether you have an extra layer of abstraction that is obfuscating, more than it is providing value. Not every module that only contains a single resource block is wrong, but many are.

The contents of the .terraform directory should mostly be considered an internal implementation detail of Terraform. Is your disk space so limited, that it matters to you that it’s being a bit inefficient in its storage layout?

@maxb thanks for taking the time to reply to my questions. I like talking about the purpose of a feature on a pure end-user perspective sort of like sharing Ux feedback after buying a car.

Error: Duplicate required providers configuration
A module may have only one required providers configuration.
“”… No, it isn’t, it’s because the upstream module is broken, even if you only reference it once."

You’re right . turns out the module was last updated in 2021 and they have required_providers defined in two tf files in the module which is not supported since 0.13.

Yes, Terraform is kind of wasteful with local disk in this scenario. It is at least sensible enough to only download the module once, and then copy the content to the other remaining uses of the same module.
you need separate module blocks if there are interdependencies between resources, as the Terraform dependency model only tracks dependencies between blocks, not between individual instances of a for_each expansion.

crazy, It’s like bringing the whole cattle of cows just because you wanted to drink a glass of milk ;).

Because doing things manually costs human time.

cue my question on why use modules at all in the first place instead of dynamic blocks.

Yes, I would do this. There is a style of Terraform programming where people try to make everything a module. I personally consider this to be an antipattern. Whenever a module contains only a single resource block, as this one does, I believe it is appropriate to question whether you have an extra layer of abstraction that is obfuscating, more than it is providing value. Not every module that only contains a single resource block is wrong, but many are.

I totally agree, I always tried to keep the code footprint super low since day 1 when deploying using terraform . Lot of people around me still made noise boasting about modules but my resources being simple I learned to leverage dynamic blocks (for_each) and nested variable interpolations through locals to keep it light.
Passing the associate certification though made me feel weird about not using modules.
But these replies make me more skeptical…knowing

  1. Registry modules leaves us at the mercy of the maintainers good will (code/sanity integrity)
  2. One single resource block per module is really an overkill
  3. wasteful

Is your disk space so limited, that it matters to you that it’s being a bit inefficient in its storage layout?

Nah man, It’s just that I can’t stand the unnecessary clutter, just doesn’t look clean for me . I usually move everything to github and I believe minimalism is healthy, offers better readability and prevents errors (before and after the apply) .

This is just a tiny config let alone a full org stack.

As with all things it depends, and there are positives and negatives.

Yes any time you use a third party module or code library you need to do due diligence to decide if the code is high quality, secure and is maintained. The advantage you get is not having to build as much yourself - some of the good Terraform modules encapsulate quite a bit of functionality and expose it in a way that’s easy to use, much quicker and less error prone.

The same is just as true for modules you make yourself. You need to ensure they are good quality and maintained correctly. Where used well you can save a huge amount of complexity and repeated code, which makes maintenance harder and errors increasingly likely.

One resource modules can sometimes be useful. Mostly where you have specific business logic you need to include - for example where the resource requires a lot of boilerplate settings, which in your case can be set a particular standard way. Using a module in this case can safe a lot of repeated code, with the large burden if anything does have to change in the future.

As with all things it depends, and there are positives and negatives.

That sums it up. I’m not saying it’s bad in all cases, but rather not a one fits all solution.