tf-starter 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +421 -0
- package/bin/tf-starter.js +88 -0
- package/package.json +43 -0
- package/scripts/postinstall.js +105 -0
- package/setup.py +32 -0
- package/tf_starter/__init__.py +3 -0
- package/tf_starter/__main__.py +6 -0
- package/tf_starter/cli.py +379 -0
- package/tf_starter/generator.py +171 -0
- package/tf_starter/template_engine.py +80 -0
- package/tf_starter/templates/aws/environments/backend.tf.j2 +16 -0
- package/tf_starter/templates/aws/environments/main.tf.j2 +85 -0
- package/tf_starter/templates/aws/environments/terraform.tfvars.j2 +52 -0
- package/tf_starter/templates/aws/environments/variables.tf.j2 +127 -0
- package/tf_starter/templates/aws/github/terraform.yml.j2 +133 -0
- package/tf_starter/templates/aws/misc/Makefile.j2 +60 -0
- package/tf_starter/templates/aws/misc/README.md.j2 +445 -0
- package/tf_starter/templates/aws/misc/init.sh.j2 +110 -0
- package/tf_starter/templates/aws/misc/pre-commit-config.yaml.j2 +34 -0
- package/tf_starter/templates/aws/modules/apigateway/main.tf.j2 +224 -0
- package/tf_starter/templates/aws/modules/apigateway/outputs.tf.j2 +28 -0
- package/tf_starter/templates/aws/modules/apigateway/variables.tf.j2 +69 -0
- package/tf_starter/templates/aws/modules/compute/main.tf.j2 +245 -0
- package/tf_starter/templates/aws/modules/compute/outputs.tf.j2 +38 -0
- package/tf_starter/templates/aws/modules/compute/variables.tf.j2 +68 -0
- package/tf_starter/templates/aws/modules/database/main.tf.j2 +122 -0
- package/tf_starter/templates/aws/modules/database/outputs.tf.j2 +33 -0
- package/tf_starter/templates/aws/modules/database/variables.tf.j2 +63 -0
- package/tf_starter/templates/aws/modules/kubernetes/main.tf.j2 +167 -0
- package/tf_starter/templates/aws/modules/kubernetes/outputs.tf.j2 +33 -0
- package/tf_starter/templates/aws/modules/kubernetes/variables.tf.j2 +64 -0
- package/tf_starter/templates/aws/modules/lambda/main.tf.j2 +215 -0
- package/tf_starter/templates/aws/modules/lambda/outputs.tf.j2 +38 -0
- package/tf_starter/templates/aws/modules/lambda/variables.tf.j2 +88 -0
- package/tf_starter/templates/aws/modules/messaging/main.tf.j2 +85 -0
- package/tf_starter/templates/aws/modules/messaging/outputs.tf.j2 +28 -0
- package/tf_starter/templates/aws/modules/messaging/variables.tf.j2 +41 -0
- package/tf_starter/templates/aws/modules/monitoring/main.tf.j2 +155 -0
- package/tf_starter/templates/aws/modules/monitoring/outputs.tf.j2 +23 -0
- package/tf_starter/templates/aws/modules/monitoring/variables.tf.j2 +39 -0
- package/tf_starter/templates/aws/modules/network/main.tf.j2 +147 -0
- package/tf_starter/templates/aws/modules/network/outputs.tf.j2 +33 -0
- package/tf_starter/templates/aws/modules/network/variables.tf.j2 +52 -0
- package/tf_starter/templates/aws/modules/storage/main.tf.j2 +88 -0
- package/tf_starter/templates/aws/modules/storage/outputs.tf.j2 +23 -0
- package/tf_starter/templates/aws/modules/storage/variables.tf.j2 +25 -0
- package/tf_starter/templates/aws/root/backend.tf.j2 +19 -0
- package/tf_starter/templates/aws/root/main.tf.j2 +219 -0
- package/tf_starter/templates/aws/root/outputs.tf.j2 +134 -0
- package/tf_starter/templates/aws/root/providers.tf.j2 +24 -0
- package/tf_starter/templates/aws/root/variables.tf.j2 +300 -0
- package/tf_starter/templates/aws/root/versions.tf.j2 +26 -0
- package/tf_starter/templates/azure/environments/backend.tf.j2 +11 -0
- package/tf_starter/templates/azure/environments/main.tf.j2 +57 -0
- package/tf_starter/templates/azure/environments/terraform.tfvars.j2 +14 -0
- package/tf_starter/templates/azure/environments/variables.tf.j2 +30 -0
- package/tf_starter/templates/azure/github/terraform.yml.j2 +133 -0
- package/tf_starter/templates/azure/misc/Makefile.j2 +60 -0
- package/tf_starter/templates/azure/misc/README.md.j2 +426 -0
- package/tf_starter/templates/azure/misc/init.sh.j2 +110 -0
- package/tf_starter/templates/azure/misc/pre-commit-config.yaml.j2 +34 -0
- package/tf_starter/templates/azure/modules/apigateway/main.tf.j2 +125 -0
- package/tf_starter/templates/azure/modules/apigateway/outputs.tf.j2 +18 -0
- package/tf_starter/templates/azure/modules/apigateway/variables.tf.j2 +54 -0
- package/tf_starter/templates/azure/modules/compute/main.tf.j2 +114 -0
- package/tf_starter/templates/azure/modules/compute/outputs.tf.j2 +9 -0
- package/tf_starter/templates/azure/modules/compute/variables.tf.j2 +23 -0
- package/tf_starter/templates/azure/modules/database/main.tf.j2 +56 -0
- package/tf_starter/templates/azure/modules/database/outputs.tf.j2 +13 -0
- package/tf_starter/templates/azure/modules/database/variables.tf.j2 +38 -0
- package/tf_starter/templates/azure/modules/kubernetes/main.tf.j2 +50 -0
- package/tf_starter/templates/azure/modules/kubernetes/outputs.tf.j2 +19 -0
- package/tf_starter/templates/azure/modules/kubernetes/variables.tf.j2 +37 -0
- package/tf_starter/templates/azure/modules/lambda/main.tf.j2 +98 -0
- package/tf_starter/templates/azure/modules/lambda/outputs.tf.j2 +23 -0
- package/tf_starter/templates/azure/modules/lambda/variables.tf.j2 +53 -0
- package/tf_starter/templates/azure/modules/messaging/main.tf.j2 +29 -0
- package/tf_starter/templates/azure/modules/messaging/outputs.tf.j2 +14 -0
- package/tf_starter/templates/azure/modules/messaging/variables.tf.j2 +11 -0
- package/tf_starter/templates/azure/modules/monitoring/main.tf.j2 +31 -0
- package/tf_starter/templates/azure/modules/monitoring/outputs.tf.j2 +9 -0
- package/tf_starter/templates/azure/modules/monitoring/variables.tf.j2 +16 -0
- package/tf_starter/templates/azure/modules/network/main.tf.j2 +89 -0
- package/tf_starter/templates/azure/modules/network/outputs.tf.j2 +25 -0
- package/tf_starter/templates/azure/modules/network/variables.tf.j2 +25 -0
- package/tf_starter/templates/azure/modules/storage/main.tf.j2 +41 -0
- package/tf_starter/templates/azure/modules/storage/outputs.tf.j2 +17 -0
- package/tf_starter/templates/azure/modules/storage/variables.tf.j2 +16 -0
- package/tf_starter/templates/azure/root/backend.tf.j2 +11 -0
- package/tf_starter/templates/azure/root/main.tf.j2 +181 -0
- package/tf_starter/templates/azure/root/outputs.tf.j2 +45 -0
- package/tf_starter/templates/azure/root/providers.tf.j2 +18 -0
- package/tf_starter/templates/azure/root/variables.tf.j2 +114 -0
- package/tf_starter/templates/azure/root/versions.tf.j2 +16 -0
- package/tf_starter/templates/gcp/environments/backend.tf.j2 +9 -0
- package/tf_starter/templates/gcp/environments/main.tf.j2 +58 -0
- package/tf_starter/templates/gcp/environments/terraform.tfvars.j2 +12 -0
- package/tf_starter/templates/gcp/environments/variables.tf.j2 +21 -0
- package/tf_starter/templates/gcp/github/terraform.yml.j2 +133 -0
- package/tf_starter/templates/gcp/misc/Makefile.j2 +60 -0
- package/tf_starter/templates/gcp/misc/README.md.j2 +426 -0
- package/tf_starter/templates/gcp/misc/init.sh.j2 +110 -0
- package/tf_starter/templates/gcp/misc/pre-commit-config.yaml.j2 +34 -0
- package/tf_starter/templates/gcp/modules/apigateway/main.tf.j2 +67 -0
- package/tf_starter/templates/gcp/modules/apigateway/outputs.tf.j2 +18 -0
- package/tf_starter/templates/gcp/modules/apigateway/variables.tf.j2 +34 -0
- package/tf_starter/templates/gcp/modules/compute/main.tf.j2 +138 -0
- package/tf_starter/templates/gcp/modules/compute/outputs.tf.j2 +13 -0
- package/tf_starter/templates/gcp/modules/compute/variables.tf.j2 +33 -0
- package/tf_starter/templates/gcp/modules/database/main.tf.j2 +62 -0
- package/tf_starter/templates/gcp/modules/database/outputs.tf.j2 +13 -0
- package/tf_starter/templates/gcp/modules/database/variables.tf.j2 +29 -0
- package/tf_starter/templates/gcp/modules/kubernetes/main.tf.j2 +75 -0
- package/tf_starter/templates/gcp/modules/kubernetes/outputs.tf.j2 +14 -0
- package/tf_starter/templates/gcp/modules/kubernetes/variables.tf.j2 +38 -0
- package/tf_starter/templates/gcp/modules/lambda/main.tf.j2 +122 -0
- package/tf_starter/templates/gcp/modules/lambda/outputs.tf.j2 +18 -0
- package/tf_starter/templates/gcp/modules/lambda/variables.tf.j2 +77 -0
- package/tf_starter/templates/gcp/modules/messaging/main.tf.j2 +44 -0
- package/tf_starter/templates/gcp/modules/messaging/outputs.tf.j2 +13 -0
- package/tf_starter/templates/gcp/modules/messaging/variables.tf.j2 +20 -0
- package/tf_starter/templates/gcp/modules/monitoring/main.tf.j2 +44 -0
- package/tf_starter/templates/gcp/modules/monitoring/outputs.tf.j2 +9 -0
- package/tf_starter/templates/gcp/modules/monitoring/variables.tf.j2 +13 -0
- package/tf_starter/templates/gcp/modules/network/main.tf.j2 +103 -0
- package/tf_starter/templates/gcp/modules/network/outputs.tf.j2 +21 -0
- package/tf_starter/templates/gcp/modules/network/variables.tf.j2 +22 -0
- package/tf_starter/templates/gcp/modules/storage/main.tf.j2 +47 -0
- package/tf_starter/templates/gcp/modules/storage/outputs.tf.j2 +13 -0
- package/tf_starter/templates/gcp/modules/storage/variables.tf.j2 +16 -0
- package/tf_starter/templates/gcp/root/backend.tf.j2 +12 -0
- package/tf_starter/templates/gcp/root/main.tf.j2 +210 -0
- package/tf_starter/templates/gcp/root/outputs.tf.j2 +61 -0
- package/tf_starter/templates/gcp/root/providers.tf.j2 +18 -0
- package/tf_starter/templates/gcp/root/variables.tf.j2 +140 -0
- package/tf_starter/templates/gcp/root/versions.tf.j2 +23 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
# LAMBDA MODULE — Outputs
|
|
3
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
output "function_name" {
|
|
6
|
+
description = "Name of the Lambda function"
|
|
7
|
+
value = aws_lambda_function.main.function_name
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
output "function_arn" {
|
|
11
|
+
description = "ARN of the Lambda function"
|
|
12
|
+
value = aws_lambda_function.main.arn
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
output "invoke_arn" {
|
|
16
|
+
description = "Invocation ARN of the Lambda function (for API Gateway)"
|
|
17
|
+
value = aws_lambda_function.main.invoke_arn
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
output "function_role_arn" {
|
|
21
|
+
description = "ARN of the Lambda execution IAM role"
|
|
22
|
+
value = aws_iam_role.lambda.arn
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
output "function_role_name" {
|
|
26
|
+
description = "Name of the Lambda execution IAM role"
|
|
27
|
+
value = aws_iam_role.lambda.name
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
output "alias_arn" {
|
|
31
|
+
description = "ARN of the live alias"
|
|
32
|
+
value = aws_lambda_alias.live.arn
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
output "log_group_name" {
|
|
36
|
+
description = "CloudWatch log group for the Lambda function"
|
|
37
|
+
value = aws_cloudwatch_log_group.lambda.name
|
|
38
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
# LAMBDA MODULE — Variables
|
|
3
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
variable "project_name" {
|
|
6
|
+
description = "Name of the project"
|
|
7
|
+
type = string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
variable "environment" {
|
|
11
|
+
description = "Deployment environment"
|
|
12
|
+
type = string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
variable "function_name" {
|
|
16
|
+
description = "Short name for the Lambda function (appended to project-env prefix)"
|
|
17
|
+
type = string
|
|
18
|
+
default = "app"
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
variable "runtime" {
|
|
22
|
+
description = "Lambda runtime identifier"
|
|
23
|
+
type = string
|
|
24
|
+
default = "python3.12"
|
|
25
|
+
|
|
26
|
+
validation {
|
|
27
|
+
condition = can(regex("^(python3\\.|nodejs|java|dotnet|ruby|provided)", var.runtime))
|
|
28
|
+
error_message = "Must be a valid Lambda runtime (e.g., python3.12, nodejs20.x)."
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
variable "handler" {
|
|
33
|
+
description = "Lambda function handler"
|
|
34
|
+
type = string
|
|
35
|
+
default = "index.handler"
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
variable "timeout" {
|
|
39
|
+
description = "Lambda function timeout in seconds"
|
|
40
|
+
type = number
|
|
41
|
+
default = 30
|
|
42
|
+
|
|
43
|
+
validation {
|
|
44
|
+
condition = var.timeout >= 1 && var.timeout <= 900
|
|
45
|
+
error_message = "Timeout must be between 1 and 900 seconds."
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
variable "memory_size" {
|
|
50
|
+
description = "Lambda function memory in MB"
|
|
51
|
+
type = number
|
|
52
|
+
default = 256
|
|
53
|
+
|
|
54
|
+
validation {
|
|
55
|
+
condition = var.memory_size >= 128 && var.memory_size <= 10240
|
|
56
|
+
error_message = "Memory must be between 128 and 10240 MB."
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
variable "environment_variables" {
|
|
61
|
+
description = "Additional environment variables for the Lambda function"
|
|
62
|
+
type = map(string)
|
|
63
|
+
default = {}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
variable "deploy_in_vpc" {
|
|
67
|
+
description = "Deploy the Lambda function inside the VPC"
|
|
68
|
+
type = bool
|
|
69
|
+
default = false
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
variable "vpc_id" {
|
|
73
|
+
description = "VPC ID (required if deploy_in_vpc is true)"
|
|
74
|
+
type = string
|
|
75
|
+
default = ""
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
variable "private_subnet_ids" {
|
|
79
|
+
description = "Private subnet IDs (required if deploy_in_vpc is true)"
|
|
80
|
+
type = list(string)
|
|
81
|
+
default = []
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
variable "tags" {
|
|
85
|
+
description = "Common resource tags"
|
|
86
|
+
type = map(string)
|
|
87
|
+
default = {}
|
|
88
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
# MESSAGING MODULE — Amazon SQS
|
|
3
|
+
# Project: {{ project_name }}
|
|
4
|
+
# Generated by tf-starter
|
|
5
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
6
|
+
|
|
7
|
+
locals {
|
|
8
|
+
name_prefix = "${var.project_name}-${var.environment}"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
12
|
+
# SQS QUEUE
|
|
13
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
resource "aws_sqs_queue" "main" {
|
|
16
|
+
name = "${local.name_prefix}-queue"
|
|
17
|
+
|
|
18
|
+
message_retention_seconds = var.message_retention_seconds
|
|
19
|
+
visibility_timeout_seconds = var.visibility_timeout
|
|
20
|
+
receive_wait_time_seconds = 10 # Long polling
|
|
21
|
+
|
|
22
|
+
# Encryption at rest
|
|
23
|
+
sqs_managed_sse_enabled = true
|
|
24
|
+
|
|
25
|
+
tags = merge(var.tags, {
|
|
26
|
+
Name = "${local.name_prefix}-queue"
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
31
|
+
# DEAD LETTER QUEUE
|
|
32
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
33
|
+
|
|
34
|
+
resource "aws_sqs_queue" "dlq" {
|
|
35
|
+
name = "${local.name_prefix}-dlq"
|
|
36
|
+
|
|
37
|
+
message_retention_seconds = 1209600 # 14 days
|
|
38
|
+
|
|
39
|
+
sqs_managed_sse_enabled = true
|
|
40
|
+
|
|
41
|
+
tags = merge(var.tags, {
|
|
42
|
+
Name = "${local.name_prefix}-dlq"
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
resource "aws_sqs_queue_redrive_policy" "main" {
|
|
47
|
+
queue_url = aws_sqs_queue.main.id
|
|
48
|
+
|
|
49
|
+
redrive_policy = jsonencode({
|
|
50
|
+
deadLetterTargetArn = aws_sqs_queue.dlq.arn
|
|
51
|
+
maxReceiveCount = 3
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
resource "aws_sqs_queue_redrive_allow_policy" "dlq" {
|
|
56
|
+
queue_url = aws_sqs_queue.dlq.id
|
|
57
|
+
|
|
58
|
+
redrive_allow_policy = jsonencode({
|
|
59
|
+
redrivePermission = "byQueue"
|
|
60
|
+
sourceQueueArns = [aws_sqs_queue.main.arn]
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
65
|
+
# SQS QUEUE POLICY — restrict access to same account
|
|
66
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
67
|
+
|
|
68
|
+
data "aws_caller_identity" "current" {}
|
|
69
|
+
|
|
70
|
+
resource "aws_sqs_queue_policy" "main" {
|
|
71
|
+
queue_url = aws_sqs_queue.main.id
|
|
72
|
+
|
|
73
|
+
policy = jsonencode({
|
|
74
|
+
Version = "2012-10-17"
|
|
75
|
+
Statement = [
|
|
76
|
+
{
|
|
77
|
+
Sid = "AllowSameAccountAccess"
|
|
78
|
+
Effect = "Allow"
|
|
79
|
+
Principal = { AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root" }
|
|
80
|
+
Action = "sqs:*"
|
|
81
|
+
Resource = aws_sqs_queue.main.arn
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
})
|
|
85
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
# MESSAGING MODULE — Outputs
|
|
3
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
output "queue_url" {
|
|
6
|
+
description = "URL of the SQS queue"
|
|
7
|
+
value = aws_sqs_queue.main.url
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
output "queue_arn" {
|
|
11
|
+
description = "ARN of the SQS queue"
|
|
12
|
+
value = aws_sqs_queue.main.arn
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
output "queue_name" {
|
|
16
|
+
description = "Name of the SQS queue"
|
|
17
|
+
value = aws_sqs_queue.main.name
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
output "dlq_url" {
|
|
21
|
+
description = "URL of the dead-letter queue"
|
|
22
|
+
value = aws_sqs_queue.dlq.url
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
output "dlq_arn" {
|
|
26
|
+
description = "ARN of the dead-letter queue"
|
|
27
|
+
value = aws_sqs_queue.dlq.arn
|
|
28
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
# MESSAGING MODULE — Variables
|
|
3
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
variable "project_name" {
|
|
6
|
+
description = "Name of the project"
|
|
7
|
+
type = string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
variable "environment" {
|
|
11
|
+
description = "Deployment environment"
|
|
12
|
+
type = string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
variable "message_retention_seconds" {
|
|
16
|
+
description = "Number of seconds to retain messages"
|
|
17
|
+
type = number
|
|
18
|
+
default = 345600 # 4 days
|
|
19
|
+
|
|
20
|
+
validation {
|
|
21
|
+
condition = var.message_retention_seconds >= 60 && var.message_retention_seconds <= 1209600
|
|
22
|
+
error_message = "Retention must be between 60 and 1209600 seconds."
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
variable "visibility_timeout" {
|
|
27
|
+
description = "Visibility timeout in seconds"
|
|
28
|
+
type = number
|
|
29
|
+
default = 30
|
|
30
|
+
|
|
31
|
+
validation {
|
|
32
|
+
condition = var.visibility_timeout >= 0 && var.visibility_timeout <= 43200
|
|
33
|
+
error_message = "Visibility timeout must be between 0 and 43200 seconds."
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
variable "tags" {
|
|
38
|
+
description = "Common resource tags"
|
|
39
|
+
type = map(string)
|
|
40
|
+
default = {}
|
|
41
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
# MONITORING MODULE — CloudWatch Alarms, SNS Notifications
|
|
3
|
+
# Project: {{ project_name }}
|
|
4
|
+
# Generated by tf-starter
|
|
5
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
6
|
+
|
|
7
|
+
locals {
|
|
8
|
+
name_prefix = "${var.project_name}-${var.environment}"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
12
|
+
# SNS TOPIC FOR ALARMS
|
|
13
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
resource "aws_sns_topic" "alarms" {
|
|
16
|
+
name = "${local.name_prefix}-alarms"
|
|
17
|
+
|
|
18
|
+
tags = merge(var.tags, {
|
|
19
|
+
Name = "${local.name_prefix}-alarms"
|
|
20
|
+
})
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
resource "aws_sns_topic_subscription" "email" {
|
|
24
|
+
count = var.alarm_email != "" ? 1 : 0
|
|
25
|
+
|
|
26
|
+
topic_arn = aws_sns_topic.alarms.arn
|
|
27
|
+
protocol = "email"
|
|
28
|
+
endpoint = var.alarm_email
|
|
29
|
+
|
|
30
|
+
### MUST EDIT THIS ###
|
|
31
|
+
# The email subscription must be confirmed manually via the confirmation email.
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
{% if "compute" in services %}
|
|
35
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
36
|
+
# CLOUDWATCH ALARMS — COMPUTE (ASG)
|
|
37
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
resource "aws_cloudwatch_metric_alarm" "high_cpu" {
|
|
40
|
+
alarm_name = "${local.name_prefix}-high-cpu"
|
|
41
|
+
comparison_operator = "GreaterThanThreshold"
|
|
42
|
+
evaluation_periods = 2
|
|
43
|
+
metric_name = "CPUUtilization"
|
|
44
|
+
namespace = "AWS/EC2"
|
|
45
|
+
period = 300
|
|
46
|
+
statistic = "Average"
|
|
47
|
+
threshold = 80
|
|
48
|
+
alarm_description = "CPU utilization exceeds 80% for 10 minutes"
|
|
49
|
+
alarm_actions = [aws_sns_topic.alarms.arn]
|
|
50
|
+
ok_actions = [aws_sns_topic.alarms.arn]
|
|
51
|
+
|
|
52
|
+
dimensions = {
|
|
53
|
+
AutoScalingGroupName = var.asg_name
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
tags = var.tags
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
resource "aws_cloudwatch_metric_alarm" "low_cpu" {
|
|
60
|
+
alarm_name = "${local.name_prefix}-low-cpu"
|
|
61
|
+
comparison_operator = "LessThanThreshold"
|
|
62
|
+
evaluation_periods = 2
|
|
63
|
+
metric_name = "CPUUtilization"
|
|
64
|
+
namespace = "AWS/EC2"
|
|
65
|
+
period = 300
|
|
66
|
+
statistic = "Average"
|
|
67
|
+
threshold = 20
|
|
68
|
+
alarm_description = "CPU utilization below 20% for 10 minutes (scale-down candidate)"
|
|
69
|
+
alarm_actions = [aws_sns_topic.alarms.arn]
|
|
70
|
+
|
|
71
|
+
dimensions = {
|
|
72
|
+
AutoScalingGroupName = var.asg_name
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
tags = var.tags
|
|
76
|
+
}
|
|
77
|
+
{% endif %}
|
|
78
|
+
|
|
79
|
+
{% if "database" in services %}
|
|
80
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
81
|
+
# CLOUDWATCH ALARMS — DATABASE (RDS)
|
|
82
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
83
|
+
|
|
84
|
+
resource "aws_cloudwatch_metric_alarm" "db_cpu" {
|
|
85
|
+
alarm_name = "${local.name_prefix}-db-high-cpu"
|
|
86
|
+
comparison_operator = "GreaterThanThreshold"
|
|
87
|
+
evaluation_periods = 2
|
|
88
|
+
metric_name = "CPUUtilization"
|
|
89
|
+
namespace = "AWS/RDS"
|
|
90
|
+
period = 300
|
|
91
|
+
statistic = "Average"
|
|
92
|
+
threshold = 80
|
|
93
|
+
alarm_description = "RDS CPU utilization exceeds 80% for 10 minutes"
|
|
94
|
+
alarm_actions = [aws_sns_topic.alarms.arn]
|
|
95
|
+
ok_actions = [aws_sns_topic.alarms.arn]
|
|
96
|
+
|
|
97
|
+
dimensions = {
|
|
98
|
+
DBInstanceIdentifier = var.db_instance_id
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
tags = var.tags
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
resource "aws_cloudwatch_metric_alarm" "db_free_storage" {
|
|
105
|
+
alarm_name = "${local.name_prefix}-db-low-storage"
|
|
106
|
+
comparison_operator = "LessThanThreshold"
|
|
107
|
+
evaluation_periods = 1
|
|
108
|
+
metric_name = "FreeStorageSpace"
|
|
109
|
+
namespace = "AWS/RDS"
|
|
110
|
+
period = 300
|
|
111
|
+
statistic = "Average"
|
|
112
|
+
threshold = 5368709120 # 5 GB in bytes
|
|
113
|
+
alarm_description = "RDS free storage below 5 GB"
|
|
114
|
+
alarm_actions = [aws_sns_topic.alarms.arn]
|
|
115
|
+
ok_actions = [aws_sns_topic.alarms.arn]
|
|
116
|
+
|
|
117
|
+
dimensions = {
|
|
118
|
+
DBInstanceIdentifier = var.db_instance_id
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
tags = var.tags
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
resource "aws_cloudwatch_metric_alarm" "db_connections" {
|
|
125
|
+
alarm_name = "${local.name_prefix}-db-high-connections"
|
|
126
|
+
comparison_operator = "GreaterThanThreshold"
|
|
127
|
+
evaluation_periods = 2
|
|
128
|
+
metric_name = "DatabaseConnections"
|
|
129
|
+
namespace = "AWS/RDS"
|
|
130
|
+
period = 300
|
|
131
|
+
statistic = "Average"
|
|
132
|
+
threshold = 100
|
|
133
|
+
alarm_description = "RDS connections exceed 100"
|
|
134
|
+
alarm_actions = [aws_sns_topic.alarms.arn]
|
|
135
|
+
|
|
136
|
+
dimensions = {
|
|
137
|
+
DBInstanceIdentifier = var.db_instance_id
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
tags = var.tags
|
|
141
|
+
}
|
|
142
|
+
{% endif %}
|
|
143
|
+
|
|
144
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
145
|
+
# CLOUDWATCH LOG GROUP
|
|
146
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
147
|
+
|
|
148
|
+
resource "aws_cloudwatch_log_group" "main" {
|
|
149
|
+
name = "/${var.project_name}/${var.environment}"
|
|
150
|
+
retention_in_days = var.environment == "prod" ? 90 : 30
|
|
151
|
+
|
|
152
|
+
tags = merge(var.tags, {
|
|
153
|
+
Name = "${local.name_prefix}-logs"
|
|
154
|
+
})
|
|
155
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
# MONITORING MODULE — Outputs
|
|
3
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
output "sns_topic_arn" {
|
|
6
|
+
description = "ARN of the SNS alarm topic"
|
|
7
|
+
value = aws_sns_topic.alarms.arn
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
output "sns_topic_name" {
|
|
11
|
+
description = "Name of the SNS alarm topic"
|
|
12
|
+
value = aws_sns_topic.alarms.name
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
output "log_group_name" {
|
|
16
|
+
description = "Name of the CloudWatch log group"
|
|
17
|
+
value = aws_cloudwatch_log_group.main.name
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
output "log_group_arn" {
|
|
21
|
+
description = "ARN of the CloudWatch log group"
|
|
22
|
+
value = aws_cloudwatch_log_group.main.arn
|
|
23
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
# MONITORING MODULE — Variables
|
|
3
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
variable "project_name" {
|
|
6
|
+
description = "Name of the project"
|
|
7
|
+
type = string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
variable "environment" {
|
|
11
|
+
description = "Deployment environment"
|
|
12
|
+
type = string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
variable "alarm_email" {
|
|
16
|
+
description = "Email address for alarm notifications"
|
|
17
|
+
type = string
|
|
18
|
+
default = ""
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
{% if "compute" in services %}
|
|
22
|
+
variable "asg_name" {
|
|
23
|
+
description = "Name of the Auto Scaling Group to monitor"
|
|
24
|
+
type = string
|
|
25
|
+
}
|
|
26
|
+
{% endif %}
|
|
27
|
+
|
|
28
|
+
{% if "database" in services %}
|
|
29
|
+
variable "db_instance_id" {
|
|
30
|
+
description = "ID of the RDS instance to monitor"
|
|
31
|
+
type = string
|
|
32
|
+
}
|
|
33
|
+
{% endif %}
|
|
34
|
+
|
|
35
|
+
variable "tags" {
|
|
36
|
+
description = "Common resource tags"
|
|
37
|
+
type = map(string)
|
|
38
|
+
default = {}
|
|
39
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
# NETWORK MODULE — VPC, Subnets, Internet Gateway, NAT Gateway
|
|
3
|
+
# Project: {{ project_name }}
|
|
4
|
+
# Generated by tf-starter
|
|
5
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
6
|
+
|
|
7
|
+
locals {
|
|
8
|
+
name_prefix = "${var.project_name}-${var.environment}"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
12
|
+
# VPC
|
|
13
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
14
|
+
|
|
15
|
+
resource "aws_vpc" "main" {
|
|
16
|
+
cidr_block = var.vpc_cidr
|
|
17
|
+
enable_dns_support = true
|
|
18
|
+
enable_dns_hostnames = true
|
|
19
|
+
|
|
20
|
+
tags = merge(var.tags, {
|
|
21
|
+
Name = "${local.name_prefix}-vpc"
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
26
|
+
# INTERNET GATEWAY
|
|
27
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
28
|
+
|
|
29
|
+
resource "aws_internet_gateway" "main" {
|
|
30
|
+
vpc_id = aws_vpc.main.id
|
|
31
|
+
|
|
32
|
+
tags = merge(var.tags, {
|
|
33
|
+
Name = "${local.name_prefix}-igw"
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
38
|
+
# PUBLIC SUBNETS
|
|
39
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
resource "aws_subnet" "public" {
|
|
42
|
+
count = length(var.public_subnet_cidrs)
|
|
43
|
+
|
|
44
|
+
vpc_id = aws_vpc.main.id
|
|
45
|
+
cidr_block = var.public_subnet_cidrs[count.index]
|
|
46
|
+
availability_zone = var.availability_zones[count.index]
|
|
47
|
+
map_public_ip_on_launch = true
|
|
48
|
+
|
|
49
|
+
tags = merge(var.tags, {
|
|
50
|
+
Name = "${local.name_prefix}-public-${var.availability_zones[count.index]}"
|
|
51
|
+
Tier = "public"
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
56
|
+
# PRIVATE SUBNETS
|
|
57
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
58
|
+
|
|
59
|
+
resource "aws_subnet" "private" {
|
|
60
|
+
count = length(var.private_subnet_cidrs)
|
|
61
|
+
|
|
62
|
+
vpc_id = aws_vpc.main.id
|
|
63
|
+
cidr_block = var.private_subnet_cidrs[count.index]
|
|
64
|
+
availability_zone = var.availability_zones[count.index]
|
|
65
|
+
|
|
66
|
+
tags = merge(var.tags, {
|
|
67
|
+
Name = "${local.name_prefix}-private-${var.availability_zones[count.index]}"
|
|
68
|
+
Tier = "private"
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
73
|
+
# ELASTIC IP FOR NAT GATEWAY
|
|
74
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
75
|
+
|
|
76
|
+
resource "aws_eip" "nat" {
|
|
77
|
+
domain = "vpc"
|
|
78
|
+
|
|
79
|
+
tags = merge(var.tags, {
|
|
80
|
+
Name = "${local.name_prefix}-nat-eip"
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
depends_on = [aws_internet_gateway.main]
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
87
|
+
# NAT GATEWAY (single — for cost optimization; use one per AZ in production)
|
|
88
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
89
|
+
|
|
90
|
+
resource "aws_nat_gateway" "main" {
|
|
91
|
+
allocation_id = aws_eip.nat.id
|
|
92
|
+
subnet_id = aws_subnet.public[0].id
|
|
93
|
+
|
|
94
|
+
tags = merge(var.tags, {
|
|
95
|
+
Name = "${local.name_prefix}-nat"
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
depends_on = [aws_internet_gateway.main]
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
102
|
+
# ROUTE TABLES
|
|
103
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
104
|
+
|
|
105
|
+
resource "aws_route_table" "public" {
|
|
106
|
+
vpc_id = aws_vpc.main.id
|
|
107
|
+
|
|
108
|
+
route {
|
|
109
|
+
cidr_block = "0.0.0.0/0"
|
|
110
|
+
gateway_id = aws_internet_gateway.main.id
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
tags = merge(var.tags, {
|
|
114
|
+
Name = "${local.name_prefix}-public-rt"
|
|
115
|
+
})
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
resource "aws_route_table" "private" {
|
|
119
|
+
vpc_id = aws_vpc.main.id
|
|
120
|
+
|
|
121
|
+
route {
|
|
122
|
+
cidr_block = "0.0.0.0/0"
|
|
123
|
+
nat_gateway_id = aws_nat_gateway.main.id
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
tags = merge(var.tags, {
|
|
127
|
+
Name = "${local.name_prefix}-private-rt"
|
|
128
|
+
})
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
132
|
+
# ROUTE TABLE ASSOCIATIONS
|
|
133
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
134
|
+
|
|
135
|
+
resource "aws_route_table_association" "public" {
|
|
136
|
+
count = length(aws_subnet.public)
|
|
137
|
+
|
|
138
|
+
subnet_id = aws_subnet.public[count.index].id
|
|
139
|
+
route_table_id = aws_route_table.public.id
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
resource "aws_route_table_association" "private" {
|
|
143
|
+
count = length(aws_subnet.private)
|
|
144
|
+
|
|
145
|
+
subnet_id = aws_subnet.private[count.index].id
|
|
146
|
+
route_table_id = aws_route_table.private.id
|
|
147
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
# NETWORK MODULE — Outputs
|
|
3
|
+
# ---------------------------------------------------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
output "vpc_id" {
|
|
6
|
+
description = "ID of the VPC"
|
|
7
|
+
value = aws_vpc.main.id
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
output "vpc_cidr" {
|
|
11
|
+
description = "CIDR block of the VPC"
|
|
12
|
+
value = aws_vpc.main.cidr_block
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
output "public_subnet_ids" {
|
|
16
|
+
description = "IDs of the public subnets"
|
|
17
|
+
value = aws_subnet.public[*].id
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
output "private_subnet_ids" {
|
|
21
|
+
description = "IDs of the private subnets"
|
|
22
|
+
value = aws_subnet.private[*].id
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
output "internet_gateway_id" {
|
|
26
|
+
description = "ID of the Internet Gateway"
|
|
27
|
+
value = aws_internet_gateway.main.id
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
output "nat_gateway_id" {
|
|
31
|
+
description = "ID of the NAT Gateway"
|
|
32
|
+
value = aws_nat_gateway.main.id
|
|
33
|
+
}
|