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,224 @@
1
+ # ---------------------------------------------------------------------------------------------------------------------
2
+ # API GATEWAY MODULE — REST API with Lambda Integration
3
+ # Project: {{ project_name }}
4
+ # Generated by tf-starter
5
+ # ---------------------------------------------------------------------------------------------------------------------
6
+
7
+ locals {
8
+ name_prefix = "${var.project_name}-${var.environment}"
9
+ api_name = "${local.name_prefix}-api"
10
+ }
11
+
12
+ # ---------------------------------------------------------------------------------------------------------------------
13
+ # REST API
14
+ # ---------------------------------------------------------------------------------------------------------------------
15
+
16
+ resource "aws_api_gateway_rest_api" "main" {
17
+ name = local.api_name
18
+ description = "${var.project_name} REST API (${var.environment})"
19
+
20
+ endpoint_configuration {
21
+ types = [var.endpoint_type]
22
+ }
23
+
24
+ tags = merge(var.tags, {
25
+ Name = local.api_name
26
+ })
27
+ }
28
+
29
+ # ---------------------------------------------------------------------------------------------------------------------
30
+ # API RESOURCE — /api proxy path
31
+ # ---------------------------------------------------------------------------------------------------------------------
32
+
33
+ resource "aws_api_gateway_resource" "proxy" {
34
+ rest_api_id = aws_api_gateway_rest_api.main.id
35
+ parent_id = aws_api_gateway_rest_api.main.root_resource_id
36
+ path_part = "{proxy+}"
37
+ }
38
+
39
+ # ---------------------------------------------------------------------------------------------------------------------
40
+ # ANY METHOD — catch-all for proxy+ resource
41
+ # ---------------------------------------------------------------------------------------------------------------------
42
+
43
+ resource "aws_api_gateway_method" "proxy" {
44
+ rest_api_id = aws_api_gateway_rest_api.main.id
45
+ resource_id = aws_api_gateway_resource.proxy.id
46
+ http_method = "ANY"
47
+ authorization = var.authorization_type
48
+
49
+ ### MUST EDIT THIS ###
50
+ # For Cognito or custom authorizers, set:
51
+ # authorizer_id = aws_api_gateway_authorizer.main.id
52
+ }
53
+
54
+ resource "aws_api_gateway_integration" "proxy" {
55
+ rest_api_id = aws_api_gateway_rest_api.main.id
56
+ resource_id = aws_api_gateway_resource.proxy.id
57
+ http_method = aws_api_gateway_method.proxy.http_method
58
+ integration_http_method = "POST"
59
+ type = "AWS_PROXY"
60
+ uri = var.lambda_invoke_arn
61
+ }
62
+
63
+ # ---------------------------------------------------------------------------------------------------------------------
64
+ # ROOT METHOD — handle requests to /
65
+ # ---------------------------------------------------------------------------------------------------------------------
66
+
67
+ resource "aws_api_gateway_method" "root" {
68
+ rest_api_id = aws_api_gateway_rest_api.main.id
69
+ resource_id = aws_api_gateway_rest_api.main.root_resource_id
70
+ http_method = "ANY"
71
+ authorization = var.authorization_type
72
+ }
73
+
74
+ resource "aws_api_gateway_integration" "root" {
75
+ rest_api_id = aws_api_gateway_rest_api.main.id
76
+ resource_id = aws_api_gateway_rest_api.main.root_resource_id
77
+ http_method = aws_api_gateway_method.root.http_method
78
+ integration_http_method = "POST"
79
+ type = "AWS_PROXY"
80
+ uri = var.lambda_invoke_arn
81
+ }
82
+
83
+ # ---------------------------------------------------------------------------------------------------------------------
84
+ # LAMBDA PERMISSION — allow API Gateway to invoke Lambda
85
+ # ---------------------------------------------------------------------------------------------------------------------
86
+
87
+ resource "aws_lambda_permission" "apigw" {
88
+ statement_id = "AllowAPIGatewayInvoke"
89
+ action = "lambda:InvokeFunction"
90
+ function_name = var.lambda_function_name
91
+ principal = "apigateway.amazonaws.com"
92
+ source_arn = "${aws_api_gateway_rest_api.main.execution_arn}/*/*"
93
+ }
94
+
95
+ # ---------------------------------------------------------------------------------------------------------------------
96
+ # DEPLOYMENT & STAGE
97
+ # ---------------------------------------------------------------------------------------------------------------------
98
+
99
+ resource "aws_api_gateway_deployment" "main" {
100
+ rest_api_id = aws_api_gateway_rest_api.main.id
101
+
102
+ triggers = {
103
+ redeployment = sha1(jsonencode([
104
+ aws_api_gateway_resource.proxy.id,
105
+ aws_api_gateway_method.proxy.id,
106
+ aws_api_gateway_integration.proxy.id,
107
+ aws_api_gateway_method.root.id,
108
+ aws_api_gateway_integration.root.id,
109
+ ]))
110
+ }
111
+
112
+ lifecycle {
113
+ create_before_destroy = true
114
+ }
115
+ }
116
+
117
+ resource "aws_api_gateway_stage" "main" {
118
+ deployment_id = aws_api_gateway_deployment.main.id
119
+ rest_api_id = aws_api_gateway_rest_api.main.id
120
+ stage_name = var.environment
121
+
122
+ access_log_settings {
123
+ destination_arn = aws_cloudwatch_log_group.api.arn
124
+ }
125
+
126
+ tags = merge(var.tags, {
127
+ Name = "${local.api_name}-${var.environment}"
128
+ })
129
+ }
130
+
131
+ # ---------------------------------------------------------------------------------------------------------------------
132
+ # METHOD SETTINGS — throttling & logging
133
+ # ---------------------------------------------------------------------------------------------------------------------
134
+
135
+ resource "aws_api_gateway_method_settings" "all" {
136
+ rest_api_id = aws_api_gateway_rest_api.main.id
137
+ stage_name = aws_api_gateway_stage.main.stage_name
138
+ method_path = "*/*"
139
+
140
+ settings {
141
+ metrics_enabled = true
142
+ logging_level = "INFO"
143
+ data_trace_enabled = var.environment != "prod"
144
+ throttling_burst_limit = var.throttle_burst_limit
145
+ throttling_rate_limit = var.throttle_rate_limit
146
+ }
147
+ }
148
+
149
+ # ---------------------------------------------------------------------------------------------------------------------
150
+ # CLOUDWATCH LOG GROUP FOR ACCESS LOGS
151
+ # ---------------------------------------------------------------------------------------------------------------------
152
+
153
+ resource "aws_cloudwatch_log_group" "api" {
154
+ name = "/aws/apigateway/${local.api_name}"
155
+ retention_in_days = var.environment == "prod" ? 90 : 14
156
+
157
+ tags = var.tags
158
+ }
159
+
160
+ # ---------------------------------------------------------------------------------------------------------------------
161
+ # CORS CONFIGURATION (OPTIONS method for proxy+ resource)
162
+ # ---------------------------------------------------------------------------------------------------------------------
163
+
164
+ resource "aws_api_gateway_method" "options" {
165
+ count = var.enable_cors ? 1 : 0
166
+
167
+ rest_api_id = aws_api_gateway_rest_api.main.id
168
+ resource_id = aws_api_gateway_resource.proxy.id
169
+ http_method = "OPTIONS"
170
+ authorization = "NONE"
171
+ }
172
+
173
+ resource "aws_api_gateway_integration" "options" {
174
+ count = var.enable_cors ? 1 : 0
175
+
176
+ rest_api_id = aws_api_gateway_rest_api.main.id
177
+ resource_id = aws_api_gateway_resource.proxy.id
178
+ http_method = aws_api_gateway_method.options[0].http_method
179
+ type = "MOCK"
180
+
181
+ request_templates = {
182
+ "application/json" = jsonencode({ statusCode = 200 })
183
+ }
184
+ }
185
+
186
+ resource "aws_api_gateway_method_response" "options" {
187
+ count = var.enable_cors ? 1 : 0
188
+
189
+ rest_api_id = aws_api_gateway_rest_api.main.id
190
+ resource_id = aws_api_gateway_resource.proxy.id
191
+ http_method = aws_api_gateway_method.options[0].http_method
192
+ status_code = "200"
193
+
194
+ response_parameters = {
195
+ "method.response.header.Access-Control-Allow-Headers" = true
196
+ "method.response.header.Access-Control-Allow-Methods" = true
197
+ "method.response.header.Access-Control-Allow-Origin" = true
198
+ }
199
+
200
+ response_models = {
201
+ "application/json" = "Empty"
202
+ }
203
+ }
204
+
205
+ resource "aws_api_gateway_integration_response" "options" {
206
+ count = var.enable_cors ? 1 : 0
207
+
208
+ rest_api_id = aws_api_gateway_rest_api.main.id
209
+ resource_id = aws_api_gateway_resource.proxy.id
210
+ http_method = aws_api_gateway_method.options[0].http_method
211
+ status_code = aws_api_gateway_method_response.options[0].status_code
212
+
213
+ response_parameters = {
214
+ "method.response.header.Access-Control-Allow-Headers" = "'Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token'"
215
+ "method.response.header.Access-Control-Allow-Methods" = "'GET,POST,PUT,DELETE,OPTIONS'"
216
+ "method.response.header.Access-Control-Allow-Origin" = "'*'"
217
+
218
+ ### MUST EDIT THIS ###
219
+ # For production, restrict the origin:
220
+ # "method.response.header.Access-Control-Allow-Origin" = "'https://yourdomain.com'"
221
+ }
222
+
223
+ depends_on = [aws_api_gateway_integration.options[0]]
224
+ }
@@ -0,0 +1,28 @@
1
+ # ---------------------------------------------------------------------------------------------------------------------
2
+ # API GATEWAY MODULE — Outputs
3
+ # ---------------------------------------------------------------------------------------------------------------------
4
+
5
+ output "api_id" {
6
+ description = "ID of the REST API"
7
+ value = aws_api_gateway_rest_api.main.id
8
+ }
9
+
10
+ output "api_arn" {
11
+ description = "ARN of the REST API"
12
+ value = aws_api_gateway_rest_api.main.arn
13
+ }
14
+
15
+ output "api_endpoint" {
16
+ description = "Invoke URL for the API stage"
17
+ value = aws_api_gateway_stage.main.invoke_url
18
+ }
19
+
20
+ output "stage_name" {
21
+ description = "Name of the deployed stage"
22
+ value = aws_api_gateway_stage.main.stage_name
23
+ }
24
+
25
+ output "execution_arn" {
26
+ description = "Execution ARN of the REST API"
27
+ value = aws_api_gateway_rest_api.main.execution_arn
28
+ }
@@ -0,0 +1,69 @@
1
+ # ---------------------------------------------------------------------------------------------------------------------
2
+ # API GATEWAY 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 "lambda_function_name" {
16
+ description = "Name of the Lambda function to integrate with"
17
+ type = string
18
+ }
19
+
20
+ variable "lambda_invoke_arn" {
21
+ description = "Invoke ARN of the Lambda function"
22
+ type = string
23
+ }
24
+
25
+ variable "endpoint_type" {
26
+ description = "API Gateway endpoint type (REGIONAL, EDGE, PRIVATE)"
27
+ type = string
28
+ default = "REGIONAL"
29
+
30
+ validation {
31
+ condition = contains(["REGIONAL", "EDGE", "PRIVATE"], var.endpoint_type)
32
+ error_message = "Endpoint type must be REGIONAL, EDGE, or PRIVATE."
33
+ }
34
+ }
35
+
36
+ variable "authorization_type" {
37
+ description = "Default authorization type for API methods"
38
+ type = string
39
+ default = "NONE"
40
+
41
+ validation {
42
+ condition = contains(["NONE", "AWS_IAM", "COGNITO_USER_POOLS", "CUSTOM"], var.authorization_type)
43
+ error_message = "Authorization type must be NONE, AWS_IAM, COGNITO_USER_POOLS, or CUSTOM."
44
+ }
45
+ }
46
+
47
+ variable "throttle_burst_limit" {
48
+ description = "API Gateway throttle burst limit"
49
+ type = number
50
+ default = 100
51
+ }
52
+
53
+ variable "throttle_rate_limit" {
54
+ description = "API Gateway throttle rate limit (requests/second)"
55
+ type = number
56
+ default = 50
57
+ }
58
+
59
+ variable "enable_cors" {
60
+ description = "Enable CORS support on the API"
61
+ type = bool
62
+ default = true
63
+ }
64
+
65
+ variable "tags" {
66
+ description = "Common resource tags"
67
+ type = map(string)
68
+ default = {}
69
+ }
@@ -0,0 +1,245 @@
1
+ # ---------------------------------------------------------------------------------------------------------------------
2
+ # COMPUTE MODULE — Launch Template, Auto Scaling Group, Application Load Balancer
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 GROUPS
13
+ # ---------------------------------------------------------------------------------------------------------------------
14
+
15
+ resource "aws_security_group" "alb" {
16
+ name_prefix = "${local.name_prefix}-alb-"
17
+ description = "Security group for the Application Load Balancer"
18
+ vpc_id = var.vpc_id
19
+
20
+ ingress {
21
+ description = "HTTP from Internet"
22
+ from_port = 80
23
+ to_port = 80
24
+ protocol = "tcp"
25
+ cidr_blocks = ["0.0.0.0/0"]
26
+ }
27
+
28
+ ingress {
29
+ description = "HTTPS from Internet"
30
+ from_port = 443
31
+ to_port = 443
32
+ protocol = "tcp"
33
+ cidr_blocks = ["0.0.0.0/0"]
34
+ }
35
+
36
+ egress {
37
+ from_port = 0
38
+ to_port = 0
39
+ protocol = "-1"
40
+ cidr_blocks = ["0.0.0.0/0"]
41
+ }
42
+
43
+ tags = merge(var.tags, {
44
+ Name = "${local.name_prefix}-alb-sg"
45
+ })
46
+
47
+ lifecycle {
48
+ create_before_destroy = true
49
+ }
50
+ }
51
+
52
+ resource "aws_security_group" "instances" {
53
+ name_prefix = "${local.name_prefix}-ec2-"
54
+ description = "Security group for EC2 instances"
55
+ vpc_id = var.vpc_id
56
+
57
+ ingress {
58
+ description = "HTTP from ALB"
59
+ from_port = 80
60
+ to_port = 80
61
+ protocol = "tcp"
62
+ security_groups = [aws_security_group.alb.id]
63
+ }
64
+
65
+ egress {
66
+ from_port = 0
67
+ to_port = 0
68
+ protocol = "-1"
69
+ cidr_blocks = ["0.0.0.0/0"]
70
+ }
71
+
72
+ tags = merge(var.tags, {
73
+ Name = "${local.name_prefix}-ec2-sg"
74
+ })
75
+
76
+ lifecycle {
77
+ create_before_destroy = true
78
+ }
79
+ }
80
+
81
+ # ---------------------------------------------------------------------------------------------------------------------
82
+ # APPLICATION LOAD BALANCER
83
+ # ---------------------------------------------------------------------------------------------------------------------
84
+
85
+ resource "aws_lb" "main" {
86
+ name = "${local.name_prefix}-alb"
87
+ internal = false
88
+ load_balancer_type = "application"
89
+ security_groups = [aws_security_group.alb.id]
90
+ subnets = var.public_subnet_ids
91
+
92
+ enable_deletion_protection = var.environment == "prod" ? true : false
93
+
94
+ tags = merge(var.tags, {
95
+ Name = "${local.name_prefix}-alb"
96
+ })
97
+ }
98
+
99
+ resource "aws_lb_target_group" "main" {
100
+ name = "${local.name_prefix}-tg"
101
+ port = 80
102
+ protocol = "HTTP"
103
+ vpc_id = var.vpc_id
104
+
105
+ health_check {
106
+ enabled = true
107
+ path = "/"
108
+ port = "traffic-port"
109
+ protocol = "HTTP"
110
+ healthy_threshold = 3
111
+ unhealthy_threshold = 3
112
+ timeout = 5
113
+ interval = 30
114
+ matcher = "200"
115
+ }
116
+
117
+ tags = merge(var.tags, {
118
+ Name = "${local.name_prefix}-tg"
119
+ })
120
+ }
121
+
122
+ resource "aws_lb_listener" "http" {
123
+ load_balancer_arn = aws_lb.main.arn
124
+ port = 80
125
+ protocol = "HTTP"
126
+
127
+ default_action {
128
+ type = "forward"
129
+ target_group_arn = aws_lb_target_group.main.arn
130
+ }
131
+
132
+ ### MUST EDIT THIS ###
133
+ # For production, add an HTTPS listener with an ACM certificate:
134
+ # resource "aws_lb_listener" "https" { ... }
135
+ }
136
+
137
+ # ---------------------------------------------------------------------------------------------------------------------
138
+ # LAUNCH TEMPLATE
139
+ # ---------------------------------------------------------------------------------------------------------------------
140
+
141
+ data "aws_ami" "amazon_linux" {
142
+ most_recent = true
143
+ owners = ["amazon"]
144
+
145
+ filter {
146
+ name = "name"
147
+ values = ["al2023-ami-*-x86_64"]
148
+ }
149
+
150
+ filter {
151
+ name = "virtualization-type"
152
+ values = ["hvm"]
153
+ }
154
+ }
155
+
156
+ resource "aws_launch_template" "main" {
157
+ name_prefix = "${local.name_prefix}-lt-"
158
+ image_id = data.aws_ami.amazon_linux.id
159
+ instance_type = var.instance_type
160
+
161
+ vpc_security_group_ids = [aws_security_group.instances.id]
162
+
163
+ monitoring {
164
+ enabled = true
165
+ }
166
+
167
+ metadata_options {
168
+ http_endpoint = "enabled"
169
+ http_tokens = "required" # IMDSv2
170
+ http_put_response_hop_limit = 1
171
+ }
172
+
173
+ tag_specifications {
174
+ resource_type = "instance"
175
+ tags = merge(var.tags, {
176
+ Name = "${local.name_prefix}-instance"
177
+ })
178
+ }
179
+
180
+ ### MUST EDIT THIS ###
181
+ # Add user_data for application bootstrap:
182
+ # user_data = base64encode(templatefile("${path.module}/user_data.sh", { ... }))
183
+
184
+ lifecycle {
185
+ create_before_destroy = true
186
+ }
187
+ }
188
+
189
+ # ---------------------------------------------------------------------------------------------------------------------
190
+ # AUTO SCALING GROUP
191
+ # ---------------------------------------------------------------------------------------------------------------------
192
+
193
+ resource "aws_autoscaling_group" "main" {
194
+ name = "${local.name_prefix}-asg"
195
+ desired_capacity = var.desired_capacity
196
+ min_size = var.min_size
197
+ max_size = var.max_size
198
+ vpc_zone_identifier = var.private_subnet_ids
199
+ target_group_arns = [aws_lb_target_group.main.arn]
200
+ health_check_type = "ELB"
201
+
202
+ launch_template {
203
+ id = aws_launch_template.main.id
204
+ version = "$Latest"
205
+ }
206
+
207
+ tag {
208
+ key = "Name"
209
+ value = "${local.name_prefix}-asg"
210
+ propagate_at_launch = false
211
+ }
212
+
213
+ dynamic "tag" {
214
+ for_each = var.tags
215
+ content {
216
+ key = tag.key
217
+ value = tag.value
218
+ propagate_at_launch = true
219
+ }
220
+ }
221
+
222
+ lifecycle {
223
+ ignore_changes = [desired_capacity]
224
+ }
225
+ }
226
+
227
+ # ---------------------------------------------------------------------------------------------------------------------
228
+ # AUTO SCALING POLICIES
229
+ # ---------------------------------------------------------------------------------------------------------------------
230
+
231
+ resource "aws_autoscaling_policy" "scale_up" {
232
+ name = "${local.name_prefix}-scale-up"
233
+ scaling_adjustment = 1
234
+ adjustment_type = "ChangeInCapacity"
235
+ cooldown = 300
236
+ autoscaling_group_name = aws_autoscaling_group.main.name
237
+ }
238
+
239
+ resource "aws_autoscaling_policy" "scale_down" {
240
+ name = "${local.name_prefix}-scale-down"
241
+ scaling_adjustment = -1
242
+ adjustment_type = "ChangeInCapacity"
243
+ cooldown = 300
244
+ autoscaling_group_name = aws_autoscaling_group.main.name
245
+ }
@@ -0,0 +1,38 @@
1
+ # ---------------------------------------------------------------------------------------------------------------------
2
+ # COMPUTE MODULE — Outputs
3
+ # ---------------------------------------------------------------------------------------------------------------------
4
+
5
+ output "alb_dns_name" {
6
+ description = "DNS name of the Application Load Balancer"
7
+ value = aws_lb.main.dns_name
8
+ }
9
+
10
+ output "alb_arn" {
11
+ description = "ARN of the Application Load Balancer"
12
+ value = aws_lb.main.arn
13
+ }
14
+
15
+ output "alb_zone_id" {
16
+ description = "Zone ID of the Application Load Balancer"
17
+ value = aws_lb.main.zone_id
18
+ }
19
+
20
+ output "asg_name" {
21
+ description = "Name of the Auto Scaling Group"
22
+ value = aws_autoscaling_group.main.name
23
+ }
24
+
25
+ output "asg_arn" {
26
+ description = "ARN of the Auto Scaling Group"
27
+ value = aws_autoscaling_group.main.arn
28
+ }
29
+
30
+ output "launch_template_id" {
31
+ description = "ID of the Launch Template"
32
+ value = aws_launch_template.main.id
33
+ }
34
+
35
+ output "instance_security_group_id" {
36
+ description = "ID of the EC2 instances security group"
37
+ value = aws_security_group.instances.id
38
+ }
@@ -0,0 +1,68 @@
1
+ # ---------------------------------------------------------------------------------------------------------------------
2
+ # COMPUTE 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 "public_subnet_ids" {
21
+ description = "IDs of the public subnets (for ALB)"
22
+ type = list(string)
23
+ }
24
+
25
+ variable "private_subnet_ids" {
26
+ description = "IDs of the private subnets (for EC2 instances)"
27
+ type = list(string)
28
+ }
29
+
30
+ variable "instance_type" {
31
+ description = "EC2 instance type"
32
+ type = string
33
+ default = "t3.medium"
34
+ }
35
+
36
+ variable "min_size" {
37
+ description = "Minimum number of instances in the ASG"
38
+ type = number
39
+ default = 1
40
+
41
+ validation {
42
+ condition = var.min_size >= 0
43
+ error_message = "Minimum size must be non-negative."
44
+ }
45
+ }
46
+
47
+ variable "max_size" {
48
+ description = "Maximum number of instances in the ASG"
49
+ type = number
50
+ default = 4
51
+
52
+ validation {
53
+ condition = var.max_size >= 1
54
+ error_message = "Maximum size must be at least 1."
55
+ }
56
+ }
57
+
58
+ variable "desired_capacity" {
59
+ description = "Desired number of instances in the ASG"
60
+ type = number
61
+ default = 2
62
+ }
63
+
64
+ variable "tags" {
65
+ description = "Common resource tags"
66
+ type = map(string)
67
+ default = {}
68
+ }