├── _modules
│ ├── network
│ │ ├── dev
│ │ │ └── main.tf
│ │ ├── nonprod
│ │ │ └── main.tf
│ │ └── prod
│ │ └── main.tf
│ └── services
│ ├── dev
│ │ └── main.tf
│ ├── nonprod
│ │ └── main.tf
│ └── prod
│ └── main.tf
├── dev
│ ├── main.tf
│ └── vars.tf
├── nonprod
│ ├── main.tf
│ └── vars.tf
├── prod
├── main.tf
└── vars.tf
This is a simple main.tf that has separated modules for activating APIs and subnetworks for a new project. This terraform skeleton also shows how to benifit from breaking down sections into modules plus uses examples on how to execute simple logic like count.index
and for_each
to keep the terraform code minimal. The goal of this is to create multi environment deployment from a single repo.
- The network module uses a
for_each
loop
resource "google_compute_subnetwork" "default" {
for_each = local.subnet_data
project = "${var.project}"
name = "${var.name}"
ip_cidr_range = each.value
region = each.key
network = "${google_compute_network.default.self_link}"
}
- The services module activates a
count.index
parameter
resource "google_project_service" "project_services" {
project = "${var.project}"
count = "${length(local.api_list)}"
service = "${element(local.api_list, count.index)}"
}
Generally speaking as each environment goes up (dev -> nonprod -> prod) security for a project becomes more strict. To achieve this change the environments main.tf modules source to point at the corresponding module environments folder.
_modules/services/dev/main.tf
into _modules/services/nonprod/main.tf
then reduce the amout of API's that are enabled or remove subnets upon project creation.
Inside the modules folder /_modules/services/nonprod/main.tf
alter the list of APIs that get enabled. The same goes for /_modules/services/prod/main.tf
file.
In each environment the only part that changes per environment main.tf is the source part of the module.
module "api_services" {
source = "../_modules/services/dev/"
project = "${data.google_project_services.project.project}"
}
module "api_services" {
source = "../_modules/services/nonprod/"
project = "${data.google_project_services.project.project}"
}
The commands are the same but to deploy a specific environment the terraform plan
and terraform apply
must contain the folder.
For example:
To deploy a dev environment - (from the root directory)
terraform init /dev
terraform plan /dev
terraform apply /dev
To deploy a nonprod environment - (from the root directory)
terraform init /nonprod
terraform plan /nonprod
terraform apply /nonprod