1
votes

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?

1
That is generally not what modules are for, modules are for organizing resources that belong together and hiding the internal complexity from the outside user of the module. Deploying the infrastructure will always deploy everything unless you specify a --target ....luk2302

1 Answers

2
votes

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