0
votes

I want to start a new Terraform project that will deploy resources on a GCP account. I want to use Terragrunt to provision multiple environments (test,dev,prod).

Essentially each environment will be the same except the names of the resources will have a prefix (environment name) and the resources will be in another region. I also want to keep it DRY with terragrunt.

So far I only have this desired folder structure:

project
└── env
    └── test
    └── dev
    └── prod
└── resources
    └── vpc
    └── pubsub
    └── cloudrun
    └── resource4

I am confused by Terragrunt and Terraform is overwhelming. I have little experience with it, I mostly know CloudFormation on AWS.

So where should I put terragrunt.hcl file and what should be inside it? Where do I store the resources variables and how to I force resources to use env variables (region and prefix). What command should I use to deploy the specific environment?

1
I would recommend you read the guide on terraform: terragrunt.gruntwork.io/docs/getting-started/quick-startLukeTerro

1 Answers

1
votes

Here's a quick example. Azure is the provider here but that doesn't change the way modules are organized.

This assumes you're using local TF state (probably you'd want to set up a remote state).

Also modules are referenced from the local file system here. You can store them in a separate Git repo (Terragrunt suggested way) for versioning.

An example reusable module at project/resources/resource_group/main.tf:

terraform {
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = "~> 2.26"
    }
  }
}

resource "azurerm_resource_group" "resource_group" {
  name     = "${var.project}-${var.environment}-resource-group"
  location = var.location

  tags = {
    project     = var.project
    environment = var.environment
    region      = var.location
  }
}

# I've included variables and outputs in the same file, 
# but it's recommended to put them into separate 
# variables.tf and outputs.tf respectively.

variable "project" {
  type        = string
  description = "Project name"
}

variable "environment" {
  type        = string
  description = "Environment (dev / stage / prod)"
}

variable "location" {
  type        = string
  description = "The Azure Region where the Resource Group should exist"
}

output "resource_group_name" {
  value = azurerm_resource_group.resource_group.name
}

An example usage of the module in a given environment. Module path is project/test/resource_group/terragrunt.hcl:

generate "provider" {
  path = "provider.tf"
  if_exists = "overwrite_terragrunt"
  contents = <<EOF
provider "azurerm" {
  features {}
}
EOF
}

terraform {
  source = "../../resources//resource_group"
}

inputs = {
  project = "myapp"
  environment = "test"
  location = "East US"
}

To deploy that specific module (likely it will have more than one resource, unlike in my example), you run terragrunt apply from project/test/resource_group.

Alternatively you can execute multiple modules by running terragrunt apply-all from project/test.

Honestly, if you're going to use it for projects in production, you better go through Terragrunt documentation, it's quite good.