Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create provide modules that support multiple AWS regions?

Tags:

terraform

We are trying to create Terraform modules for below activities in AWS, so that we can use them where ever that is required.

  1. VPC creation
  2. Subnets creation
  3. Instance creation etc.

But while creating these modules we have to define the provider in all above listed modules. So we decided to create one more module for provider so that we can call that provider module in other modules (VPC, Subnet, etc.).

Issue in above approach is that it is not taking provider value, and asking for the user input for region.

Terraform configuration is as follow:

$HOME/modules/providers/main.tf

provider "aws" {
  region = "${var.region}"
}

$HOME/modules/providers/variables.tf

variable "region" {}

$HOME/modules/vpc/main.tf

module "provider" {
  source = "../../modules/providers"
  region = "${var.region}"
}

resource "aws_vpc" "vpc" {
  cidr_block = "${var.vpc_cidr}"
  tags = {
    "name" = "${var.environment}_McD_VPC"
  }
}

$HOME/modules/vpc/variables.tf

variable "vpc_cidr" {}
variable "environment" {}
variable "region" {}

$HOME/main.tf

module "dev_vpc" {
  source = "modules/vpc"
  vpc_cidr = "${var.vpc_cidr}"
  environment = "${var.environment}"
  region = "${var.region}"
}

$HOME/variables.tf

variable "vpc_cidr" {
  default = "192.168.0.0/16"
}

variable "environment" {
  default = "dev"
}

variable "region" {
  default = "ap-south-1"
}

Then when running terraform plan command at $HOME/ location it is not taking provider value and instead asking for the user input for region.

I need help from the Terraform experts, what approach we should follow to address below concerns:

  1. Wrap provider in a Terraform module
  2. Handle multiple region use case using provider module or any other way.
like image 557
Sandeep Sharma Avatar asked May 02 '17 07:05

Sandeep Sharma


1 Answers

I knew a long time back that it wasn't possible to do this because Terraform built a graph that required a provider for any resource before it included any dependencies and it didn't used to be possible to force a dependency on a module.

However since Terraform 0.8 it is now possible to set a dependency on modules with the following syntax:

module "network" {
  # ...
}

resource "aws_instance" "foo" {
  # ...

  depends_on = ["module.network"]
}

However, if I try that with your setup by changing modules/vpc/main.tf to look something like this:

module "aws_provider" {
  source = "../../modules/providers"
  region = "${var.region}"
}

resource "aws_vpc" "vpc" {
  cidr_block = "${var.vpc_cidr}"
  tags = {
    "name" = "${var.environment}_McD_VPC"
  }
  depends_on = ["module.aws_provider"]
}

And run terraform graph | dot -Tpng > graph.png against it it looks like the graph doesn't change at all from when the explicit dependency isn't there.

This seems like it might be a potential bug in the graph building stage in Terraform that should probably be raised as an issue but I don't know the core code base well enough to spot where the change needs to be.

For our usage we use symlinks heavily in our Terraform code base, some of which is historic from before Terraform supported other ways of doing things but could work for you here.

We simply define the provider in a single .tf file (such as environment.tf) along with any other generic config needed for every place you would ever run Terraform (ie not at a module level) and then symlink this into each location. That allows us to define the provider in a single place with overridable variables if necessary.

like image 93
ydaetskcoR Avatar answered Sep 25 '22 13:09

ydaetskcoR