Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create Terraform sub-module

I'm using Terraform to manage AWS resources, I have a module, the source for it is the whole terraform folder, but now I want to create a sub-module under this module for A.tf and B.tf files, so that when I apply terraform, if I specify this submodule, Terraform doesn't have to create all the resources outside of this sub-module.

I've tried a couple of thing but still not working, is there any example I can follow?

like image 667
wawawa Avatar asked Sep 05 '25 01:09

wawawa


1 Answers

As @luk2302 pointed it would be good to create composable modules rather than submodules.

anyways I was able to create something as you asked.

❯❯ tree
.
├── main.tf
├── sub_module_1
│   └── main.tf
├── sub_module_2
│   └── main.tf
└── terraform.tfstate

2 directories, 4 files
tmp/boo/parent_module
❯❯ ls
main.tf            sub_module_1/      sub_module_2/      terraform.tfstate
❯❯ terraform state list
aws_iam_role_policy_attachment.lambda_logs
aws_sns_topic.user_updates
module.iam_role_info.aws_iam_role.iam_for_lambda
module.logging_policy.aws_iam_policy.lambda_logging
❯❯ ls
main.tf        parent_module/
/private/tmp/boo
❯❯ cat main.tf
variable "env" {
  type    = string
  default = "dev"
}
locals {
  default_tags = {
    Product     = "wallaby",
    Environment = var.env,
    Application = "wallaby-api"
  }
}

module "parent_module" {
source = "./parent_module"
}

output "sns_info" {
  value = module.parent_module.sns_info
}

in the root of the parent_module main.tf

❯❯ cat main.tf
module "iam_role_info" {
  source = "./sub_module_1"
}

module "logging_policy" {
  source = "./sub_module_2"
}

resource "aws_iam_role_policy_attachment" "lambda_logs" {
  role       = module.iam_role_info.lambda_role_name
  policy_arn = module.logging_policy.iam_policy_arn
}

resource "aws_sns_topic" "user_updates" {
  name = "user-updates-topic"
}

output "sns_info" {
  value = aws_sns_topic.user_updates.arn
}
❯❯ cat sub_module_1/main.tf
resource "aws_iam_role" "iam_for_lambda" {
  name = "iam_for_lambda"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

output "lambda_role_name" {
    value = aws_iam_role.iam_for_lambda.name
}
❯❯ cat sub_module_2/main.tf
# See also the following AWS managed policy: AWSLambdaBasicExecutionRole
resource "aws_iam_policy" "lambda_logging" {
  name        = "lambda_logging"
  path        = "/"
  description = "IAM policy for logging from a lambda"

  policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*",
      "Effect": "Allow"
    }
  ]
}
EOF
}

output "iam_policy_arn" {
value = aws_iam_policy.lambda_logging.arn
like image 133
samtoddler Avatar answered Sep 07 '25 17:09

samtoddler