When using module getting error

Provider is giving error when using module.

terraform init

Initializing the backend...
Initializing modules...
There are some problems with the configuration, described below.

The Terraform configuration must be valid before initialization so that
Terraform can determine which modules and providers need to be installed.
╷
│ Error: Module is incompatible with count, for_each, and depends_on
│ 
│   on main.tf line 19, in module "sre-central-slo":
│   19:   for_each          = local.slos_flattened
│ 
│ The module at module.sre-central-slo 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.
╵

Please find the folder structure :-
main.tf
–provider.tf
–version.tf
module-folder
– module.tf
– provider.tf

main.tf →

resource "dynatrace_slo" "sre-central-slo" {
  name              = var.slo_name
  evaluation        = var.evaluation
  filter            = var.filter_name
  metric_expression = var.metric
  target            = var.slo_target
  warning           = var.slo_warning
  timeframe         = var.timeframe
  provider          = dynatrace.dynatrace_api
}

provider.tf–>

terraform {
  required_version = "~> 1.2"

  required_providers {
    dynatrace = {
      source  = "dynatrace-oss/dynatrace"
      version = ">= 1.20.0"
    }
  }
}
provider "dynatrace" {
  dt_env_url   = var.dynatrace_url
  dt_api_token = var.dynatrace_api_token
  alias = "dynatrace_api"
}

module.tf →

locals {
  json_files = fileset("${path.module}/solutions", "*/*.json")
  solutions = {
    for filename in local.json_files :
    "${jsondecode(file("${path.module}/solutions/${filename}"))["solution_name"]}-${jsondecode(file("${path.module}/solutions/${filename}"))["environment"]}" => jsondecode(file("${path.module}/solutions/${filename}"))
  }
  slo = [for solution in local.solutions : {
    for slo in solution.slo : "${solution.sre_team}-${solution.product_id}-${solution.solution_name}-${solution.environment}" => {
      product_management_zone = try(solution.product_management_zone, null)
      slo_target              = try(solution.slo[0].slo_target, "98")
      slo_warning             = try(solution.slo[0].slo_warning, "99")
    } if try(solution.slo, null) != null
  }]
  slos_flattened = merge([for solution in local.slo : solution]...)
}

module "sre-central-slo" {
  source = "../"
  for_each          = local.slos_flattened

  slo_name          = "${each.key}-slo"
  evaluation        = "AGGREGATE"
  filter_name       = each.value.product_management_zone != null ? "type(SYNTHETIC_TEST),entityName.startsWith(\"${each.key}\"),mzName(\"${each.value.product_management_zone}\", \"${var.default_mz_name}\")" : "type(SYNTHETIC_TEST),entityName.startsWith(\"${each.key}\"),mzName(\"${var.default_mz_name}\")" 
  metric            = "(builtin:synthetic.browser.availability.location.total:splitBy())"
  slo_target        = each.value.slo_target
  slo_warning       = each.value.slo_warning
  timeframe         = "-1w"
}

MOdule folder provider.tf →

terraform {
  required_version = "~> 1.2"

  required_providers {
    dynatrace = {
      source  = "dynatrace-oss/dynatrace"
      version = ">= 1.20.0"
    }
  }
}
provider "dynatrace" {
  dt_env_url   = var.dynatrace_url
  dt_api_token = var.dynatrace_api_token
  alias = "dynatrace_api"
}

Like the error message says, this is something that is not (and has never been) supported.

Is there a reason you have chosen to set an alias on this provider? If it is the only provider of its type in your configuration, using an alias just complicates things.

Generally, you should be aiming for all provider configurations to be defined in your root Terraform configuration, so there should be no provider blocks within child modules.

Yeah there was only one provider which I want to use fully, just tried alias intentionally. We can remove that, but is there any way to create this module and use it with provider. Can you please help with the code changes…

You’d really have to share more of your code - preferably as a Git repository, for me to be confident in proposing specific code changes, but it certainly is looking rather like you just need to delete a lot of stuff:

  • The alias in the root level provider "dynatrace" block
  • All the provider = dynatrace.dynatrace_api lines
  • The entire provider "dynatrace" block inside the module
  • All the variables being used to pass the URL and API token from the root level to the module

@maxb Please find the repo attached for reference

@maxb is there any update…

Now that I can see your code, I can see my previous ideas were mostly correct.

Before talking more about that, however, I need to mention something else:

Your setup, where you run Terraform commands from inside the slo-module directory, and that directory then uses the parent directory as a child module:

module "sre-central-slo" {
  source = "../"

is really weird.

It works. Terraform doesn’t care about it. But from the human perspective, it’s an inversion of all normal conventions, and means that if we talk about the root directory of your Terraform code, and the root module of the Terraform configuration … these two meanings of “root” are now referring to different directories/modules, when normally they would be one and the same!

I highly encourage you to flip these things around to a more normal layout.

Anyway, back to the immediate problem:

Just delete the incorrect bits I previously identified: Delete the incorrect stuff · maxb/shnigam2-slo@9caaf98 · GitHub

Thanks @maxb it worked and will definitely follow recommended folder structure.