0
votes

I am developing the infrastructure (IaC) I want to have in AWS with Terraform. To test, I am using an EC2 instance.

This code has to be able to be deployed across multiple accounts and **multiple regions (environments) per developer **. This is an example:

account-999

developer1: us-east-2
developer2: us-west-1
developerN: us-east-1

account-666:

Staging: us-east-1
Production: eu-west-2

I've created two .tfvars variables, account-999.env.tfvars and account-666.env.tfvars with the following content:

  • profile="account-999" and profile="account-666" respectively

This is my main.tf which contains the aws provider with the EC2 instance:

provider "aws" {
  version = "~> 2.0"
  region  = "us-east-1"
  profile = var.profile
}

data "aws_ami" "ubuntu" {
  most_recent = true

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }

  owners = ["099720109477"]
}

resource "aws_instance" "web" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = "t3.micro"

  tags = {
    Name = "HelloWorld"
  }
}

And the variable.tf file:

variable "profile" {
  type=string
}

variable "region" {
  description = "Region by developer"
  type = map
  default = {
    developer1 = "us-west-2"
    developer2 = "us-east-2"
    developerN = "ap-southeast-1"
  }
}

But I'm not sure if I'm managing it well. For example, the region variable only contains the values of the account-999 account. How can I solve that? On the other hand, with this structure, would it be possible to implement modules?

1
Regions can be solved best with modules and provider aliases, especially if you are using 0.13 with the new meta-argument features for modules.Matt Schuchard

1 Answers

1
votes

You could use a provider alias to accomplish this. More info about provider aliases can be found here.

provider "aws" {
  region = "us-east-1"
}

provider "aws" {
  alias  = "west"
  region = "us-west-2"
}

resource "aws_instance" "foo" {
  provider = aws.west
  # ...
}

Another way to look at is, is by using terraform workspaces. Here is an example:

terraform workspace new account-999
terraform workspace new account-666

Then this is an example of your aws credentials file:

[account-999]
aws_access_key_id=xxx
aws_secret_access_key=xxx

[account-666]
aws_access_key_id=xxx
aws_secret_access_key=xxx

A reference to that account can be used within the provider block:

provider "aws" {
    region  = "us-east-1"
    profile = "${terraform.workspace}"
}

You could even combine both methods!