slide

Mysterious missing "region" argument in terraform

Ned Bellavance
3 min read

Cover

I’m working on my next course for Pluralsight, Implementing Terraform on AWS. I probably don’t need to explain what the course is about. Anyhow, I was trying to show how you can create multiple instances of an AWS provider using the alias argument. Running through the initialization and validation process I ran into an error that was not very helpful.

Error: Missing required argument

The argument "region" is required, but was not set.

No mention of what line the error occurred on, or what resource in the configuration was throwing it. Just a missing region argument. Let’s see what’s going on here.

In the configuration I have two providers being defined:

provider "aws" {
  version = "~> 2.0"
  region  = var.region
  alias   = "infra"
  profile = "infra"
}

provider "aws" {
  version = "~> 2.0"
  region  = var.region
  alias   = "sec"
  profile = "sec"
}

It’s pretty clear that I am defining a region for each provider. So that’s not the issue. I thought maybe since I was using the profile argument, Terraform wanted to use the region set from the profile and not the provider. I tried omitting the region argument instead, and just ended up with more errors.

Error: Missing required argument

The argument "region" is required, but was not set.


Error: Missing required argument

  on main.tf line 18, in provider "aws":
  18: provider "aws" {

The argument "region" is required, but no definition was found.

At this point it was time to turn up the logging and see what’s going on. I’m working in Windows, so I ran $env:TF_LOG="DEBUG" and reran the validation process. I won’t paste in all the output here, it’s amazingly verbose! But after looking for a bit, I found two sets of lines that gave me a clue as to what was going on.

2020/05/04 09:20:06 [TRACE] dag/walk: added new vertex: "provider.aws"
2020/05/04 09:20:06 [TRACE] dag/walk: added new vertex: "provider.aws.sec (close)"
2020/05/04 09:20:06 [TRACE] dag/walk: added new vertex: "provider.aws.infra"
...
2020/05/04 09:20:06 [TRACE] buildProviderConfig for provider.aws: no configuration at all

Terraform was constructing three AWS providers even though I only defined two. And the third AWS provider had no configuration, which means that Terraform was implicitly creating it for a resource. I looked through the configuration and sure enough:

resource "aws_iam_group_policy" "peering-policy" {
  name   = "peering-policy"
  group  = aws_iam_group.peering.id

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "sts:AssumeRole",
    "Resource": "${aws_iam_role.peer_role.arn}"
  }
}
EOF
}

There is no provider argument in the configuration block. Since both of my explicitly defined AWS providers have an alias, Terraform was creating a third, non-alias provider for this resource. Unfortunately, the implicit provider had no configuration data and I had not set any environment variables that Terraform could use.

Terraform was correct, I was missing the region argument for the provider, and it could not provide a line reference because the provider was being created implicitly.

I updated the configuration with a provider argument and the error went away.

resource "aws_iam_group_policy" "peering-policy" {
  name     = "peering-policy"
  group    = aws_iam_group.peering.id
  provider = aws.infra

  policy   = <<EOF
{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "sts:AssumeRole",
    "Resource": "${aws_iam_role.peer_role.arn}"
  }
}
EOF
}

I’ve never been a fan of the implicit provider creation feature of Terraform. The first time I saw it in a demo, I thought, “Well that’s confusing and possibly problematic.” Turns out I was right, but I don’t expect HashiCorp to change it now.

The moral of the story is that the debug logs for Terraform are your friend. When faced with an inscrutable error, go ahead and turn them on and take your time parsing through. There’s a lot of information, and buried in there will be the answer to your problem.