kybernus 2.2.0 → 2.3.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 (101) hide show
  1. package/package.json +1 -1
  2. package/templates/java-spring/clean/infra/main.tf.hbs +42 -18
  3. package/templates/java-spring/clean/infra/modules/ecs/main.tf.hbs +217 -6
  4. package/templates/java-spring/clean/infra/modules/rds/main.tf.hbs +15 -15
  5. package/templates/java-spring/clean/infra/modules/vpc/main.tf.hbs +170 -30
  6. package/templates/java-spring/clean/src/main/java/{{packagePath}}/application/usecase/PaymentUseCase.java.hbs +89 -0
  7. package/templates/java-spring/clean/src/main/java/{{packagePath}}/infrastructure/web/payment/PaymentController.java.hbs +78 -0
  8. package/templates/java-spring/clean/src/main/resources/application.properties.hbs +7 -0
  9. package/templates/java-spring/hexagonal/infra/main.tf.hbs +42 -18
  10. package/templates/java-spring/hexagonal/infra/modules/ecs/main.tf.hbs +217 -6
  11. package/templates/java-spring/hexagonal/infra/modules/rds/main.tf.hbs +15 -15
  12. package/templates/java-spring/hexagonal/infra/modules/vpc/main.tf.hbs +170 -30
  13. package/templates/java-spring/hexagonal/src/main/java/{{packagePath}}/adapters/inbound/web/PaymentController.java.hbs +78 -0
  14. package/templates/java-spring/hexagonal/src/main/java/{{packagePath}}/adapters/outbound/stripe/StripeAdapter.java.hbs +76 -0
  15. package/templates/java-spring/hexagonal/src/main/java/{{packagePath}}/core/service/PaymentService.java.hbs +90 -0
  16. package/templates/java-spring/hexagonal/src/main/resources/application.properties.hbs +7 -0
  17. package/templates/java-spring/mvc/infra/main.tf.hbs +42 -18
  18. package/templates/java-spring/mvc/infra/modules/ecs/main.tf.hbs +217 -6
  19. package/templates/java-spring/mvc/infra/modules/rds/main.tf.hbs +15 -15
  20. package/templates/java-spring/mvc/infra/modules/vpc/main.tf.hbs +170 -30
  21. package/templates/java-spring/mvc/src/main/java/{{packagePath}}/controller/PaymentsController.java.hbs +42 -53
  22. package/templates/java-spring/mvc/src/main/java/{{packagePath}}/service/StripeService.java.hbs +105 -23
  23. package/templates/nestjs/clean/infra/main.tf.hbs +42 -18
  24. package/templates/nestjs/clean/infra/modules/ecs/main.tf.hbs +217 -6
  25. package/templates/nestjs/clean/infra/modules/rds/main.tf.hbs +15 -15
  26. package/templates/nestjs/clean/infra/modules/vpc/main.tf.hbs +170 -30
  27. package/templates/nestjs/clean/src/app.module.ts.hbs +3 -1
  28. package/templates/nestjs/clean/src/application/payment.service.ts.hbs +90 -0
  29. package/templates/nestjs/clean/src/infrastructure/http/payment.controller.ts.hbs +46 -0
  30. package/templates/nestjs/clean/src/infrastructure/stripe.provider.ts.hbs +51 -0
  31. package/templates/nestjs/clean/src/main.ts.hbs +13 -4
  32. package/templates/nestjs/clean/src/payment.module.ts.hbs +23 -0
  33. package/templates/nestjs/hexagonal/infra/main.tf.hbs +42 -18
  34. package/templates/nestjs/hexagonal/infra/modules/ecs/main.tf.hbs +217 -6
  35. package/templates/nestjs/hexagonal/infra/modules/rds/main.tf.hbs +15 -15
  36. package/templates/nestjs/hexagonal/infra/modules/vpc/main.tf.hbs +170 -30
  37. package/templates/nestjs/hexagonal/src/adapters/inbound/payment.controller.ts.hbs +46 -0
  38. package/templates/nestjs/hexagonal/src/adapters/outbound/stripe.adapter.ts.hbs +54 -0
  39. package/templates/nestjs/hexagonal/src/app.module.ts.hbs +2 -0
  40. package/templates/nestjs/hexagonal/src/core/payment.service.ts.hbs +90 -0
  41. package/templates/nestjs/hexagonal/src/main.ts.hbs +13 -4
  42. package/templates/nestjs/hexagonal/src/payment.module.ts.hbs +23 -0
  43. package/templates/nestjs/mvc/infra/main.tf.hbs +42 -18
  44. package/templates/nestjs/mvc/infra/modules/ecs/main.tf.hbs +217 -6
  45. package/templates/nestjs/mvc/infra/modules/rds/main.tf.hbs +15 -15
  46. package/templates/nestjs/mvc/infra/modules/vpc/main.tf.hbs +170 -30
  47. package/templates/nestjs/mvc/src/main.ts.hbs +6 -3
  48. package/templates/nestjs/mvc/src/payments/payments.controller.ts.hbs +33 -8
  49. package/templates/nestjs/mvc/src/payments/payments.service.ts.hbs +66 -22
  50. package/templates/nextjs/mvc/infra/main.tf.hbs +42 -18
  51. package/templates/nextjs/mvc/infra/modules/ecs/main.tf.hbs +217 -6
  52. package/templates/nextjs/mvc/infra/modules/rds/main.tf.hbs +15 -15
  53. package/templates/nextjs/mvc/infra/modules/vpc/main.tf.hbs +170 -30
  54. package/templates/nextjs/mvc/src/app/api/checkout/route.ts.hbs +42 -13
  55. package/templates/nextjs/mvc/src/app/api/portal/route.ts.hbs +36 -0
  56. package/templates/nextjs/mvc/src/app/api/webhook/route.ts.hbs +32 -20
  57. package/templates/nodejs-express/clean/infra/main.tf.hbs +42 -18
  58. package/templates/nodejs-express/clean/infra/modules/ecs/main.tf.hbs +217 -6
  59. package/templates/nodejs-express/clean/infra/modules/rds/main.tf.hbs +15 -15
  60. package/templates/nodejs-express/clean/infra/modules/vpc/main.tf.hbs +170 -30
  61. package/templates/nodejs-express/clean/src/application/services/PaymentService.ts.hbs +98 -0
  62. package/templates/nodejs-express/clean/src/index.ts.hbs +29 -8
  63. package/templates/nodejs-express/clean/src/infrastructure/http/controllers/PaymentController.ts.hbs +57 -0
  64. package/templates/nodejs-express/clean/src/infrastructure/providers/StripeProvider.ts.hbs +45 -0
  65. package/templates/nodejs-express/hexagonal/infra/main.tf.hbs +42 -18
  66. package/templates/nodejs-express/hexagonal/infra/modules/ecs/main.tf.hbs +217 -6
  67. package/templates/nodejs-express/hexagonal/infra/modules/rds/main.tf.hbs +15 -15
  68. package/templates/nodejs-express/hexagonal/infra/modules/vpc/main.tf.hbs +170 -30
  69. package/templates/nodejs-express/hexagonal/src/adapters/inbound/http/PaymentController.ts.hbs +57 -0
  70. package/templates/nodejs-express/hexagonal/src/adapters/outbound/StripeAdapter.ts.hbs +48 -0
  71. package/templates/nodejs-express/hexagonal/src/core/PaymentService.ts.hbs +89 -0
  72. package/templates/nodejs-express/hexagonal/src/index.ts.hbs +28 -8
  73. package/templates/nodejs-express/mvc/infra/main.tf.hbs +42 -18
  74. package/templates/nodejs-express/mvc/infra/modules/ecs/main.tf.hbs +217 -6
  75. package/templates/nodejs-express/mvc/infra/modules/rds/main.tf.hbs +15 -15
  76. package/templates/nodejs-express/mvc/infra/modules/vpc/main.tf.hbs +170 -30
  77. package/templates/nodejs-express/mvc/src/app.ts.hbs +11 -2
  78. package/templates/nodejs-express/mvc/src/controllers/payments.controller.ts.hbs +31 -47
  79. package/templates/nodejs-express/mvc/src/services/stripe.service.ts.hbs +66 -49
  80. package/templates/python-fastapi/clean/app/application/services/payment_service.py.hbs +85 -0
  81. package/templates/python-fastapi/clean/app/infrastructure/http/payment_controller.py.hbs +64 -0
  82. package/templates/python-fastapi/clean/app/infrastructure/stripe_provider.py.hbs +44 -0
  83. package/templates/python-fastapi/clean/app/main.py.hbs +8 -5
  84. package/templates/python-fastapi/clean/infra/main.tf.hbs +42 -18
  85. package/templates/python-fastapi/clean/infra/modules/ecs/main.tf.hbs +217 -6
  86. package/templates/python-fastapi/clean/infra/modules/rds/main.tf.hbs +15 -15
  87. package/templates/python-fastapi/clean/infra/modules/vpc/main.tf.hbs +170 -30
  88. package/templates/python-fastapi/hexagonal/app/adapters/inbound/payment_http_adapter.py.hbs +64 -0
  89. package/templates/python-fastapi/hexagonal/app/adapters/outbound/stripe_adapter.py.hbs +44 -0
  90. package/templates/python-fastapi/hexagonal/app/core/payment_service.py.hbs +81 -0
  91. package/templates/python-fastapi/hexagonal/app/main.py.hbs +9 -3
  92. package/templates/python-fastapi/hexagonal/infra/main.tf.hbs +42 -18
  93. package/templates/python-fastapi/hexagonal/infra/modules/ecs/main.tf.hbs +217 -6
  94. package/templates/python-fastapi/hexagonal/infra/modules/rds/main.tf.hbs +15 -15
  95. package/templates/python-fastapi/hexagonal/infra/modules/vpc/main.tf.hbs +170 -30
  96. package/templates/python-fastapi/mvc/app/controllers/payments.py.hbs +70 -35
  97. package/templates/python-fastapi/mvc/app/services/stripe_service.py.hbs +58 -0
  98. package/templates/python-fastapi/mvc/infra/main.tf.hbs +42 -18
  99. package/templates/python-fastapi/mvc/infra/modules/ecs/main.tf.hbs +217 -6
  100. package/templates/python-fastapi/mvc/infra/modules/rds/main.tf.hbs +15 -15
  101. package/templates/python-fastapi/mvc/infra/modules/vpc/main.tf.hbs +170 -30
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kybernus",
3
- "version": "2.2.0",
3
+ "version": "2.3.0",
4
4
  "type": "module",
5
5
  "description": "The Ultimate Scaffolding CLI for Modern Developers",
6
6
  "main": "dist/index.js",
@@ -5,9 +5,13 @@ terraform {
5
5
 
6
6
  required_providers {
7
7
  aws = {
8
- source = "hashicorp/aws"
8
+ source = "hashicorp/aws"
9
9
  version = "~> 5.0"
10
10
  }
11
+ random = {
12
+ source = "hashicorp/random"
13
+ version = "~> 3.5"
14
+ }
11
15
  }
12
16
 
13
17
  # Uncomment for remote state (recommended for production)
@@ -27,27 +31,27 @@ provider "aws" {
27
31
  # Variables
28
32
  variable "aws_region" {
29
33
  description = "AWS region"
30
- type = string
31
- default = "us-east-1"
34
+ type = string
35
+ default = "us-east-1"
32
36
  }
33
37
 
34
38
  variable "environment" {
35
39
  description = "Environment name (dev, staging, prod)"
36
- type = string
37
- default = "dev"
40
+ type = string
41
+ default = "dev"
38
42
  }
39
43
 
40
44
  variable "app_name" {
41
45
  description = "Application name"
42
- type = string
43
- default = "{{projectNameKebabCase}}"
46
+ type = string
47
+ default = "{{projectNameKebabCase}}"
44
48
  }
45
49
 
46
50
  # VPC
47
51
  module "vpc" {
48
52
  source = "./modules/vpc"
49
53
 
50
- app_name = var.app_name
54
+ app_name = var.app_name
51
55
  environment = var.environment
52
56
  }
53
57
 
@@ -55,29 +59,49 @@ module "vpc" {
55
59
  module "ecs" {
56
60
  source = "./modules/ecs"
57
61
 
58
- app_name = var.app_name
59
- environment = var.environment
60
- vpc_id = module.vpc.vpc_id
61
- subnet_ids = module.vpc.private_subnet_ids
62
+ app_name = var.app_name
63
+ environment = var.environment
64
+ vpc_id = module.vpc.vpc_id
65
+ public_subnet_ids = module.vpc.public_subnet_ids
66
+ private_subnet_ids = module.vpc.private_subnet_ids
67
+ alb_security_group_id = module.vpc.alb_security_group_id
68
+ ecs_tasks_security_group_id = module.vpc.ecs_tasks_security_group_id
62
69
  }
63
70
 
64
71
  # RDS PostgreSQL
65
72
  module "rds" {
66
73
  source = "./modules/rds"
67
74
 
68
- app_name = var.app_name
69
- environment = var.environment
70
- vpc_id = module.vpc.vpc_id
71
- subnet_ids = module.vpc.private_subnet_ids
75
+ app_name = var.app_name
76
+ environment = var.environment
77
+ vpc_id = module.vpc.vpc_id
78
+ subnet_ids = module.vpc.private_subnet_ids
72
79
  security_group_id = module.vpc.db_security_group_id
73
80
  }
74
81
 
75
82
  # Outputs
83
+ output "vpc_id" {
84
+ value = module.vpc.vpc_id
85
+ }
86
+
76
87
  output "ecs_cluster_name" {
77
88
  value = module.ecs.cluster_name
78
89
  }
79
90
 
91
+ output "ecr_repository_url" {
92
+ value = module.ecs.ecr_repository_url
93
+ }
94
+
95
+ output "alb_dns_name" {
96
+ value = module.ecs.alb_dns_name
97
+ description = "The DNS name of the ALB to access the application"
98
+ }
99
+
80
100
  output "rds_endpoint" {
81
- value = module.rds.endpoint
101
+ value = module.rds.endpoint
82
102
  sensitive = true
83
- }
103
+ }
104
+
105
+ output "db_name" {
106
+ value = module.rds.db_name
107
+ }
@@ -12,21 +12,54 @@ variable "vpc_id" {
12
12
  type = string
13
13
  }
14
14
 
15
- variable "subnet_ids" {
15
+ variable "public_subnet_ids" {
16
16
  type = list(string)
17
17
  }
18
18
 
19
+ variable "private_subnet_ids" {
20
+ type = list(string)
21
+ }
22
+
23
+ variable "alb_security_group_id" {
24
+ type = string
25
+ }
26
+
27
+ variable "ecs_tasks_security_group_id" {
28
+ type = string
29
+ }
30
+
31
+ variable "container_port" {
32
+ type = number
33
+ default = 3000
34
+ }
35
+
36
+ # ECR Repository
37
+ resource "aws_ecr_repository" "app" {
38
+ name = "${var.app_name}-${var.environment}"
39
+ image_tag_mutability = "MUTABLE"
40
+ force_delete = true
41
+
42
+ image_scanning_configuration {
43
+ scan_on_push = true
44
+ }
45
+
46
+ tags = {
47
+ Name = "${var.app_name}-${var.environment}"
48
+ Environment = var.environment
49
+ }
50
+ }
51
+
19
52
  # ECS Cluster
20
53
  resource "aws_ecs_cluster" "main" {
21
54
  name = "${var.app_name}-${var.environment}"
22
55
 
23
56
  setting {
24
- name = "containerInsights"
57
+ name = "containerInsights"
25
58
  value = "enabled"
26
59
  }
27
60
 
28
61
  tags = {
29
- Name = "${var.app_name}-${var.environment}"
62
+ Name = "${var.app_name}-${var.environment}"
30
63
  Environment = var.environment
31
64
  }
32
65
  }
@@ -38,12 +71,182 @@ resource "aws_ecs_cluster_capacity_providers" "main" {
38
71
  capacity_providers = ["FARGATE", "FARGATE_SPOT"]
39
72
 
40
73
  default_capacity_provider_strategy {
41
- base = 1
42
- weight = 100
74
+ base = 1
75
+ weight = 100
43
76
  capacity_provider = "FARGATE"
44
77
  }
45
78
  }
46
79
 
80
+ # Application Load Balancer
81
+ resource "aws_lb" "main" {
82
+ name = "${var.app_name}-${var.environment}-alb"
83
+ internal = false
84
+ load_balancer_type = "application"
85
+ security_groups = [var.alb_security_group_id]
86
+ subnets = var.public_subnet_ids
87
+
88
+ enable_deletion_protection = false
89
+
90
+ tags = {
91
+ Name = "${var.app_name}-${var.environment}-alb"
92
+ Environment = var.environment
93
+ }
94
+ }
95
+
96
+ # ALB Target Group
97
+ resource "aws_lb_target_group" "app" {
98
+ name = "${var.app_name}-${var.environment}-tg"
99
+ port = var.container_port
100
+ protocol = "HTTP"
101
+ vpc_id = var.vpc_id
102
+ target_type = "ip"
103
+
104
+ health_check {
105
+ path = "/health"
106
+ healthy_threshold = 2
107
+ unhealthy_threshold = 10
108
+ timeout = 30
109
+ interval = 40
110
+ matcher = "200-399"
111
+ }
112
+
113
+ tags = {
114
+ Name = "${var.app_name}-${var.environment}-tg"
115
+ Environment = var.environment
116
+ }
117
+ }
118
+
119
+ # ALB Listener (HTTP)
120
+ resource "aws_lb_listener" "http" {
121
+ load_balancer_arn = aws_lb.main.arn
122
+ port = "80"
123
+ protocol = "HTTP"
124
+
125
+ default_action {
126
+ type = "forward"
127
+ target_group_arn = aws_lb_target_group.app.arn
128
+ }
129
+ }
130
+
131
+ # CloudWatch Log Group for ECS
132
+ resource "aws_cloudwatch_log_group" "ecs" {
133
+ name = "/ecs/${var.app_name}-${var.environment}"
134
+ retention_in_days = 14
135
+
136
+ tags = {
137
+ Environment = var.environment
138
+ }
139
+ }
140
+
141
+ # IAM Role for ECS Task Execution
142
+ resource "aws_iam_role" "ecs_task_execution_role" {
143
+ name = "${var.app_name}-${var.environment}-ecs-execution-role"
144
+
145
+ assume_role_policy = jsonencode({
146
+ Version = "2012-10-17"
147
+ Statement = [
148
+ {
149
+ Action = "sts:AssumeRole"
150
+ Effect = "Allow"
151
+ Principal = {
152
+ Service = "ecs-tasks.amazonaws.com"
153
+ }
154
+ }
155
+ ]
156
+ })
157
+ }
158
+
159
+ resource "aws_iam_role_policy_attachment" "ecs_task_execution_role_policy" {
160
+ role = aws_iam_role.ecs_task_execution_role.name
161
+ policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
162
+ }
163
+
164
+ # IAM Role for ECS Task (the application itself)
165
+ resource "aws_iam_role" "ecs_task_role" {
166
+ name = "${var.app_name}-${var.environment}-ecs-task-role"
167
+
168
+ assume_role_policy = jsonencode({
169
+ Version = "2012-10-17"
170
+ Statement = [
171
+ {
172
+ Action = "sts:AssumeRole"
173
+ Effect = "Allow"
174
+ Principal = {
175
+ Service = "ecs-tasks.amazonaws.com"
176
+ }
177
+ }
178
+ ]
179
+ })
180
+ }
181
+
182
+ # ECS Task Definition
183
+ resource "aws_ecs_task_definition" "app" {
184
+ family = "${var.app_name}-${var.environment}"
185
+ requires_compatibilities = ["FARGATE"]
186
+ network_mode = "awsvpc"
187
+ cpu = 256
188
+ memory = 512
189
+ execution_role_arn = aws_iam_role.ecs_task_execution_role.arn
190
+ task_role_arn = aws_iam_role.ecs_task_role.arn
191
+
192
+ container_definitions = jsonencode([
193
+ {
194
+ name = "${var.app_name}"
195
+ image = "${aws_ecr_repository.app.repository_url}:latest"
196
+ essential = true
197
+
198
+ portMappings = [
199
+ {
200
+ containerPort = var.container_port
201
+ hostPort = var.container_port
202
+ protocol = "tcp"
203
+ }
204
+ ]
205
+
206
+ environment = [
207
+ { name = "NODE_ENV", value = var.environment == "prod" ? "production" : "development" },
208
+ { name = "PORT", value = tostring(var.container_port) }
209
+ ]
210
+
211
+ # Note: Add Secrets (like DB passwords) via SSM Parameter Store dynamically in a real deployment
212
+
213
+ logConfiguration = {
214
+ logDriver = "awslogs"
215
+ options = {
216
+ "awslogs-group" = aws_cloudwatch_log_group.ecs.name
217
+ "awslogs-region" = "us-east-1"
218
+ "awslogs-stream-prefix" = "ecs"
219
+ }
220
+ }
221
+ }
222
+ ])
223
+ }
224
+
225
+ # ECS Service
226
+ resource "aws_ecs_service" "app" {
227
+ name = "${var.app_name}-${var.environment}"
228
+ cluster = aws_ecs_cluster.main.id
229
+ task_definition = aws_ecs_task_definition.app.arn
230
+ desired_count = 1
231
+ launch_type = "FARGATE"
232
+
233
+ network_configuration {
234
+ subnets = var.private_subnet_ids
235
+ security_groups = [var.ecs_tasks_security_group_id]
236
+ assign_public_ip = false
237
+ }
238
+
239
+ load_balancer {
240
+ target_group_arn = aws_lb_target_group.app.arn
241
+ container_name = "${var.app_name}"
242
+ container_port = var.container_port
243
+ }
244
+
245
+ depends_on = [
246
+ aws_lb_listener.http
247
+ ]
248
+ }
249
+
47
250
  # Outputs
48
251
  output "cluster_name" {
49
252
  value = aws_ecs_cluster.main.name
@@ -51,4 +254,12 @@ output "cluster_name" {
51
254
 
52
255
  output "cluster_arn" {
53
256
  value = aws_ecs_cluster.main.arn
54
- }
257
+ }
258
+
259
+ output "ecr_repository_url" {
260
+ value = aws_ecr_repository.app.repository_url
261
+ }
262
+
263
+ output "alb_dns_name" {
264
+ value = aws_lb.main.dns_name
265
+ }
@@ -22,11 +22,11 @@ variable "security_group_id" {
22
22
 
23
23
  # DB Subnet Group
24
24
  resource "aws_db_subnet_group" "main" {
25
- name = "${var.app_name}-${var.environment}"
25
+ name = "${var.app_name}-${var.environment}"
26
26
  subnet_ids = var.subnet_ids
27
27
 
28
28
  tags = {
29
- Name = "${var.app_name}-${var.environment}"
29
+ Name = "${var.app_name}-${var.environment}"
30
30
  Environment = var.environment
31
31
  }
32
32
  }
@@ -35,43 +35,43 @@ resource "aws_db_subnet_group" "main" {
35
35
  resource "aws_db_instance" "main" {
36
36
  identifier = "${var.app_name}-${var.environment}"
37
37
 
38
- engine = "postgres"
38
+ engine = "postgres"
39
39
  engine_version = "16"
40
40
  instance_class = "db.t3.micro"
41
41
 
42
- allocated_storage = 20
42
+ allocated_storage = 20
43
43
  max_allocated_storage = 100
44
- storage_type = "gp3"
45
- storage_encrypted = true
44
+ storage_type = "gp3"
45
+ storage_encrypted = true
46
46
 
47
- db_name = replace(var.app_name, "-", "_")
47
+ db_name = replace(var.app_name, "-", "_")
48
48
  username = "postgres"
49
49
  password = random_password.db_password.result
50
50
 
51
- db_subnet_group_name = aws_db_subnet_group.main.name
51
+ db_subnet_group_name = aws_db_subnet_group.main.name
52
52
  vpc_security_group_ids = [var.security_group_id]
53
53
 
54
54
  backup_retention_period = 7
55
- skip_final_snapshot = var.environment != "prod"
55
+ skip_final_snapshot = var.environment != "prod"
56
56
 
57
57
  tags = {
58
- Name = "${var.app_name}-${var.environment}"
58
+ Name = "${var.app_name}-${var.environment}"
59
59
  Environment = var.environment
60
60
  }
61
61
  }
62
62
 
63
63
  # Random password for DB
64
64
  resource "random_password" "db_password" {
65
- length = 32
65
+ length = 32
66
66
  special = false
67
67
  }
68
68
 
69
69
  # Store password in SSM
70
70
  resource "aws_ssm_parameter" "db_password" {
71
- name = "/${var.app_name}/${var.environment}/db-password"
71
+ name = "/${var.app_name}/${var.environment}/db-password"
72
72
  description = "Database password for ${var.app_name}"
73
- type = "SecureString"
74
- value = random_password.db_password.result
73
+ type = "SecureString"
74
+ value = random_password.db_password.result
75
75
 
76
76
  tags = {
77
77
  Environment = var.environment
@@ -85,4 +85,4 @@ output "endpoint" {
85
85
 
86
86
  output "db_name" {
87
87
  value = aws_db_instance.main.db_name
88
- }
88
+ }
@@ -10,81 +10,213 @@ variable "environment" {
10
10
 
11
11
  # VPC
12
12
  resource "aws_vpc" "main" {
13
- cidr_block = "10.0.0.0/16"
13
+ cidr_block = "10.0.0.0/16"
14
14
  enable_dns_hostnames = true
15
- enable_dns_support = true
15
+ enable_dns_support = true
16
16
 
17
17
  tags = {
18
- Name = "${var.app_name}-${var.environment}-vpc"
18
+ Name = "${var.app_name}-${var.environment}-vpc"
19
19
  Environment = var.environment
20
20
  }
21
21
  }
22
22
 
23
+ # Internet Gateway
24
+ resource "aws_internet_gateway" "main" {
25
+ vpc_id = aws_vpc.main.id
26
+
27
+ tags = {
28
+ Name = "${var.app_name}-${var.environment}-igw"
29
+ Environment = var.environment
30
+ }
31
+ }
32
+
33
+ # Data source for AZs
34
+ data "aws_availability_zones" "available" {
35
+ state = "available"
36
+ }
37
+
23
38
  # Public Subnets
24
39
  resource "aws_subnet" "public" {
25
- count = 2
40
+ count = 2
41
+ vpc_id = aws_vpc.main.id
42
+ cidr_block = "10.0.${count.index + 1}.0/24"
43
+ availability_zone = data.aws_availability_zones.available.names[count.index]
44
+ map_public_ip_on_launch = true
45
+
46
+ tags = {
47
+ Name = "${var.app_name}-${var.environment}-public-${count.index + 1}"
48
+ Environment = var.environment
49
+ }
50
+ }
51
+
52
+ # Route Table for Public Subnets
53
+ resource "aws_route_table" "public" {
26
54
  vpc_id = aws_vpc.main.id
27
- cidr_block = "10.0.${count.index + 1}.0/24"
28
- availability_zone = data.aws_availability_zones.available.names[count.index]
29
55
 
30
- map_public_ip_on_launch = true
56
+ route {
57
+ cidr_block = "0.0.0.0/0"
58
+ gateway_id = aws_internet_gateway.main.id
59
+ }
60
+
61
+ tags = {
62
+ Name = "${var.app_name}-${var.environment}-public-rt"
63
+ Environment = var.environment
64
+ }
65
+ }
66
+
67
+ # Association for Public Subnets
68
+ resource "aws_route_table_association" "public" {
69
+ count = 2
70
+ subnet_id = aws_subnet.public[count.index].id
71
+ route_table_id = aws_route_table.public.id
72
+ }
73
+
74
+ # Elastic IP for NAT Gateway
75
+ resource "aws_eip" "nat" {
76
+ count = 1
77
+ domain = "vpc"
31
78
 
32
79
  tags = {
33
- Name = "${var.app_name}-${var.environment}-public-${count.index + 1}"
80
+ Name = "${var.app_name}-${var.environment}-nat-eip"
81
+ Environment = var.environment
82
+ }
83
+ }
84
+
85
+ # NAT Gateway (single NAT for cost savings, can change to 1 per AZ for production if needed)
86
+ resource "aws_nat_gateway" "main" {
87
+ count = 1
88
+ allocation_id = aws_eip.nat[0].id
89
+ subnet_id = aws_subnet.public[0].id
90
+
91
+ depends_on = [aws_internet_gateway.main]
92
+
93
+ tags = {
94
+ Name = "${var.app_name}-${var.environment}-nat"
34
95
  Environment = var.environment
35
96
  }
36
97
  }
37
98
 
38
99
  # Private Subnets
39
100
  resource "aws_subnet" "private" {
40
- count = 2
41
- vpc_id = aws_vpc.main.id
42
- cidr_block = "10.0.${count.index + 10}.0/24"
101
+ count = 2
102
+ vpc_id = aws_vpc.main.id
103
+ cidr_block = "10.0.${count.index + 10}.0/24"
43
104
  availability_zone = data.aws_availability_zones.available.names[count.index]
44
105
 
45
106
  tags = {
46
- Name = "${var.app_name}-${var.environment}-private-${count.index + 1}"
107
+ Name = "${var.app_name}-${var.environment}-private-${count.index + 1}"
47
108
  Environment = var.environment
48
109
  }
49
110
  }
50
111
 
51
- # Internet Gateway
52
- resource "aws_internet_gateway" "main" {
112
+ # Route Table for Private Subnets
113
+ resource "aws_route_table" "private" {
53
114
  vpc_id = aws_vpc.main.id
54
115
 
116
+ route {
117
+ cidr_block = "0.0.0.0/0"
118
+ nat_gateway_id = aws_nat_gateway.main[0].id
119
+ }
120
+
55
121
  tags = {
56
- Name = "${var.app_name}-${var.environment}-igw"
122
+ Name = "${var.app_name}-${var.environment}-private-rt"
57
123
  Environment = var.environment
58
124
  }
59
125
  }
60
126
 
61
- # Data source for AZs
62
- data "aws_availability_zones" "available" {
63
- state = "available"
127
+ # Association for Private Subnets
128
+ resource "aws_route_table_association" "private" {
129
+ count = 2
130
+ subnet_id = aws_subnet.private[count.index].id
131
+ route_table_id = aws_route_table.private.id
132
+ }
133
+
134
+ # Security Group for Load Balancer (ALB)
135
+ resource "aws_security_group" "alb" {
136
+ name = "${var.app_name}-${var.environment}-alb-sg"
137
+ description = "Security group for ALB"
138
+ vpc_id = aws_vpc.main.id
139
+
140
+ ingress {
141
+ from_port = 80
142
+ to_port = 80
143
+ protocol = "tcp"
144
+ cidr_blocks = ["0.0.0.0/0"]
145
+ description = "Allow HTTP from anywhere"
146
+ }
147
+
148
+ ingress {
149
+ from_port = 443
150
+ to_port = 443
151
+ protocol = "tcp"
152
+ cidr_blocks = ["0.0.0.0/0"]
153
+ description = "Allow HTTPS from anywhere"
154
+ }
155
+
156
+ egress {
157
+ from_port = 0
158
+ to_port = 0
159
+ protocol = "-1"
160
+ cidr_blocks = ["0.0.0.0/0"]
161
+ }
162
+
163
+ tags = {
164
+ Name = "${var.app_name}-${var.environment}-alb-sg"
165
+ Environment = var.environment
166
+ }
64
167
  }
65
168
 
66
- # Security Group for DB
169
+ # Security Group for ECS Tasks
170
+ resource "aws_security_group" "ecs_tasks" {
171
+ name = "${var.app_name}-${var.environment}-ecs-tasks-sg"
172
+ description = "Security group for ECS tasks"
173
+ vpc_id = aws_vpc.main.id
174
+
175
+ ingress {
176
+ from_port = 0
177
+ to_port = 0
178
+ protocol = "-1"
179
+ security_groups = [aws_security_group.alb.id]
180
+ description = "Allow all traffic from ALB"
181
+ }
182
+
183
+ egress {
184
+ from_port = 0
185
+ to_port = 0
186
+ protocol = "-1"
187
+ cidr_blocks = ["0.0.0.0/0"]
188
+ description = "Allow all outbound traffic"
189
+ }
190
+
191
+ tags = {
192
+ Name = "${var.app_name}-${var.environment}-ecs-tasks-sg"
193
+ Environment = var.environment
194
+ }
195
+ }
196
+
197
+ # Security Group for Database (RDS)
67
198
  resource "aws_security_group" "db" {
68
- name = "${var.app_name}-${var.environment}-db-sg"
199
+ name = "${var.app_name}-${var.environment}-db-sg"
69
200
  description = "Security group for database"
70
- vpc_id = aws_vpc.main.id
201
+ vpc_id = aws_vpc.main.id
71
202
 
72
203
  ingress {
73
- from_port = 5432
74
- to_port = 5432
75
- protocol = "tcp"
76
- cidr_blocks = ["10.0.0.0/16"]
204
+ from_port = 5432
205
+ to_port = 5432
206
+ protocol = "tcp"
207
+ security_groups = [aws_security_group.ecs_tasks.id]
208
+ description = "Allow PostgreSQL access from ECS tasks"
77
209
  }
78
210
 
79
211
  egress {
80
- from_port = 0
81
- to_port = 0
82
- protocol = "-1"
212
+ from_port = 0
213
+ to_port = 0
214
+ protocol = "-1"
83
215
  cidr_blocks = ["0.0.0.0/0"]
84
216
  }
85
217
 
86
218
  tags = {
87
- Name = "${var.app_name}-${var.environment}-db-sg"
219
+ Name = "${var.app_name}-${var.environment}-db-sg"
88
220
  Environment = var.environment
89
221
  }
90
222
  }
@@ -104,4 +236,12 @@ output "private_subnet_ids" {
104
236
 
105
237
  output "db_security_group_id" {
106
238
  value = aws_security_group.db.id
107
- }
239
+ }
240
+
241
+ output "alb_security_group_id" {
242
+ value = aws_security_group.alb.id
243
+ }
244
+
245
+ output "ecs_tasks_security_group_id" {
246
+ value = aws_security_group.ecs_tasks.id
247
+ }