Skip to content

Instantly share code, notes, and snippets.

@rkhullar
Last active September 10, 2023 23:39
Show Gist options
  • Save rkhullar/a244ec2fd1bc958fffc4ce3a44ed613e to your computer and use it in GitHub Desktop.
Save rkhullar/a244ec2fd1bc958fffc4ce3a44ed613e to your computer and use it in GitHub Desktop.
tutorials/terraform-project-structure
locals {
account_id = "REDACTED"
}
terraform {
source = "git::git@github.com:company/example-infra-modules//api?ref=0.1.0"
}
include {
path = find_in_parent_folders()
}
inputs = {
enable_dns = true
hosted_zone = "example.company.org"
domain = {
name = "api-dev.example.company.org",
cert = "example.company.org"
}
}
terraform {
source = "git::git@github.com:company/example-infra-modules//iam?ref=0.1.0"
}
include {
path = find_in_parent_folders()
}
inputs = {}
terraform {
source = "git::git@github.com:company/example-infra-modules//lambdas?ref=0.1.0"
}
include {
path = find_in_parent_folders()
}
inputs = {}
locals {
account = "workloads"
project = "example"
owner = "engineering@company.org"
namespace = "company"
default_region = "us-east-1"
}
locals {
common_vars = read_terragrunt_config(find_in_parent_folders("common.hcl"))
account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl"))
path_parts = split("/", path_relative_to_include())
path_parts_len = length(local.path_parts)
account = local.common_vars.locals.account
project = local.common_vars.locals.project
owner = local.common_vars.locals.owner
namespace = local.common_vars.locals.namespace
default_region = local.common_vars.locals.default_region
account_id = local.account_vars.locals.account_id
construct = local.path_parts[local.path_parts_len - 1]
environment = local.path_parts[local.path_parts_len - 2]
region_path = local.path_parts[local.path_parts_len - 3]
region = local.region_path != "_global" ? local.region_path : local.default_region
}
inputs = {
account = local.account
project = local.project
owner = local.owner
namespace = local.namespace
account_id = local.account_id
environment = local.environment
region = local.region
default_region = local.default_region
}
remote_state {
backend = "s3"
config = {
bucket = "${local.project}-terraformstate-${local.region}-${local.environment}-${local.namespace}"
key = "${local.construct}/terraform.tfstate"
dynamodb_table = "${local.project}-terraformlock-${local.region}-${local.environment}-${local.namespace}"
region = local.region
encrypt = true
s3_bucket_tags = {
name = "Terraform Remote State"
account = local.account
project = local.project
owner = local.owner
namespace = local.namespace
environment = local.environment
region = local.region
managed = "terraform"
}
dynamodb_table_tags = {
name = "Terraform Lock Table"
account = local.account
project = local.project
owner = local.owner
namespace = local.namespace
environment = local.environment
region = local.region
managed = "terraform"
}
}
}
|-- common.hcl
|-- terragrunt.hcl
`-- ${account}
|-- account.hcl
`-- ${region}
`-- ${construct}
`-- terragrunt.hcl
|-- common.hcl
|-- terragrunt.hcl
|-- non-prod
| |-- account.hcl
| |-- _global
| | |-- dev
| | | `-- iam
| | | `-- terragrunt.hcl
| | `-- stage
| | `-- iam
| | `-- terragrunt.hcl
| `-- us-east-1
| |-- dev
| | |-- api
| | | `-- terragrunt.hcl
| | `-- lambdas
| | `-- terragrunt.hcl
| `-- stage
| |-- api
| | `-- terragrunt.hcl
| `-- lambdas
| `-- terragrunt.hcl
`-- prod
|-- account.hcl
|-- _global
| `-- prod
| `-- iam
| `-- terragrunt.hcl
`-- us-east-1
`-- prod
|-- api
| `-- terragrunt.hcl
`-- lambdas
`-- terragrunt.hcl
module "fastapi-http" {
source = "github.com/rkhullar/terraform-modules//aws/apigw/http-api?ref=0.3.4"
name = "${local.prefix}-fastapi-${local.suffix}"
lambda_function_name = local.lambda_function_names["fastapi"]
tags = local.common_tags
jwt_auth = {
name = var.okta_host
issuer = "https://${var.okta_host}/oauth2/default"
audience = "api://default"
}
extra_routes = [
{ method = "get", path = "/docs" },
{ method = "get", path = "/docs/oauth2-redirect" },
{ method = "get", path = "/openapi.json" }
]
}
data "aws_acm_certificate" "default" {
domain = var.domain.cert
}
resource "aws_apigatewayv2_domain_name" "default" {
domain_name = var.domain.name
tags = local.common_tags
domain_name_configuration {
certificate_arn = data.aws_acm_certificate.default.arn
endpoint_type = "REGIONAL"
security_policy = "TLS_1_2"
}
}
locals {
domain_name = aws_apigatewayv2_domain_name.default.id
target_domain_name = aws_apigatewayv2_domain_name.default.domain_name_configuration[0].target_domain_name
}
resource "aws_apigatewayv2_api_mapping" "fastapi-http" {
domain_name = aws_apigatewayv2_domain_name.default.domain_name
api_id = module.fastapi-http.api_id
stage = module.fastapi-http.stage_id
}
data "aws_route53_zone" "default" {
count = var.enable_dns ? 1 : 0
name = var.hosted_zone
}
resource "aws_route53_record" "default" {
count = var.enable_dns ? 1 : 0
zone_id = data.aws_route53_zone.default[0].zone_id
name = local.domain_name
type = "A"
alias {
name = local.target_domain_name
zone_id = aws_apigatewayv2_domain_name.default.domain_name_configuration[0].hosted_zone_id
evaluate_target_health = false
}
}
# module
variable "domain" {
type = object({
name = string
cert = string
})
}
variable "hosted_zone" {
type = string
nullable = true
}
variable "enable_dns" {
type = bool
nullable = false
default = true
}
variable "okta_host" {
type = string
nullable = false
}
# output
locals {
dns_record_type = var.enable_dns ? "alias" : "cname"
}
output "dns" {
value = {
"${local.dns_record_type}" = {
"${local.domain_name}" = local.target_domain_name
}
}
}
locals {
tf_bucket = "${var.project}-terraformstate-${var.region}-${var.environment}-${var.namespace}"
}
data "terraform_remote_state" "lambdas" {
backend = "s3"
config = {
bucket = local.tf_bucket
key = "lambdas/terraform.tfstate"
region = var.region
}
}
locals {
remote_lambdas = data.terraform_remote_state.lambdas.outputs
lambda_function_names = local.remote_lambdas["lambdas"]
}
# general
variable "account" { type = string }
variable "project" { type = string }
variable "owner" { type = string }
variable "namespace" { type = string }
variable "account_id" { type = string }
variable "environment" { type = string }
variable "region" { type = string }
variable "default_region" { type = string }
locals {
common_tags = {
account = var.account
project = var.project
owner = var.owner
namespace = var.namespace
environment = var.environment
region = var.region
managed = "terraform"
}
}
locals {
prefix = var.project
suffix = "${var.environment}-${var.namespace}"
}
terraform {
backend "s3" {}
required_version = "~> 1.5"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.region
allowed_account_ids = [var.account_id]
}
module "fastapi-lambda-role" {
source = "github.com/rkhullar/terraform-modules//aws/iam/role?ref=0.1.0"
name = "${local.prefix}-fastapi-lambda-${local.suffix}"
tags = local.common_tags
principals = [{ type = "Service", identifiers = ["lambda.amazonaws.com"] }]
managed_policies = [
"service-role/AWSLambdaBasicExecutionRole"
]
}
# output
output "roles" {
value = {
lambda = {
fastapi = module.fastapi-lambda-role.output["name"]
}
}
}
module "fastapi-lambda" {
source = "github.com/rkhullar/terraform-modules//aws/lambda/function?ref=0.2.3"
name = "${local.prefix}-fastapi-${local.suffix}"
tags = local.common_tags
role = local.lambda_roles["fastapi"]
runtime = "python3.11"
handler = "lambda_function.lambda_handler"
architecture = "arm64"
environment = {
PROJECT = var.project
ENVIRONMENT = var.environment
}
}
# output
output "lambdas" {
value = {
fastapi = module.fastapi-lambda.output["function_name"]
}
}
locals {
tf_bucket_global = "${var.project}-terraformstate-${var.default_region}-${var.environment}-${var.namespace}"
}
data "terraform_remote_state" "iam" {
backend = "s3"
config = {
bucket = local.tf_bucket_global
key = "iam/terraform.tfstate"
region = var.default_region
}
}
locals {
lambda_roles = data.terraform_remote_state.iam.outputs["roles"]["lambda"]
}
|-- api
| |-- default.tf
| |-- interface.tf
| |-- locals.tf
| |-- provider.tf
| `-- remotes.tf
|-- iam
| |-- default.tf
| |-- interface.tf
| |-- locals.tf
| `-- provider.tf
`-- lambdas
|-- default.tf
|-- interface.tf
|-- locals.tf
|-- provider.tf
`-- remotes.tf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment