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.
Files changed (137) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +421 -0
  3. package/bin/tf-starter.js +88 -0
  4. package/package.json +43 -0
  5. package/scripts/postinstall.js +105 -0
  6. package/setup.py +32 -0
  7. package/tf_starter/__init__.py +3 -0
  8. package/tf_starter/__main__.py +6 -0
  9. package/tf_starter/cli.py +379 -0
  10. package/tf_starter/generator.py +171 -0
  11. package/tf_starter/template_engine.py +80 -0
  12. package/tf_starter/templates/aws/environments/backend.tf.j2 +16 -0
  13. package/tf_starter/templates/aws/environments/main.tf.j2 +85 -0
  14. package/tf_starter/templates/aws/environments/terraform.tfvars.j2 +52 -0
  15. package/tf_starter/templates/aws/environments/variables.tf.j2 +127 -0
  16. package/tf_starter/templates/aws/github/terraform.yml.j2 +133 -0
  17. package/tf_starter/templates/aws/misc/Makefile.j2 +60 -0
  18. package/tf_starter/templates/aws/misc/README.md.j2 +445 -0
  19. package/tf_starter/templates/aws/misc/init.sh.j2 +110 -0
  20. package/tf_starter/templates/aws/misc/pre-commit-config.yaml.j2 +34 -0
  21. package/tf_starter/templates/aws/modules/apigateway/main.tf.j2 +224 -0
  22. package/tf_starter/templates/aws/modules/apigateway/outputs.tf.j2 +28 -0
  23. package/tf_starter/templates/aws/modules/apigateway/variables.tf.j2 +69 -0
  24. package/tf_starter/templates/aws/modules/compute/main.tf.j2 +245 -0
  25. package/tf_starter/templates/aws/modules/compute/outputs.tf.j2 +38 -0
  26. package/tf_starter/templates/aws/modules/compute/variables.tf.j2 +68 -0
  27. package/tf_starter/templates/aws/modules/database/main.tf.j2 +122 -0
  28. package/tf_starter/templates/aws/modules/database/outputs.tf.j2 +33 -0
  29. package/tf_starter/templates/aws/modules/database/variables.tf.j2 +63 -0
  30. package/tf_starter/templates/aws/modules/kubernetes/main.tf.j2 +167 -0
  31. package/tf_starter/templates/aws/modules/kubernetes/outputs.tf.j2 +33 -0
  32. package/tf_starter/templates/aws/modules/kubernetes/variables.tf.j2 +64 -0
  33. package/tf_starter/templates/aws/modules/lambda/main.tf.j2 +215 -0
  34. package/tf_starter/templates/aws/modules/lambda/outputs.tf.j2 +38 -0
  35. package/tf_starter/templates/aws/modules/lambda/variables.tf.j2 +88 -0
  36. package/tf_starter/templates/aws/modules/messaging/main.tf.j2 +85 -0
  37. package/tf_starter/templates/aws/modules/messaging/outputs.tf.j2 +28 -0
  38. package/tf_starter/templates/aws/modules/messaging/variables.tf.j2 +41 -0
  39. package/tf_starter/templates/aws/modules/monitoring/main.tf.j2 +155 -0
  40. package/tf_starter/templates/aws/modules/monitoring/outputs.tf.j2 +23 -0
  41. package/tf_starter/templates/aws/modules/monitoring/variables.tf.j2 +39 -0
  42. package/tf_starter/templates/aws/modules/network/main.tf.j2 +147 -0
  43. package/tf_starter/templates/aws/modules/network/outputs.tf.j2 +33 -0
  44. package/tf_starter/templates/aws/modules/network/variables.tf.j2 +52 -0
  45. package/tf_starter/templates/aws/modules/storage/main.tf.j2 +88 -0
  46. package/tf_starter/templates/aws/modules/storage/outputs.tf.j2 +23 -0
  47. package/tf_starter/templates/aws/modules/storage/variables.tf.j2 +25 -0
  48. package/tf_starter/templates/aws/root/backend.tf.j2 +19 -0
  49. package/tf_starter/templates/aws/root/main.tf.j2 +219 -0
  50. package/tf_starter/templates/aws/root/outputs.tf.j2 +134 -0
  51. package/tf_starter/templates/aws/root/providers.tf.j2 +24 -0
  52. package/tf_starter/templates/aws/root/variables.tf.j2 +300 -0
  53. package/tf_starter/templates/aws/root/versions.tf.j2 +26 -0
  54. package/tf_starter/templates/azure/environments/backend.tf.j2 +11 -0
  55. package/tf_starter/templates/azure/environments/main.tf.j2 +57 -0
  56. package/tf_starter/templates/azure/environments/terraform.tfvars.j2 +14 -0
  57. package/tf_starter/templates/azure/environments/variables.tf.j2 +30 -0
  58. package/tf_starter/templates/azure/github/terraform.yml.j2 +133 -0
  59. package/tf_starter/templates/azure/misc/Makefile.j2 +60 -0
  60. package/tf_starter/templates/azure/misc/README.md.j2 +426 -0
  61. package/tf_starter/templates/azure/misc/init.sh.j2 +110 -0
  62. package/tf_starter/templates/azure/misc/pre-commit-config.yaml.j2 +34 -0
  63. package/tf_starter/templates/azure/modules/apigateway/main.tf.j2 +125 -0
  64. package/tf_starter/templates/azure/modules/apigateway/outputs.tf.j2 +18 -0
  65. package/tf_starter/templates/azure/modules/apigateway/variables.tf.j2 +54 -0
  66. package/tf_starter/templates/azure/modules/compute/main.tf.j2 +114 -0
  67. package/tf_starter/templates/azure/modules/compute/outputs.tf.j2 +9 -0
  68. package/tf_starter/templates/azure/modules/compute/variables.tf.j2 +23 -0
  69. package/tf_starter/templates/azure/modules/database/main.tf.j2 +56 -0
  70. package/tf_starter/templates/azure/modules/database/outputs.tf.j2 +13 -0
  71. package/tf_starter/templates/azure/modules/database/variables.tf.j2 +38 -0
  72. package/tf_starter/templates/azure/modules/kubernetes/main.tf.j2 +50 -0
  73. package/tf_starter/templates/azure/modules/kubernetes/outputs.tf.j2 +19 -0
  74. package/tf_starter/templates/azure/modules/kubernetes/variables.tf.j2 +37 -0
  75. package/tf_starter/templates/azure/modules/lambda/main.tf.j2 +98 -0
  76. package/tf_starter/templates/azure/modules/lambda/outputs.tf.j2 +23 -0
  77. package/tf_starter/templates/azure/modules/lambda/variables.tf.j2 +53 -0
  78. package/tf_starter/templates/azure/modules/messaging/main.tf.j2 +29 -0
  79. package/tf_starter/templates/azure/modules/messaging/outputs.tf.j2 +14 -0
  80. package/tf_starter/templates/azure/modules/messaging/variables.tf.j2 +11 -0
  81. package/tf_starter/templates/azure/modules/monitoring/main.tf.j2 +31 -0
  82. package/tf_starter/templates/azure/modules/monitoring/outputs.tf.j2 +9 -0
  83. package/tf_starter/templates/azure/modules/monitoring/variables.tf.j2 +16 -0
  84. package/tf_starter/templates/azure/modules/network/main.tf.j2 +89 -0
  85. package/tf_starter/templates/azure/modules/network/outputs.tf.j2 +25 -0
  86. package/tf_starter/templates/azure/modules/network/variables.tf.j2 +25 -0
  87. package/tf_starter/templates/azure/modules/storage/main.tf.j2 +41 -0
  88. package/tf_starter/templates/azure/modules/storage/outputs.tf.j2 +17 -0
  89. package/tf_starter/templates/azure/modules/storage/variables.tf.j2 +16 -0
  90. package/tf_starter/templates/azure/root/backend.tf.j2 +11 -0
  91. package/tf_starter/templates/azure/root/main.tf.j2 +181 -0
  92. package/tf_starter/templates/azure/root/outputs.tf.j2 +45 -0
  93. package/tf_starter/templates/azure/root/providers.tf.j2 +18 -0
  94. package/tf_starter/templates/azure/root/variables.tf.j2 +114 -0
  95. package/tf_starter/templates/azure/root/versions.tf.j2 +16 -0
  96. package/tf_starter/templates/gcp/environments/backend.tf.j2 +9 -0
  97. package/tf_starter/templates/gcp/environments/main.tf.j2 +58 -0
  98. package/tf_starter/templates/gcp/environments/terraform.tfvars.j2 +12 -0
  99. package/tf_starter/templates/gcp/environments/variables.tf.j2 +21 -0
  100. package/tf_starter/templates/gcp/github/terraform.yml.j2 +133 -0
  101. package/tf_starter/templates/gcp/misc/Makefile.j2 +60 -0
  102. package/tf_starter/templates/gcp/misc/README.md.j2 +426 -0
  103. package/tf_starter/templates/gcp/misc/init.sh.j2 +110 -0
  104. package/tf_starter/templates/gcp/misc/pre-commit-config.yaml.j2 +34 -0
  105. package/tf_starter/templates/gcp/modules/apigateway/main.tf.j2 +67 -0
  106. package/tf_starter/templates/gcp/modules/apigateway/outputs.tf.j2 +18 -0
  107. package/tf_starter/templates/gcp/modules/apigateway/variables.tf.j2 +34 -0
  108. package/tf_starter/templates/gcp/modules/compute/main.tf.j2 +138 -0
  109. package/tf_starter/templates/gcp/modules/compute/outputs.tf.j2 +13 -0
  110. package/tf_starter/templates/gcp/modules/compute/variables.tf.j2 +33 -0
  111. package/tf_starter/templates/gcp/modules/database/main.tf.j2 +62 -0
  112. package/tf_starter/templates/gcp/modules/database/outputs.tf.j2 +13 -0
  113. package/tf_starter/templates/gcp/modules/database/variables.tf.j2 +29 -0
  114. package/tf_starter/templates/gcp/modules/kubernetes/main.tf.j2 +75 -0
  115. package/tf_starter/templates/gcp/modules/kubernetes/outputs.tf.j2 +14 -0
  116. package/tf_starter/templates/gcp/modules/kubernetes/variables.tf.j2 +38 -0
  117. package/tf_starter/templates/gcp/modules/lambda/main.tf.j2 +122 -0
  118. package/tf_starter/templates/gcp/modules/lambda/outputs.tf.j2 +18 -0
  119. package/tf_starter/templates/gcp/modules/lambda/variables.tf.j2 +77 -0
  120. package/tf_starter/templates/gcp/modules/messaging/main.tf.j2 +44 -0
  121. package/tf_starter/templates/gcp/modules/messaging/outputs.tf.j2 +13 -0
  122. package/tf_starter/templates/gcp/modules/messaging/variables.tf.j2 +20 -0
  123. package/tf_starter/templates/gcp/modules/monitoring/main.tf.j2 +44 -0
  124. package/tf_starter/templates/gcp/modules/monitoring/outputs.tf.j2 +9 -0
  125. package/tf_starter/templates/gcp/modules/monitoring/variables.tf.j2 +13 -0
  126. package/tf_starter/templates/gcp/modules/network/main.tf.j2 +103 -0
  127. package/tf_starter/templates/gcp/modules/network/outputs.tf.j2 +21 -0
  128. package/tf_starter/templates/gcp/modules/network/variables.tf.j2 +22 -0
  129. package/tf_starter/templates/gcp/modules/storage/main.tf.j2 +47 -0
  130. package/tf_starter/templates/gcp/modules/storage/outputs.tf.j2 +13 -0
  131. package/tf_starter/templates/gcp/modules/storage/variables.tf.j2 +16 -0
  132. package/tf_starter/templates/gcp/root/backend.tf.j2 +12 -0
  133. package/tf_starter/templates/gcp/root/main.tf.j2 +210 -0
  134. package/tf_starter/templates/gcp/root/outputs.tf.j2 +61 -0
  135. package/tf_starter/templates/gcp/root/providers.tf.j2 +18 -0
  136. package/tf_starter/templates/gcp/root/variables.tf.j2 +140 -0
  137. package/tf_starter/templates/gcp/root/versions.tf.j2 +23 -0
@@ -0,0 +1,122 @@
1
+ # ---------------------------------------------------------------------------------------------------------------------
2
+ # DATABASE MODULE — RDS PostgreSQL (Multi-AZ in production)
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
+ # SECURITY GROUP
13
+ # ---------------------------------------------------------------------------------------------------------------------
14
+
15
+ resource "aws_security_group" "database" {
16
+ name_prefix = "${local.name_prefix}-db-"
17
+ description = "Security group for RDS PostgreSQL"
18
+ vpc_id = var.vpc_id
19
+
20
+ ingress {
21
+ description = "PostgreSQL from private subnets"
22
+ from_port = 5432
23
+ to_port = 5432
24
+ protocol = "tcp"
25
+ cidr_blocks = [data.aws_vpc.selected.cidr_block]
26
+ }
27
+
28
+ egress {
29
+ from_port = 0
30
+ to_port = 0
31
+ protocol = "-1"
32
+ cidr_blocks = ["0.0.0.0/0"]
33
+ }
34
+
35
+ tags = merge(var.tags, {
36
+ Name = "${local.name_prefix}-db-sg"
37
+ })
38
+
39
+ lifecycle {
40
+ create_before_destroy = true
41
+ }
42
+ }
43
+
44
+ data "aws_vpc" "selected" {
45
+ id = var.vpc_id
46
+ }
47
+
48
+ # ---------------------------------------------------------------------------------------------------------------------
49
+ # DB SUBNET GROUP
50
+ # ---------------------------------------------------------------------------------------------------------------------
51
+
52
+ resource "aws_db_subnet_group" "main" {
53
+ name = "${local.name_prefix}-db-subnet"
54
+ subnet_ids = var.private_subnet_ids
55
+
56
+ tags = merge(var.tags, {
57
+ Name = "${local.name_prefix}-db-subnet-group"
58
+ })
59
+ }
60
+
61
+ # ---------------------------------------------------------------------------------------------------------------------
62
+ # RANDOM PASSWORD
63
+ # ---------------------------------------------------------------------------------------------------------------------
64
+
65
+ resource "random_password" "db_password" {
66
+ length = 24
67
+ special = true
68
+ override_special = "!#$%^&*()-_=+"
69
+ }
70
+
71
+ # ---------------------------------------------------------------------------------------------------------------------
72
+ # RDS POSTGRESQL INSTANCE
73
+ # ---------------------------------------------------------------------------------------------------------------------
74
+
75
+ resource "aws_db_instance" "main" {
76
+ identifier = "${local.name_prefix}-postgres"
77
+
78
+ engine = "postgres"
79
+ engine_version = "16.2"
80
+ instance_class = var.db_instance_class
81
+ allocated_storage = var.db_allocated_storage
82
+ max_allocated_storage = var.db_allocated_storage * 2
83
+
84
+ db_name = var.db_name
85
+ username = var.db_username
86
+ password = random_password.db_password.result
87
+
88
+ db_subnet_group_name = aws_db_subnet_group.main.name
89
+ vpc_security_group_ids = [aws_security_group.database.id]
90
+
91
+ multi_az = var.db_multi_az
92
+ publicly_accessible = false
93
+ storage_encrypted = true
94
+ storage_type = "gp3"
95
+
96
+ backup_retention_period = var.environment == "prod" ? 30 : 7
97
+ backup_window = "03:00-04:00"
98
+ maintenance_window = "Mon:04:00-Mon:05:00"
99
+
100
+ deletion_protection = var.environment == "prod" ? true : false
101
+ skip_final_snapshot = var.environment == "prod" ? false : true
102
+ final_snapshot_identifier = var.environment == "prod" ? "${local.name_prefix}-final-snapshot" : null
103
+
104
+ performance_insights_enabled = true
105
+
106
+ tags = merge(var.tags, {
107
+ Name = "${local.name_prefix}-postgres"
108
+ })
109
+ }
110
+
111
+ # ---------------------------------------------------------------------------------------------------------------------
112
+ # STORE PASSWORD IN SSM PARAMETER STORE
113
+ # ---------------------------------------------------------------------------------------------------------------------
114
+
115
+ resource "aws_ssm_parameter" "db_password" {
116
+ name = "/${var.project_name}/${var.environment}/database/password"
117
+ description = "RDS master password for ${local.name_prefix}"
118
+ type = "SecureString"
119
+ value = random_password.db_password.result
120
+
121
+ tags = var.tags
122
+ }
@@ -0,0 +1,33 @@
1
+ # ---------------------------------------------------------------------------------------------------------------------
2
+ # DATABASE MODULE — Outputs
3
+ # ---------------------------------------------------------------------------------------------------------------------
4
+
5
+ output "db_instance_id" {
6
+ description = "ID of the RDS instance"
7
+ value = aws_db_instance.main.id
8
+ }
9
+
10
+ output "db_endpoint" {
11
+ description = "Connection endpoint of the RDS instance"
12
+ value = aws_db_instance.main.endpoint
13
+ }
14
+
15
+ output "db_port" {
16
+ description = "Port of the RDS instance"
17
+ value = aws_db_instance.main.port
18
+ }
19
+
20
+ output "db_name" {
21
+ description = "Name of the database"
22
+ value = aws_db_instance.main.db_name
23
+ }
24
+
25
+ output "db_arn" {
26
+ description = "ARN of the RDS instance"
27
+ value = aws_db_instance.main.arn
28
+ }
29
+
30
+ output "db_security_group_id" {
31
+ description = "ID of the database security group"
32
+ value = aws_security_group.database.id
33
+ }
@@ -0,0 +1,63 @@
1
+ # ---------------------------------------------------------------------------------------------------------------------
2
+ # DATABASE 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 "vpc_id" {
16
+ description = "ID of the VPC"
17
+ type = string
18
+ }
19
+
20
+ variable "private_subnet_ids" {
21
+ description = "IDs of the private subnets"
22
+ type = list(string)
23
+ }
24
+
25
+ variable "db_instance_class" {
26
+ description = "RDS instance class"
27
+ type = string
28
+ default = "db.t3.medium"
29
+ }
30
+
31
+ variable "db_allocated_storage" {
32
+ description = "Allocated storage in GB"
33
+ type = number
34
+ default = 20
35
+
36
+ validation {
37
+ condition = var.db_allocated_storage >= 20 && var.db_allocated_storage <= 65536
38
+ error_message = "Allocated storage must be between 20 and 65536 GB."
39
+ }
40
+ }
41
+
42
+ variable "db_name" {
43
+ description = "Name of the database"
44
+ type = string
45
+ }
46
+
47
+ variable "db_username" {
48
+ description = "Master username for the database"
49
+ type = string
50
+ sensitive = true
51
+ }
52
+
53
+ variable "db_multi_az" {
54
+ description = "Enable Multi-AZ deployment"
55
+ type = bool
56
+ default = false
57
+ }
58
+
59
+ variable "tags" {
60
+ description = "Common resource tags"
61
+ type = map(string)
62
+ default = {}
63
+ }
@@ -0,0 +1,167 @@
1
+ # ---------------------------------------------------------------------------------------------------------------------
2
+ # KUBERNETES MODULE — Amazon EKS
3
+ # Project: {{ project_name }}
4
+ # Generated by tf-starter
5
+ # ---------------------------------------------------------------------------------------------------------------------
6
+
7
+ locals {
8
+ name_prefix = "${var.project_name}-${var.environment}"
9
+ cluster_name = "${local.name_prefix}-eks"
10
+ }
11
+
12
+ # ---------------------------------------------------------------------------------------------------------------------
13
+ # EKS CLUSTER IAM ROLE
14
+ # ---------------------------------------------------------------------------------------------------------------------
15
+
16
+ resource "aws_iam_role" "cluster" {
17
+ name = "${local.name_prefix}-eks-cluster-role"
18
+
19
+ assume_role_policy = jsonencode({
20
+ Version = "2012-10-17"
21
+ Statement = [
22
+ {
23
+ Action = "sts:AssumeRole"
24
+ Effect = "Allow"
25
+ Principal = {
26
+ Service = "eks.amazonaws.com"
27
+ }
28
+ }
29
+ ]
30
+ })
31
+
32
+ tags = var.tags
33
+ }
34
+
35
+ resource "aws_iam_role_policy_attachment" "cluster_policy" {
36
+ policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
37
+ role = aws_iam_role.cluster.name
38
+ }
39
+
40
+ resource "aws_iam_role_policy_attachment" "cluster_vpc_controller" {
41
+ policy_arn = "arn:aws:iam::aws:policy/AmazonEKSVPCResourceController"
42
+ role = aws_iam_role.cluster.name
43
+ }
44
+
45
+ # ---------------------------------------------------------------------------------------------------------------------
46
+ # EKS CLUSTER SECURITY GROUP
47
+ # ---------------------------------------------------------------------------------------------------------------------
48
+
49
+ resource "aws_security_group" "cluster" {
50
+ name_prefix = "${local.name_prefix}-eks-cluster-"
51
+ description = "Security group for the EKS cluster control plane"
52
+ vpc_id = var.vpc_id
53
+
54
+ egress {
55
+ from_port = 0
56
+ to_port = 0
57
+ protocol = "-1"
58
+ cidr_blocks = ["0.0.0.0/0"]
59
+ }
60
+
61
+ tags = merge(var.tags, {
62
+ Name = "${local.name_prefix}-eks-cluster-sg"
63
+ })
64
+
65
+ lifecycle {
66
+ create_before_destroy = true
67
+ }
68
+ }
69
+
70
+ # ---------------------------------------------------------------------------------------------------------------------
71
+ # EKS CLUSTER
72
+ # ---------------------------------------------------------------------------------------------------------------------
73
+
74
+ resource "aws_eks_cluster" "main" {
75
+ name = local.cluster_name
76
+ version = var.cluster_version
77
+ role_arn = aws_iam_role.cluster.arn
78
+
79
+ vpc_config {
80
+ subnet_ids = var.private_subnet_ids
81
+ endpoint_private_access = true
82
+ endpoint_public_access = true
83
+ security_group_ids = [aws_security_group.cluster.id]
84
+ }
85
+
86
+ enabled_cluster_log_types = ["api", "audit", "authenticator", "controllerManager", "scheduler"]
87
+
88
+ tags = merge(var.tags, {
89
+ Name = local.cluster_name
90
+ })
91
+
92
+ depends_on = [
93
+ aws_iam_role_policy_attachment.cluster_policy,
94
+ aws_iam_role_policy_attachment.cluster_vpc_controller,
95
+ ]
96
+ }
97
+
98
+ # ---------------------------------------------------------------------------------------------------------------------
99
+ # EKS NODE GROUP IAM ROLE
100
+ # ---------------------------------------------------------------------------------------------------------------------
101
+
102
+ resource "aws_iam_role" "node_group" {
103
+ name = "${local.name_prefix}-eks-node-role"
104
+
105
+ assume_role_policy = jsonencode({
106
+ Version = "2012-10-17"
107
+ Statement = [
108
+ {
109
+ Action = "sts:AssumeRole"
110
+ Effect = "Allow"
111
+ Principal = {
112
+ Service = "ec2.amazonaws.com"
113
+ }
114
+ }
115
+ ]
116
+ })
117
+
118
+ tags = var.tags
119
+ }
120
+
121
+ resource "aws_iam_role_policy_attachment" "node_worker" {
122
+ policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
123
+ role = aws_iam_role.node_group.name
124
+ }
125
+
126
+ resource "aws_iam_role_policy_attachment" "node_cni" {
127
+ policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
128
+ role = aws_iam_role.node_group.name
129
+ }
130
+
131
+ resource "aws_iam_role_policy_attachment" "node_ecr" {
132
+ policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
133
+ role = aws_iam_role.node_group.name
134
+ }
135
+
136
+ # ---------------------------------------------------------------------------------------------------------------------
137
+ # EKS MANAGED NODE GROUP
138
+ # ---------------------------------------------------------------------------------------------------------------------
139
+
140
+ resource "aws_eks_node_group" "main" {
141
+ cluster_name = aws_eks_cluster.main.name
142
+ node_group_name = "${local.name_prefix}-node-group"
143
+ node_role_arn = aws_iam_role.node_group.arn
144
+ subnet_ids = var.private_subnet_ids
145
+
146
+ instance_types = [var.node_instance_type]
147
+
148
+ scaling_config {
149
+ desired_size = var.node_desired_size
150
+ min_size = var.node_min_size
151
+ max_size = var.node_max_size
152
+ }
153
+
154
+ update_config {
155
+ max_unavailable = 1
156
+ }
157
+
158
+ tags = merge(var.tags, {
159
+ Name = "${local.name_prefix}-node-group"
160
+ })
161
+
162
+ depends_on = [
163
+ aws_iam_role_policy_attachment.node_worker,
164
+ aws_iam_role_policy_attachment.node_cni,
165
+ aws_iam_role_policy_attachment.node_ecr,
166
+ ]
167
+ }
@@ -0,0 +1,33 @@
1
+ # ---------------------------------------------------------------------------------------------------------------------
2
+ # KUBERNETES MODULE — Outputs
3
+ # ---------------------------------------------------------------------------------------------------------------------
4
+
5
+ output "cluster_endpoint" {
6
+ description = "EKS cluster API endpoint"
7
+ value = aws_eks_cluster.main.endpoint
8
+ }
9
+
10
+ output "cluster_name" {
11
+ description = "Name of the EKS cluster"
12
+ value = aws_eks_cluster.main.name
13
+ }
14
+
15
+ output "cluster_arn" {
16
+ description = "ARN of the EKS cluster"
17
+ value = aws_eks_cluster.main.arn
18
+ }
19
+
20
+ output "cluster_certificate_authority" {
21
+ description = "Base64 encoded CA certificate for the cluster"
22
+ value = aws_eks_cluster.main.certificate_authority[0].data
23
+ }
24
+
25
+ output "cluster_security_group_id" {
26
+ description = "Security group ID of the EKS cluster"
27
+ value = aws_security_group.cluster.id
28
+ }
29
+
30
+ output "node_group_arn" {
31
+ description = "ARN of the EKS node group"
32
+ value = aws_eks_node_group.main.arn
33
+ }
@@ -0,0 +1,64 @@
1
+ # ---------------------------------------------------------------------------------------------------------------------
2
+ # KUBERNETES 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 "vpc_id" {
16
+ description = "ID of the VPC"
17
+ type = string
18
+ }
19
+
20
+ variable "private_subnet_ids" {
21
+ description = "IDs of the private subnets for EKS"
22
+ type = list(string)
23
+ }
24
+
25
+ variable "cluster_version" {
26
+ description = "Kubernetes version for the EKS cluster"
27
+ type = string
28
+ default = "1.29"
29
+ }
30
+
31
+ variable "node_instance_type" {
32
+ description = "Instance type for EKS worker nodes"
33
+ type = string
34
+ default = "t3.large"
35
+ }
36
+
37
+ variable "node_desired_size" {
38
+ description = "Desired number of worker nodes"
39
+ type = number
40
+ default = 2
41
+ }
42
+
43
+ variable "node_min_size" {
44
+ description = "Minimum number of worker nodes"
45
+ type = number
46
+ default = 1
47
+
48
+ validation {
49
+ condition = var.node_min_size >= 1
50
+ error_message = "Minimum node count must be at least 1."
51
+ }
52
+ }
53
+
54
+ variable "node_max_size" {
55
+ description = "Maximum number of worker nodes"
56
+ type = number
57
+ default = 5
58
+ }
59
+
60
+ variable "tags" {
61
+ description = "Common resource tags"
62
+ type = map(string)
63
+ default = {}
64
+ }
@@ -0,0 +1,215 @@
1
+ # ---------------------------------------------------------------------------------------------------------------------
2
+ # LAMBDA MODULE — AWS Lambda Functions
3
+ # Project: {{ project_name }}
4
+ # Generated by tf-starter
5
+ # ---------------------------------------------------------------------------------------------------------------------
6
+
7
+ locals {
8
+ name_prefix = "${var.project_name}-${var.environment}"
9
+ function_name = "${local.name_prefix}-${var.function_name}"
10
+ }
11
+
12
+ # ---------------------------------------------------------------------------------------------------------------------
13
+ # IAM ROLE FOR LAMBDA EXECUTION
14
+ # ---------------------------------------------------------------------------------------------------------------------
15
+
16
+ resource "aws_iam_role" "lambda" {
17
+ name = "${local.function_name}-role"
18
+
19
+ assume_role_policy = jsonencode({
20
+ Version = "2012-10-17"
21
+ Statement = [
22
+ {
23
+ Action = "sts:AssumeRole"
24
+ Effect = "Allow"
25
+ Principal = {
26
+ Service = "lambda.amazonaws.com"
27
+ }
28
+ }
29
+ ]
30
+ })
31
+
32
+ tags = var.tags
33
+ }
34
+
35
+ resource "aws_iam_role_policy_attachment" "lambda_basic" {
36
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
37
+ role = aws_iam_role.lambda.name
38
+ }
39
+
40
+ resource "aws_iam_role_policy_attachment" "lambda_vpc" {
41
+ count = var.deploy_in_vpc ? 1 : 0
42
+
43
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
44
+ role = aws_iam_role.lambda.name
45
+ }
46
+
47
+ {% if "messaging" in services %}
48
+ # Allow Lambda to read from SQS (if messaging is enabled)
49
+ resource "aws_iam_role_policy" "lambda_sqs" {
50
+ name = "${local.function_name}-sqs-policy"
51
+ role = aws_iam_role.lambda.id
52
+
53
+ policy = jsonencode({
54
+ Version = "2012-10-17"
55
+ Statement = [
56
+ {
57
+ Effect = "Allow"
58
+ Action = [
59
+ "sqs:ReceiveMessage",
60
+ "sqs:DeleteMessage",
61
+ "sqs:GetQueueAttributes",
62
+ ]
63
+ Resource = "*"
64
+ }
65
+ ]
66
+ })
67
+ }
68
+ {% endif %}
69
+
70
+ {% if "database" in services %}
71
+ # Allow Lambda to access RDS via IAM auth (if database is enabled)
72
+ resource "aws_iam_role_policy" "lambda_rds" {
73
+ name = "${local.function_name}-rds-policy"
74
+ role = aws_iam_role.lambda.id
75
+
76
+ policy = jsonencode({
77
+ Version = "2012-10-17"
78
+ Statement = [
79
+ {
80
+ Effect = "Allow"
81
+ Action = [
82
+ "rds-db:connect",
83
+ ]
84
+ Resource = "*"
85
+ }
86
+ ]
87
+ })
88
+ }
89
+ {% endif %}
90
+
91
+ # ---------------------------------------------------------------------------------------------------------------------
92
+ # CLOUDWATCH LOG GROUP
93
+ # ---------------------------------------------------------------------------------------------------------------------
94
+
95
+ resource "aws_cloudwatch_log_group" "lambda" {
96
+ name = "/aws/lambda/${local.function_name}"
97
+ retention_in_days = var.environment == "prod" ? 90 : 14
98
+
99
+ tags = var.tags
100
+ }
101
+
102
+ # ---------------------------------------------------------------------------------------------------------------------
103
+ # LAMBDA FUNCTION
104
+ # ---------------------------------------------------------------------------------------------------------------------
105
+
106
+ data "archive_file" "lambda_placeholder" {
107
+ type = "zip"
108
+ output_path = "${path.module}/placeholder.zip"
109
+
110
+ source {
111
+ content = <<-EOF
112
+ def handler(event, context):
113
+ """Placeholder Lambda handler — replace with your application code."""
114
+ return {
115
+ "statusCode": 200,
116
+ "body": "Hello from ${local.function_name}"
117
+ }
118
+ EOF
119
+ filename = "index.py"
120
+ }
121
+ }
122
+
123
+ resource "aws_lambda_function" "main" {
124
+ function_name = local.function_name
125
+ description = "${var.project_name} Lambda function (${var.environment})"
126
+
127
+ role = aws_iam_role.lambda.arn
128
+ handler = var.handler
129
+ runtime = var.runtime
130
+ timeout = var.timeout
131
+ memory_size = var.memory_size
132
+
133
+ filename = data.archive_file.lambda_placeholder.output_path
134
+ source_code_hash = data.archive_file.lambda_placeholder.output_base64sha256
135
+
136
+ environment {
137
+ variables = merge(
138
+ {
139
+ ENVIRONMENT = var.environment
140
+ PROJECT_NAME = var.project_name
141
+ },
142
+ var.environment_variables,
143
+ )
144
+ }
145
+
146
+ dynamic "vpc_config" {
147
+ for_each = var.deploy_in_vpc ? [1] : []
148
+ content {
149
+ subnet_ids = var.private_subnet_ids
150
+ security_group_ids = [aws_security_group.lambda[0].id]
151
+ }
152
+ }
153
+
154
+ tracing_config {
155
+ mode = "Active"
156
+ }
157
+
158
+ tags = merge(var.tags, {
159
+ Name = local.function_name
160
+ })
161
+
162
+ depends_on = [
163
+ aws_iam_role_policy_attachment.lambda_basic,
164
+ aws_cloudwatch_log_group.lambda,
165
+ ]
166
+
167
+ ### MUST EDIT THIS ###
168
+ # Replace the placeholder code above with your actual deployment package:
169
+ # filename = "path/to/your/deployment.zip"
170
+ # Or use S3:
171
+ # s3_bucket = "your-deployment-bucket"
172
+ # s3_key = "lambdas/${local.function_name}.zip"
173
+ }
174
+
175
+ # ---------------------------------------------------------------------------------------------------------------------
176
+ # SECURITY GROUP (when deployed in VPC)
177
+ # ---------------------------------------------------------------------------------------------------------------------
178
+
179
+ resource "aws_security_group" "lambda" {
180
+ count = var.deploy_in_vpc ? 1 : 0
181
+
182
+ name_prefix = "${local.function_name}-sg-"
183
+ description = "Security group for Lambda function ${local.function_name}"
184
+ vpc_id = var.vpc_id
185
+
186
+ egress {
187
+ from_port = 0
188
+ to_port = 0
189
+ protocol = "-1"
190
+ cidr_blocks = ["0.0.0.0/0"]
191
+ }
192
+
193
+ tags = merge(var.tags, {
194
+ Name = "${local.function_name}-sg"
195
+ })
196
+
197
+ lifecycle {
198
+ create_before_destroy = true
199
+ }
200
+ }
201
+
202
+ # ---------------------------------------------------------------------------------------------------------------------
203
+ # LAMBDA ALIAS (for stable invocations & traffic shifting)
204
+ # ---------------------------------------------------------------------------------------------------------------------
205
+
206
+ resource "aws_lambda_alias" "live" {
207
+ name = "live"
208
+ description = "Alias pointing to the current live version"
209
+ function_name = aws_lambda_function.main.function_name
210
+ function_version = "$LATEST"
211
+
212
+ ### MUST EDIT THIS ###
213
+ # For production, pin to a specific version instead of $LATEST:
214
+ # function_version = aws_lambda_function.main.version
215
+ }