@aws/nx-plugin 0.45.1 → 0.47.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/infra/app/generator.js +4 -1
- package/src/infra/app/generator.js.map +1 -1
- package/src/py/fast-api/__snapshots__/generator.spec.ts.snap +3729 -0
- package/src/py/fast-api/generator.js +57 -50
- package/src/py/fast-api/generator.js.map +1 -1
- package/src/py/fast-api/react/__snapshots__/generator.spec.ts.snap +1 -0
- package/src/py/fast-api/schema.d.ts +1 -0
- package/src/py/fast-api/schema.json +8 -0
- package/src/py/lambda-function/__snapshots__/generator.spec.ts.snap +310 -0
- package/src/py/lambda-function/generator.js +15 -25
- package/src/py/lambda-function/generator.js.map +1 -1
- package/src/py/lambda-function/schema.d.ts +1 -0
- package/src/py/lambda-function/schema.json +8 -0
- package/src/py/mcp-server/__snapshots__/generator.spec.ts.snap +590 -0
- package/src/py/mcp-server/generator.js +4 -18
- package/src/py/mcp-server/generator.js.map +1 -1
- package/src/py/mcp-server/schema.d.ts +1 -0
- package/src/py/mcp-server/schema.json +8 -0
- package/src/py/strands-agent/__snapshots__/generator.spec.ts.snap +590 -0
- package/src/py/strands-agent/generator.js +4 -18
- package/src/py/strands-agent/generator.js.map +1 -1
- package/src/py/strands-agent/schema.d.ts +1 -0
- package/src/py/strands-agent/schema.json +8 -0
- package/src/terraform/project/generator.js +23 -7
- package/src/terraform/project/generator.js.map +1 -1
- package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +3729 -0
- package/src/trpc/backend/generator.js +6 -17
- package/src/trpc/backend/generator.js.map +1 -1
- package/src/trpc/backend/schema.d.ts +1 -0
- package/src/trpc/backend/schema.json +8 -0
- package/src/trpc/react/__snapshots__/generator.spec.ts.snap +1 -0
- package/src/ts/lambda-function/__snapshots__/generator.spec.ts.snap +310 -0
- package/src/ts/lambda-function/generator.js +15 -27
- package/src/ts/lambda-function/generator.js.map +1 -1
- package/src/ts/lambda-function/schema.d.ts +1 -0
- package/src/ts/lambda-function/schema.json +8 -0
- package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +590 -0
- package/src/ts/mcp-server/generator.js +4 -18
- package/src/ts/mcp-server/generator.js.map +1 -1
- package/src/ts/mcp-server/schema.d.ts +1 -0
- package/src/ts/mcp-server/schema.json +8 -0
- package/src/ts/nx-plugin/generator.js +1 -0
- package/src/ts/nx-plugin/generator.js.map +1 -1
- package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +756 -0
- package/src/ts/react-website/app/generator.js +42 -43
- package/src/ts/react-website/app/generator.js.map +1 -1
- package/src/ts/react-website/app/schema.d.ts +1 -0
- package/src/ts/react-website/app/schema.json +8 -0
- package/src/ts/react-website/cognito-auth/__snapshots__/generator.spec.ts.snap +259 -0
- package/src/ts/react-website/cognito-auth/generator.js +10 -13
- package/src/ts/react-website/cognito-auth/generator.js.map +1 -1
- package/src/ts/react-website/cognito-auth/schema.d.ts +1 -0
- package/src/ts/react-website/cognito-auth/schema.json +8 -0
- package/src/ts/react-website/runtime-config/__snapshots__/generator.spec.ts.snap +0 -40
- package/src/ts/react-website/runtime-config/generator.js +0 -2
- package/src/ts/react-website/runtime-config/generator.js.map +1 -1
- package/src/utils/agent-core-constructs/agent-core-constructs.d.ts +11 -5
- package/src/utils/agent-core-constructs/agent-core-constructs.js +51 -10
- package/src/utils/agent-core-constructs/agent-core-constructs.js.map +1 -1
- package/src/utils/agent-core-constructs/files/terraform/app/agent-core/__nameKebabCase__/__nameKebabCase__.tf.template +46 -0
- package/src/utils/agent-core-constructs/files/terraform/core/agent-core/runtime.tf.template +536 -0
- package/src/utils/api-constructs/api-constructs.d.ts +4 -4
- package/src/utils/api-constructs/api-constructs.js +45 -5
- package/src/utils/api-constructs/api-constructs.js.map +1 -1
- package/src/utils/api-constructs/files/terraform/app/apis/http/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +392 -0
- package/src/utils/api-constructs/files/terraform/app/apis/rest/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +518 -0
- package/src/utils/api-constructs/files/terraform/core/api/http/http-api/http-api.tf.template +250 -0
- package/src/utils/api-constructs/files/terraform/core/api/rest/rest-api/rest-api.tf.template +150 -0
- package/src/utils/files/terraform/src/core/runtime-config/entry/entry.tf.template +119 -0
- package/src/utils/files/terraform/src/core/runtime-config/read/read.tf.template +28 -0
- package/src/utils/files/terraform/src/metrics/metrics.tf.template +3 -2
- package/src/{py/lambda-function/files/common/constructs/src/app/lambda-functions/__constructFunctionKebabCase__.ts.template → utils/function-constructs/files/cdk/app/lambda-functions/__functionNameKebabCase__.ts.template} +5 -5
- package/src/utils/function-constructs/files/terraform/app/lambda-functions/__functionNameKebabCase__/__functionNameKebabCase__.tf.template +150 -0
- package/src/utils/function-constructs/function-constructs.d.ts +19 -0
- package/src/utils/function-constructs/function-constructs.js +57 -0
- package/src/utils/function-constructs/function-constructs.js.map +1 -0
- package/src/utils/identity-constructs/files/terraform/core/user-identity/add-callback-url/add-callback-url.tf.template +123 -0
- package/src/utils/identity-constructs/files/terraform/core/user-identity/identity/identity.tf.template +421 -0
- package/src/utils/identity-constructs/files/terraform/core/user-identity/main.tf.template +47 -0
- package/src/utils/identity-constructs/identity-constructs.d.ts +15 -0
- package/src/utils/identity-constructs/identity-constructs.js +84 -0
- package/src/utils/identity-constructs/identity-constructs.js.map +1 -0
- package/src/utils/metrics.js +1 -1
- package/src/utils/metrics.js.map +1 -1
- package/src/utils/py.d.ts +5 -0
- package/src/utils/py.js +9 -1
- package/src/utils/py.js.map +1 -1
- package/src/utils/shared-constructs-constants.d.ts +2 -0
- package/src/utils/shared-constructs-constants.js +3 -1
- package/src/utils/shared-constructs-constants.js.map +1 -1
- package/src/utils/shared-constructs.js +26 -2
- package/src/utils/shared-constructs.js.map +1 -1
- package/src/utils/versions.d.ts +3 -1
- package/src/utils/versions.js +2 -0
- package/src/utils/versions.js.map +1 -1
- package/src/utils/website-constructs/files/terraform/app/static-websites/__websiteNameKebabCase__/__websiteNameKebabCase__.tf.template +42 -0
- package/src/utils/website-constructs/files/terraform/core/static-website/static-website.tf.template +709 -0
- package/src/utils/website-constructs/website-constructs.d.ts +18 -0
- package/src/utils/website-constructs/website-constructs.js +61 -0
- package/src/utils/website-constructs/website-constructs.js.map +1 -0
- package/src/ts/lambda-function/files/common/constructs/src/app/lambda-functions/__constructFunctionNameKebabCase__.ts.template +0 -24
- /package/src/utils/agent-core-constructs/files/{app → cdk/app}/agent-core/__nameKebabCase__/Dockerfile.template +0 -0
- /package/src/utils/agent-core-constructs/files/{app → cdk/app}/agent-core/__nameKebabCase__/__nameKebabCase__.ts.template +0 -0
- /package/src/utils/agent-core-constructs/files/{core → cdk/core}/agent-core/runtime.ts.template +0 -0
- /package/src/utils/api-constructs/files/{app → cdk/app}/apis/http/__apiNameKebabCase__.ts.template +0 -0
- /package/src/utils/api-constructs/files/{app → cdk/app}/apis/rest/__apiNameKebabCase__.ts.template +0 -0
- /package/src/utils/api-constructs/files/{core → cdk/core}/api/http/http-api.ts.template +0 -0
- /package/src/utils/api-constructs/files/{core → cdk/core}/api/rest/rest-api.ts.template +0 -0
- /package/src/utils/api-constructs/files/{core → cdk/core}/api/trpc/trpc-utils.ts.template +0 -0
- /package/src/utils/api-constructs/files/{core → cdk/core}/api/utils/utils.ts.template +0 -0
- /package/src/{ts/react-website/cognito-auth/files/common/constructs/src → utils/identity-constructs/files/cdk}/core/user-identity.ts.template +0 -0
- /package/src/{ts/react-website/app/files/common/constructs/src → utils/website-constructs/files/cdk}/app/static-websites/__websiteNameKebabCase__.ts.template +0 -0
- /package/src/{ts/react-website/app/files/common/constructs/src → utils/website-constructs/files/cdk}/core/static-website.ts.template +0 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
# Core HTTP API Gateway module
|
|
2
|
+
# This module creates the API Gateway HTTP API, stage, and logging resources
|
|
3
|
+
|
|
4
|
+
terraform {
|
|
5
|
+
required_version = ">= 1.0"
|
|
6
|
+
|
|
7
|
+
required_providers {
|
|
8
|
+
aws = {
|
|
9
|
+
source = "hashicorp/aws"
|
|
10
|
+
version = "~> 6.0"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
# Core HTTP API Gateway Variables
|
|
16
|
+
|
|
17
|
+
variable "api_name" {
|
|
18
|
+
description = "Name of the HTTP API Gateway"
|
|
19
|
+
type = string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
variable "api_description" {
|
|
23
|
+
description = "Description of the HTTP API Gateway"
|
|
24
|
+
type = string
|
|
25
|
+
default = "HTTP API Gateway"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
variable "stage_name" {
|
|
29
|
+
description = "Name of the API Gateway stage"
|
|
30
|
+
type = string
|
|
31
|
+
default = "prod"
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
variable "stage_auto_deploy" {
|
|
35
|
+
description = "Whether to automatically deploy the API stage"
|
|
36
|
+
type = bool
|
|
37
|
+
default = true
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# CORS Configuration
|
|
41
|
+
|
|
42
|
+
variable "cors_allow_credentials" {
|
|
43
|
+
description = "Whether to allow credentials in CORS requests"
|
|
44
|
+
type = bool
|
|
45
|
+
default = false
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
variable "cors_allow_headers" {
|
|
49
|
+
description = "List of allowed headers for CORS"
|
|
50
|
+
type = list(string)
|
|
51
|
+
default = ["authorization", "content-type", "x-amz-content-sha256", "x-amz-date", "x-amz-security-token"]
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
variable "cors_allow_methods" {
|
|
55
|
+
description = "List of allowed HTTP methods for CORS"
|
|
56
|
+
type = list(string)
|
|
57
|
+
default = ["*"]
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
variable "cors_allow_origins" {
|
|
61
|
+
description = "List of allowed origins for CORS"
|
|
62
|
+
type = list(string)
|
|
63
|
+
default = ["*"]
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
variable "cors_expose_headers" {
|
|
67
|
+
description = "List of headers to expose in CORS responses"
|
|
68
|
+
type = list(string)
|
|
69
|
+
default = []
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
variable "cors_max_age" {
|
|
73
|
+
description = "Maximum age for CORS preflight requests in seconds"
|
|
74
|
+
type = number
|
|
75
|
+
default = 86400
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
# Tags
|
|
79
|
+
|
|
80
|
+
variable "tags" {
|
|
81
|
+
description = "Tags to apply to all resources"
|
|
82
|
+
type = map(string)
|
|
83
|
+
default = {}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
# Data sources
|
|
87
|
+
data "aws_region" "current" {}
|
|
88
|
+
data "aws_caller_identity" "current" {}
|
|
89
|
+
|
|
90
|
+
# Resources
|
|
91
|
+
|
|
92
|
+
# KMS key for CloudWatch log group encryption
|
|
93
|
+
resource "aws_kms_key" "logs_key" {
|
|
94
|
+
description = "KMS key for CloudWatch log group encryption"
|
|
95
|
+
deletion_window_in_days = 7
|
|
96
|
+
enable_key_rotation = true
|
|
97
|
+
|
|
98
|
+
policy = jsonencode({
|
|
99
|
+
Version = "2012-10-17"
|
|
100
|
+
Statement = [
|
|
101
|
+
{
|
|
102
|
+
Sid = "Enable IAM User Permissions"
|
|
103
|
+
Effect = "Allow"
|
|
104
|
+
Principal = {
|
|
105
|
+
AWS = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:root"
|
|
106
|
+
}
|
|
107
|
+
Action = "kms:*"
|
|
108
|
+
Resource = "*"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
Sid = "Allow CloudWatch Logs"
|
|
112
|
+
Effect = "Allow"
|
|
113
|
+
Principal = {
|
|
114
|
+
Service = "logs.${data.aws_region.current.name}.amazonaws.com"
|
|
115
|
+
}
|
|
116
|
+
Action = [
|
|
117
|
+
"kms:Encrypt",
|
|
118
|
+
"kms:Decrypt",
|
|
119
|
+
"kms:ReEncrypt*",
|
|
120
|
+
"kms:GenerateDataKey*",
|
|
121
|
+
"kms:DescribeKey"
|
|
122
|
+
]
|
|
123
|
+
Resource = "*"
|
|
124
|
+
Condition = {
|
|
125
|
+
ArnEquals = {
|
|
126
|
+
"kms:EncryptionContext:aws:logs:arn" = "arn:aws:logs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:log-group:/aws/apigateway/${var.api_name}"
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
]
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
tags = var.tags
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
resource "aws_kms_alias" "logs_key_alias" {
|
|
137
|
+
name = "alias/${var.api_name}-api-logs-encryption"
|
|
138
|
+
target_key_id = aws_kms_key.logs_key.key_id
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
# HTTP API Gateway
|
|
142
|
+
resource "aws_apigatewayv2_api" "http_api" {
|
|
143
|
+
name = var.api_name
|
|
144
|
+
protocol_type = "HTTP"
|
|
145
|
+
description = var.api_description
|
|
146
|
+
|
|
147
|
+
cors_configuration {
|
|
148
|
+
allow_credentials = var.cors_allow_credentials
|
|
149
|
+
allow_headers = var.cors_allow_headers
|
|
150
|
+
allow_methods = var.cors_allow_methods
|
|
151
|
+
allow_origins = var.cors_allow_origins
|
|
152
|
+
expose_headers = var.cors_expose_headers
|
|
153
|
+
max_age = var.cors_max_age
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
tags = var.tags
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
# API Gateway stage
|
|
160
|
+
resource "aws_apigatewayv2_stage" "api_stage" {
|
|
161
|
+
api_id = aws_apigatewayv2_api.http_api.id
|
|
162
|
+
name = var.stage_name
|
|
163
|
+
auto_deploy = var.stage_auto_deploy
|
|
164
|
+
|
|
165
|
+
access_log_settings {
|
|
166
|
+
destination_arn = aws_cloudwatch_log_group.api_logs.arn
|
|
167
|
+
format = jsonencode({
|
|
168
|
+
requestId = "$context.requestId"
|
|
169
|
+
ip = "$context.identity.sourceIp"
|
|
170
|
+
requestTime = "$context.requestTime"
|
|
171
|
+
httpMethod = "$context.httpMethod"
|
|
172
|
+
routeKey = "$context.routeKey"
|
|
173
|
+
status = "$context.status"
|
|
174
|
+
protocol = "$context.protocol"
|
|
175
|
+
responseLength = "$context.responseLength"
|
|
176
|
+
error = "$context.error.message"
|
|
177
|
+
integrationError = "$context.integrationErrorMessage"
|
|
178
|
+
})
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
default_route_settings {
|
|
182
|
+
throttling_burst_limit = 5000
|
|
183
|
+
throttling_rate_limit = 10000
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
tags = var.tags
|
|
187
|
+
|
|
188
|
+
depends_on = [aws_cloudwatch_log_group.api_logs]
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
# CloudWatch Log Group for API Gateway
|
|
192
|
+
resource "aws_cloudwatch_log_group" "api_logs" {
|
|
193
|
+
#checkov:skip=CKV_AWS_338:Log retention set to forever
|
|
194
|
+
#checkov:skip=CKV_AWS_66:Log retention set to forever
|
|
195
|
+
name = "/aws/apigateway/${var.api_name}"
|
|
196
|
+
kms_key_id = aws_kms_key.logs_key.arn
|
|
197
|
+
tags = var.tags
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
# Outputs
|
|
201
|
+
|
|
202
|
+
output "api_id" {
|
|
203
|
+
description = "ID of the HTTP API Gateway"
|
|
204
|
+
value = aws_apigatewayv2_api.http_api.id
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
output "api_arn" {
|
|
208
|
+
description = "ARN of the HTTP API Gateway"
|
|
209
|
+
value = aws_apigatewayv2_api.http_api.arn
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
output "api_endpoint" {
|
|
213
|
+
description = "Base URL of the HTTP API Gateway"
|
|
214
|
+
value = aws_apigatewayv2_api.http_api.api_endpoint
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
output "api_execution_arn" {
|
|
218
|
+
description = "Execution ARN of the HTTP API Gateway"
|
|
219
|
+
value = aws_apigatewayv2_api.http_api.execution_arn
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
output "stage_id" {
|
|
223
|
+
description = "ID of the API Gateway stage"
|
|
224
|
+
value = aws_apigatewayv2_stage.api_stage.id
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
output "stage_arn" {
|
|
228
|
+
description = "ARN of the API Gateway stage"
|
|
229
|
+
value = aws_apigatewayv2_stage.api_stage.arn
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
output "stage_execution_arn" {
|
|
233
|
+
description = "Execution ARN of the API Gateway stage"
|
|
234
|
+
value = aws_apigatewayv2_stage.api_stage.execution_arn
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
output "stage_invoke_url" {
|
|
238
|
+
description = "Invoke URL of the API Gateway stage"
|
|
239
|
+
value = aws_apigatewayv2_stage.api_stage.invoke_url
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
output "api_log_group_name" {
|
|
243
|
+
description = "Name of the API Gateway CloudWatch log group"
|
|
244
|
+
value = aws_cloudwatch_log_group.api_logs.name
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
output "api_log_group_arn" {
|
|
248
|
+
description = "ARN of the API Gateway CloudWatch log group"
|
|
249
|
+
value = aws_cloudwatch_log_group.api_logs.arn
|
|
250
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Core REST API Gateway module
|
|
2
|
+
# This module creates the API Gateway REST API, deployment, stage, and logging resources
|
|
3
|
+
|
|
4
|
+
terraform {
|
|
5
|
+
required_version = ">= 1.0"
|
|
6
|
+
|
|
7
|
+
required_providers {
|
|
8
|
+
aws = {
|
|
9
|
+
source = "hashicorp/aws"
|
|
10
|
+
version = "~> 6.0"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
# Core REST API Gateway Variables
|
|
16
|
+
|
|
17
|
+
variable "api_name" {
|
|
18
|
+
description = "Name of the REST API Gateway"
|
|
19
|
+
type = string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
variable "api_description" {
|
|
23
|
+
description = "Description of the REST API Gateway"
|
|
24
|
+
type = string
|
|
25
|
+
default = "REST API Gateway"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
variable "stage_name" {
|
|
29
|
+
description = "Name of the API Gateway stage"
|
|
30
|
+
type = string
|
|
31
|
+
default = "prod"
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
variable "stage_auto_deploy" {
|
|
35
|
+
description = "Whether to automatically deploy the API stage"
|
|
36
|
+
type = bool
|
|
37
|
+
default = true
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# CORS Configuration
|
|
41
|
+
|
|
42
|
+
variable "cors_allow_headers" {
|
|
43
|
+
description = "List of allowed headers for CORS"
|
|
44
|
+
type = list(string)
|
|
45
|
+
default = ["authorization", "content-type", "x-amz-content-sha256", "x-amz-date", "x-amz-security-token"]
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
variable "cors_allow_methods" {
|
|
49
|
+
description = "List of allowed HTTP methods for CORS"
|
|
50
|
+
type = list(string)
|
|
51
|
+
default = ["*"]
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
variable "cors_allow_origins" {
|
|
55
|
+
description = "List of allowed origins for CORS"
|
|
56
|
+
type = list(string)
|
|
57
|
+
default = ["*"]
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
# Tags
|
|
61
|
+
|
|
62
|
+
variable "tags" {
|
|
63
|
+
description = "Tags to apply to all resources"
|
|
64
|
+
type = map(string)
|
|
65
|
+
default = {}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
# Data sources
|
|
69
|
+
data "aws_region" "current" {}
|
|
70
|
+
data "aws_caller_identity" "current" {}
|
|
71
|
+
|
|
72
|
+
# Resources
|
|
73
|
+
|
|
74
|
+
# Note: CloudWatch logging removed due to account-level CloudWatch Logs role ARN requirement
|
|
75
|
+
|
|
76
|
+
# REST API Gateway
|
|
77
|
+
resource "aws_api_gateway_rest_api" "rest_api" {
|
|
78
|
+
name = var.api_name
|
|
79
|
+
description = var.api_description
|
|
80
|
+
|
|
81
|
+
endpoint_configuration {
|
|
82
|
+
types = ["REGIONAL"]
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
lifecycle {
|
|
86
|
+
create_before_destroy = true
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
tags = var.tags
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
# Note: Deployment and stage are created in the consuming module (e.g., foo-api.tf)
|
|
93
|
+
# after all methods and integrations are defined
|
|
94
|
+
|
|
95
|
+
# Note: CloudWatch Log Group removed due to account-level CloudWatch Logs role ARN requirement
|
|
96
|
+
|
|
97
|
+
# Gateway Response for CORS (4XX errors)
|
|
98
|
+
resource "aws_api_gateway_gateway_response" "cors_4xx" {
|
|
99
|
+
rest_api_id = aws_api_gateway_rest_api.rest_api.id
|
|
100
|
+
response_type = "DEFAULT_4XX"
|
|
101
|
+
|
|
102
|
+
response_parameters = {
|
|
103
|
+
"gatewayresponse.header.Access-Control-Allow-Origin" = "'${join(",", var.cors_allow_origins)}'"
|
|
104
|
+
"gatewayresponse.header.Access-Control-Allow-Headers" = "'${join(",", var.cors_allow_headers)}'"
|
|
105
|
+
"gatewayresponse.header.Access-Control-Allow-Methods" = "'${join(",", var.cors_allow_methods)}'"
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
# Gateway Response for CORS (5XX errors)
|
|
110
|
+
resource "aws_api_gateway_gateway_response" "cors_5xx" {
|
|
111
|
+
rest_api_id = aws_api_gateway_rest_api.rest_api.id
|
|
112
|
+
response_type = "DEFAULT_5XX"
|
|
113
|
+
|
|
114
|
+
response_parameters = {
|
|
115
|
+
"gatewayresponse.header.Access-Control-Allow-Origin" = "'${join(",", var.cors_allow_origins)}'"
|
|
116
|
+
"gatewayresponse.header.Access-Control-Allow-Headers" = "'${join(",", var.cors_allow_headers)}'"
|
|
117
|
+
"gatewayresponse.header.Access-Control-Allow-Methods" = "'${join(",", var.cors_allow_methods)}'"
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
# Outputs
|
|
122
|
+
|
|
123
|
+
output "api_id" {
|
|
124
|
+
description = "ID of the REST API Gateway"
|
|
125
|
+
value = aws_api_gateway_rest_api.rest_api.id
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
output "api_arn" {
|
|
129
|
+
description = "ARN of the REST API Gateway"
|
|
130
|
+
value = aws_api_gateway_rest_api.rest_api.arn
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
output "api_endpoint" {
|
|
134
|
+
description = "Base URL of the REST API Gateway"
|
|
135
|
+
value = "https://${aws_api_gateway_rest_api.rest_api.id}.execute-api.${data.aws_region.current.id}.amazonaws.com"
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
output "api_execution_arn" {
|
|
139
|
+
description = "Execution ARN of the REST API Gateway"
|
|
140
|
+
value = aws_api_gateway_rest_api.rest_api.execution_arn
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
output "api_root_resource_id" {
|
|
144
|
+
description = "Root resource ID of the REST API Gateway"
|
|
145
|
+
value = aws_api_gateway_rest_api.rest_api.root_resource_id
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
# Note: Stage and deployment outputs are provided by the consuming module
|
|
149
|
+
|
|
150
|
+
# Note: CloudWatch log group outputs removed due to account-level CloudWatch Logs role ARN requirement
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
terraform {
|
|
2
|
+
required_providers {
|
|
3
|
+
local = {
|
|
4
|
+
source = "hashicorp/local"
|
|
5
|
+
version = "~> 2.0"
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
# Variables
|
|
11
|
+
variable "key_path" {
|
|
12
|
+
description = "Dot-separated path for the configuration key (e.g., 'apis.FooApi', 'cognito.userPoolId')"
|
|
13
|
+
type = string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
variable "value" {
|
|
17
|
+
description = "Value to set at the key path"
|
|
18
|
+
type = any
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
locals {
|
|
22
|
+
config_file_path = "${path.module}/../../../../../../../dist/packages/common/terraform/runtime-config.json"
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
# This module writes an entry to runtime-config.json which is provided to any static websites
|
|
26
|
+
# as a way to pass deploy-time values to the UI such as API urls
|
|
27
|
+
|
|
28
|
+
data "external" "updated_config" {
|
|
29
|
+
program = ["uv", "run", "python", "-c", <<-EOT
|
|
30
|
+
import json
|
|
31
|
+
import sys
|
|
32
|
+
import os
|
|
33
|
+
import time
|
|
34
|
+
import fcntl
|
|
35
|
+
from pathlib import Path
|
|
36
|
+
|
|
37
|
+
# Read input from Terraform
|
|
38
|
+
input_data = json.load(sys.stdin)
|
|
39
|
+
config_file = input_data['config_file']
|
|
40
|
+
key_path = input_data['key_path']
|
|
41
|
+
value = json.loads(input_data['value'])
|
|
42
|
+
|
|
43
|
+
# Create lock file path
|
|
44
|
+
lock_file = config_file + '.lock'
|
|
45
|
+
|
|
46
|
+
# Ensure directory exists
|
|
47
|
+
Path(config_file).parent.mkdir(parents=True, exist_ok=True)
|
|
48
|
+
|
|
49
|
+
# Acquire exclusive lock with retry mechanism
|
|
50
|
+
max_retries = 30
|
|
51
|
+
retry_delay = 1.0
|
|
52
|
+
|
|
53
|
+
for attempt in range(max_retries):
|
|
54
|
+
try:
|
|
55
|
+
# Open lock file for exclusive access
|
|
56
|
+
with open(lock_file, 'w') as lock_fd:
|
|
57
|
+
# Try to acquire exclusive lock (non-blocking)
|
|
58
|
+
fcntl.flock(lock_fd.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
|
|
59
|
+
|
|
60
|
+
# Critical section - file operations under lock
|
|
61
|
+
try:
|
|
62
|
+
# Create empty base config if file doesn't exist
|
|
63
|
+
if not os.path.exists(config_file):
|
|
64
|
+
base_config = {}
|
|
65
|
+
with open(config_file, 'w') as f:
|
|
66
|
+
json.dump(base_config, f, indent=2)
|
|
67
|
+
|
|
68
|
+
# Read current config
|
|
69
|
+
with open(config_file, 'r') as f:
|
|
70
|
+
config = json.load(f)
|
|
71
|
+
|
|
72
|
+
# Set the nested key using dot notation
|
|
73
|
+
keys = key_path.split('.')
|
|
74
|
+
current = config
|
|
75
|
+
for key in keys[:-1]:
|
|
76
|
+
if key not in current:
|
|
77
|
+
current[key] = {}
|
|
78
|
+
current = current[key]
|
|
79
|
+
current[keys[-1]] = value
|
|
80
|
+
|
|
81
|
+
# Write updated config back to file atomically
|
|
82
|
+
temp_file = config_file + '.tmp'
|
|
83
|
+
with open(temp_file, 'w') as f:
|
|
84
|
+
json.dump(config, f, indent=2)
|
|
85
|
+
os.rename(temp_file, config_file)
|
|
86
|
+
|
|
87
|
+
# Output the updated config for Terraform
|
|
88
|
+
print(json.dumps({"updated_json": json.dumps(config)}))
|
|
89
|
+
|
|
90
|
+
# Success - break out of retry loop
|
|
91
|
+
break
|
|
92
|
+
|
|
93
|
+
finally:
|
|
94
|
+
# Lock is automatically released when file is closed
|
|
95
|
+
pass
|
|
96
|
+
|
|
97
|
+
except (IOError, OSError) as e:
|
|
98
|
+
if attempt < max_retries - 1:
|
|
99
|
+
# Wait before retrying
|
|
100
|
+
time.sleep(retry_delay)
|
|
101
|
+
continue
|
|
102
|
+
else:
|
|
103
|
+
# Final attempt failed
|
|
104
|
+
raise Exception(f"Failed to acquire lock after {max_retries} attempts: {e}")
|
|
105
|
+
|
|
106
|
+
# Clean up lock file if it exists
|
|
107
|
+
try:
|
|
108
|
+
os.remove(lock_file)
|
|
109
|
+
except OSError:
|
|
110
|
+
pass
|
|
111
|
+
EOT
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
query = {
|
|
115
|
+
config_file = local.config_file_path
|
|
116
|
+
key_path = var.key_path
|
|
117
|
+
value = jsonencode(var.value)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
terraform {
|
|
2
|
+
required_providers {
|
|
3
|
+
local = {
|
|
4
|
+
source = "hashicorp/local"
|
|
5
|
+
version = "~> 2.0"
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
locals {
|
|
11
|
+
config_file_path = "${path.module}/../../../../../../../dist/packages/common/terraform/runtime-config.json"
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
# Read the runtime config file - will fail gracefully if file doesn't exist
|
|
15
|
+
data "local_file" "runtime_config" {
|
|
16
|
+
filename = local.config_file_path
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
# Outputs
|
|
20
|
+
output "config" {
|
|
21
|
+
description = "Runtime configuration object"
|
|
22
|
+
value = jsondecode(data.local_file.runtime_config.content)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
output "config_json" {
|
|
26
|
+
description = "Runtime configuration as JSON string"
|
|
27
|
+
value = data.local_file.runtime_config.content
|
|
28
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# CloudFormation stack for metrics tracking
|
|
2
2
|
resource "aws_cloudformation_stack" "metrics" {
|
|
3
|
+
#checkov:skip=CKV_AWS_124:Metrics stack does not require SNS notifications
|
|
3
4
|
name = "nx-plugin-metrics"
|
|
4
|
-
|
|
5
|
+
|
|
5
6
|
template_body = jsonencode({
|
|
6
7
|
AWSTemplateFormatVersion = "2010-09-09"
|
|
7
8
|
Description = "<%= metricId %> (version:<%= version %>) (tag:<%= tags %>)"
|
|
@@ -12,7 +13,7 @@ resource "aws_cloudformation_stack" "metrics" {
|
|
|
12
13
|
}
|
|
13
14
|
}
|
|
14
15
|
})
|
|
15
|
-
|
|
16
|
+
|
|
16
17
|
tags = {
|
|
17
18
|
Purpose = "nx-plugin-metrics"
|
|
18
19
|
}
|
|
@@ -3,15 +3,15 @@ import * as url from 'url';
|
|
|
3
3
|
import { Code, Function, Runtime, Tracing } from 'aws-cdk-lib/aws-lambda';
|
|
4
4
|
import { Duration } from 'aws-cdk-lib';
|
|
5
5
|
|
|
6
|
-
export class <%=
|
|
6
|
+
export class <%= functionNameClassName %> extends Function {
|
|
7
7
|
constructor(scope: Construct, id: string) {
|
|
8
8
|
super(scope, id, {
|
|
9
9
|
timeout: Duration.seconds(30),
|
|
10
|
-
runtime:
|
|
11
|
-
handler: '<%=
|
|
10
|
+
runtime: <%= runtime %>,
|
|
11
|
+
handler: '<%= handler %>',
|
|
12
12
|
code: Code.fromAsset(url.fileURLToPath(
|
|
13
13
|
new URL(
|
|
14
|
-
'
|
|
14
|
+
'../../../../../../<%- bundlePathFromRoot %>',
|
|
15
15
|
import.meta.url
|
|
16
16
|
)
|
|
17
17
|
)),
|
|
@@ -21,4 +21,4 @@ export class <%= constructFunctionClassName %> extends Function {
|
|
|
21
21
|
},
|
|
22
22
|
});
|
|
23
23
|
}
|
|
24
|
-
}
|
|
24
|
+
}
|