@aws/nx-plugin 1.0.0-rc.4 → 1.0.0-rc.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE-THIRD-PARTY +5449 -4980
- package/README.md +7 -7
- package/executors.json +9 -0
- package/generators.json +101 -2
- package/package.json +35 -17
- package/src/agentcore-gateway/attach-upstream.d.ts +33 -0
- package/src/agentcore-gateway/attach-upstream.js +38 -0
- package/src/agentcore-gateway/attach-upstream.js.map +1 -0
- package/src/agentcore-gateway/files/cedar/policies/README.md +52 -0
- package/src/agentcore-gateway/files/cedar/policies/permit-all.cedar +11 -0
- package/src/agentcore-gateway/files/project/local-dev.ts.template +134 -0
- package/src/agentcore-gateway/gateway-connection/generator.d.ts +21 -0
- package/src/agentcore-gateway/gateway-connection/generator.js +101 -0
- package/src/agentcore-gateway/gateway-connection/generator.js.map +1 -0
- package/src/agentcore-gateway/gateway-connection/schema.d.js +6 -0
- package/src/agentcore-gateway/gateway-connection/schema.d.js.map +1 -0
- package/src/agentcore-gateway/gateway-connection/schema.d.ts +13 -0
- package/src/agentcore-gateway/gateway-connection/schema.json +31 -0
- package/src/agentcore-gateway/generator.d.ts +25 -0
- package/src/agentcore-gateway/generator.js +149 -0
- package/src/agentcore-gateway/generator.js.map +1 -0
- package/src/agentcore-gateway/mcp-connection/generator.d.ts +19 -0
- package/src/agentcore-gateway/mcp-connection/generator.js +59 -0
- package/src/agentcore-gateway/mcp-connection/generator.js.map +1 -0
- package/src/agentcore-gateway/mcp-connection/schema.d.js +6 -0
- package/src/agentcore-gateway/mcp-connection/schema.d.js.map +1 -0
- package/src/agentcore-gateway/mcp-connection/schema.d.ts +13 -0
- package/src/agentcore-gateway/mcp-connection/schema.json +31 -0
- package/src/agentcore-gateway/schema.d.js +6 -0
- package/src/agentcore-gateway/schema.d.js.map +1 -0
- package/src/agentcore-gateway/schema.d.ts +17 -0
- package/src/agentcore-gateway/schema.json +70 -0
- package/src/bin/aws-nx-mcp.js +14 -0
- package/src/bin/aws-nx-mcp.js.map +1 -0
- package/src/connection/{agent-serve-local.d.ts → agent-local-dev.d.ts} +7 -7
- package/src/connection/agent-local-dev.js +42 -0
- package/src/connection/agent-local-dev.js.map +1 -0
- package/src/connection/agent-runtime-config.d.ts +1 -1
- package/src/connection/agent-runtime-config.js +9 -14
- package/src/connection/agent-runtime-config.js.map +1 -1
- package/src/connection/generator.d.ts +7 -14
- package/src/connection/generator.js +167 -194
- package/src/connection/generator.js.map +1 -1
- package/src/connection/local-dev.d.ts +15 -0
- package/src/connection/local-dev.js +37 -0
- package/src/connection/local-dev.js.map +1 -0
- package/src/connection/schema.d.js +6 -0
- package/src/connection/schema.d.js.map +1 -0
- package/src/connection/schema.d.ts +1 -0
- package/src/connection/schema.json +5 -0
- package/src/connection/supported-connections.d.ts +107 -0
- package/src/connection/supported-connections.js +151 -0
- package/src/connection/supported-connections.js.map +1 -0
- package/src/index.js +2 -5
- package/src/index.js.map +1 -1
- package/src/infra/app/__snapshots__/generator.spec.ts.snap +97 -85
- package/src/infra/app/files/app/src/main.ts.template +1 -1
- package/src/infra/app/files/app/src/stages/application-stage.ts.template +1 -1
- package/src/infra/app/generator.d.ts +3 -3
- package/src/infra/app/generator.js +142 -122
- package/src/infra/app/generator.js.map +1 -1
- package/src/infra/app/schema.d.js +6 -0
- package/src/infra/app/schema.d.js.map +1 -0
- package/src/infra/app/schema.d.ts +1 -1
- package/src/infra/app/schema.json +5 -0
- package/src/init/generator.d.ts +18 -0
- package/src/init/generator.js +35 -0
- package/src/init/generator.js.map +1 -0
- package/src/init/schema.d.js +6 -0
- package/src/init/schema.d.js.map +1 -0
- package/src/init/schema.d.ts +16 -0
- package/src/init/schema.json +35 -0
- package/src/license/__snapshots__/config.spec.ts.snap +23 -0
- package/src/license/config-types.d.ts +18 -1
- package/src/license/config-types.js +8 -2
- package/src/license/config-types.js.map +1 -1
- package/src/license/config.d.ts +65 -7
- package/src/license/config.js +442 -109
- package/src/license/config.js.map +1 -1
- package/src/license/dependency-check/check.d.ts +16 -0
- package/src/license/dependency-check/check.js +116 -0
- package/src/license/dependency-check/check.js.map +1 -0
- package/src/license/dependency-check/collectors/collector.d.ts +21 -0
- package/src/license/dependency-check/collectors/collector.js +46 -0
- package/src/license/dependency-check/collectors/collector.js.map +1 -0
- package/src/license/dependency-check/collectors/npm-collector.d.ts +10 -0
- package/src/license/dependency-check/collectors/npm-collector.js +68 -0
- package/src/license/dependency-check/collectors/npm-collector.js.map +1 -0
- package/src/license/dependency-check/collectors/python-collector.d.ts +23 -0
- package/src/license/dependency-check/collectors/python-collector.js +114 -0
- package/src/license/dependency-check/collectors/python-collector.js.map +1 -0
- package/src/license/dependency-check/evaluator.d.ts +9 -0
- package/src/license/dependency-check/evaluator.js +94 -0
- package/src/license/dependency-check/evaluator.js.map +1 -0
- package/src/license/dependency-check/executor-schema.json +6 -0
- package/src/license/dependency-check/executor.d.ts +9 -0
- package/src/license/dependency-check/executor.js +51 -0
- package/src/license/dependency-check/executor.js.map +1 -0
- package/src/license/dependency-check/pre-approved.d.ts +6 -0
- package/src/license/dependency-check/pre-approved.js +1893 -0
- package/src/license/dependency-check/pre-approved.js.map +1 -0
- package/src/license/dependency-check/types.d.ts +45 -0
- package/src/license/dependency-check/types.js +6 -0
- package/src/license/dependency-check/types.js.map +1 -0
- package/src/license/generator.d.ts +3 -3
- package/src/license/generator.js +126 -30
- package/src/license/generator.js.map +1 -1
- package/src/license/index.d.ts +8 -0
- package/src/license/index.js +7 -0
- package/src/license/index.js.map +1 -0
- package/src/license/known-exceptions.d.ts +7 -0
- package/src/license/known-exceptions.js +39 -0
- package/src/license/known-exceptions.js.map +1 -0
- package/src/license/schema.d.js +6 -0
- package/src/license/schema.d.js.map +1 -0
- package/src/license/schema.d.ts +7 -0
- package/src/license/schema.json +11 -0
- package/src/license/sync/generator.d.ts +2 -2
- package/src/license/sync/generator.js +100 -125
- package/src/license/sync/generator.js.map +1 -1
- package/src/license/sync/project-file-sync.d.ts +3 -3
- package/src/license/sync/project-file-sync.js +28 -35
- package/src/license/sync/project-file-sync.js.map +1 -1
- package/src/mcp-server/generator-info.d.ts +5 -1
- package/src/mcp-server/generator-info.js +149 -165
- package/src/mcp-server/generator-info.js.map +1 -1
- package/src/mcp-server/guide-pipeline.d.ts +1 -1
- package/src/mcp-server/guide-pipeline.js +199 -206
- package/src/mcp-server/guide-pipeline.js.map +1 -1
- package/src/mcp-server/guide-render.js +10 -25
- package/src/mcp-server/guide-render.js.map +1 -1
- package/src/mcp-server/index.js +6 -10
- package/src/mcp-server/index.js.map +1 -1
- package/src/mcp-server/mdx-ast.js +42 -56
- package/src/mcp-server/mdx-ast.js.map +1 -1
- package/src/mcp-server/option-filter.js +33 -47
- package/src/mcp-server/option-filter.js.map +1 -1
- package/src/mcp-server/schema-registry.d.ts +9 -3
- package/src/mcp-server/schema-registry.js +41 -38
- package/src/mcp-server/schema-registry.js.map +1 -1
- package/src/mcp-server/schema.js +9 -7
- package/src/mcp-server/schema.js.map +1 -1
- package/src/mcp-server/server.js +22 -24
- package/src/mcp-server/server.js.map +1 -1
- package/src/mcp-server/tools/add-to-existing-project.d.ts +12 -0
- package/src/mcp-server/tools/add-to-existing-project.js +36 -0
- package/src/mcp-server/tools/add-to-existing-project.js.map +1 -0
- package/src/mcp-server/tools/create-workspace-command.d.ts +1 -1
- package/src/mcp-server/tools/create-workspace-command.js +23 -24
- package/src/mcp-server/tools/create-workspace-command.js.map +1 -1
- package/src/mcp-server/tools/general-guidance.d.ts +3 -3
- package/src/mcp-server/tools/general-guidance.js +47 -25
- package/src/mcp-server/tools/general-guidance.js.map +1 -1
- package/src/mcp-server/tools/generator-guide.d.ts +2 -2
- package/src/mcp-server/tools/generator-guide.js +29 -37
- package/src/mcp-server/tools/generator-guide.js.map +1 -1
- package/src/mcp-server/tools/list-generators.d.ts +2 -2
- package/src/mcp-server/tools/list-generators.js +19 -25
- package/src/mcp-server/tools/list-generators.js.map +1 -1
- package/src/open-api/ts-client/__snapshots__/generator.additional-properties.spec.ts.snap +147 -33
- package/src/open-api/ts-client/__snapshots__/generator.arrays.spec.ts.snap +308 -75
- package/src/open-api/ts-client/__snapshots__/generator.complex-types.spec.ts.snap +298 -74
- package/src/open-api/ts-client/__snapshots__/generator.composite-types.spec.ts.snap +748 -103
- package/src/open-api/ts-client/__snapshots__/generator.content-type.spec.ts.snap +230 -37
- package/src/open-api/ts-client/__snapshots__/generator.duplicate-types.spec.ts.snap +249 -52
- package/src/open-api/ts-client/__snapshots__/generator.edge-cases.spec.ts.snap +5535 -0
- package/src/open-api/ts-client/__snapshots__/generator.fast-api-gaps.spec.ts.snap +736 -0
- package/src/open-api/ts-client/__snapshots__/generator.fast-api.spec.ts.snap +305 -71
- package/src/open-api/ts-client/__snapshots__/generator.multipart.spec.ts.snap +298 -0
- package/src/open-api/ts-client/__snapshots__/generator.primitive-types.spec.ts.snap +353 -82
- package/src/open-api/ts-client/__snapshots__/generator.request.spec.ts.snap +176 -55
- package/src/open-api/ts-client/__snapshots__/generator.reserved-keywords.spec.ts.snap +101 -25
- package/src/open-api/ts-client/__snapshots__/generator.response.spec.ts.snap +147 -33
- package/src/open-api/ts-client/__snapshots__/generator.spec-compliance.spec.ts.snap +1883 -0
- package/src/open-api/ts-client/__snapshots__/generator.streaming.spec.ts.snap +392 -88
- package/src/open-api/ts-client/__snapshots__/generator.tags.spec.ts.snap +200 -48
- package/src/open-api/ts-client/files/client.gen.ts.template +358 -24
- package/src/open-api/ts-client/files/types.gen.ts.template +6 -4
- package/src/open-api/ts-client/generator.d.ts +3 -3
- package/src/open-api/ts-client/generator.js +41 -26
- package/src/open-api/ts-client/generator.js.map +1 -1
- package/src/open-api/ts-client/schema.d.js +6 -0
- package/src/open-api/ts-client/schema.d.js.map +1 -0
- package/src/open-api/ts-hooks/files/options-proxy.gen.ts.template +7 -2
- package/src/open-api/ts-hooks/generator.d.ts +3 -3
- package/src/open-api/ts-hooks/generator.js +17 -21
- package/src/open-api/ts-hooks/generator.js.map +1 -1
- package/src/open-api/ts-hooks/generator.spec.tsx +84 -14
- package/src/open-api/ts-hooks/schema.d.js +6 -0
- package/src/open-api/ts-hooks/schema.d.js.map +1 -0
- package/src/open-api/ts-metadata/generator.d.ts +3 -3
- package/src/open-api/ts-metadata/generator.js +12 -20
- package/src/open-api/ts-metadata/generator.js.map +1 -1
- package/src/open-api/ts-metadata/schema.d.js +6 -0
- package/src/open-api/ts-metadata/schema.d.js.map +1 -0
- package/src/open-api/utils/codegen-data/languages.d.ts +3 -5
- package/src/open-api/utils/codegen-data/languages.js +59 -66
- package/src/open-api/utils/codegen-data/languages.js.map +1 -1
- package/src/open-api/utils/codegen-data/types.d.ts +255 -10
- package/src/open-api/utils/codegen-data/types.js +54 -30
- package/src/open-api/utils/codegen-data/types.js.map +1 -1
- package/src/open-api/utils/codegen-data.d.ts +8 -4
- package/src/open-api/utils/codegen-data.js +494 -674
- package/src/open-api/utils/codegen-data.js.map +1 -1
- package/src/open-api/utils/normalise.d.ts +5 -1
- package/src/open-api/utils/normalise.js +437 -246
- package/src/open-api/utils/normalise.js.map +1 -1
- package/src/open-api/utils/parse.d.ts +2 -2
- package/src/open-api/utils/parse.js +11 -13
- package/src/open-api/utils/parse.js.map +1 -1
- package/src/open-api/utils/parser.d.ts +55 -0
- package/src/open-api/utils/parser.js +787 -0
- package/src/open-api/utils/parser.js.map +1 -0
- package/src/open-api/utils/refs.d.ts +1 -1
- package/src/open-api/utils/refs.js +12 -22
- package/src/open-api/utils/refs.js.map +1 -1
- package/src/open-api/utils/types.d.ts +18 -0
- package/src/open-api/utils/types.js +5 -2
- package/src/open-api/utils/types.js.map +1 -1
- package/src/preset/__snapshots__/generator.spec.ts.snap +109 -28
- package/src/preset/generator.d.ts +4 -4
- package/src/preset/generator.js +64 -147
- package/src/preset/generator.js.map +1 -1
- package/src/preset/schema.d.js +6 -0
- package/src/preset/schema.d.js.map +1 -0
- package/src/preset/schema.d.ts +5 -2
- package/src/preset/schema.json +11 -5
- package/src/py/agent/__snapshots__/generator.constructs.spec.ts.snap +320 -0
- package/src/py/agent/__snapshots__/generator.frameworks.spec.ts.snap +734 -0
- package/src/py/agent/__snapshots__/{generator.spec.ts.snap → generator.protocols.spec.ts.snap} +182 -314
- package/src/py/agent/a2a-connection/__snapshots__/generator.spec.ts.snap +189 -0
- package/src/py/agent/a2a-connection/files/agent-connection/app/__targetAgentSnakeCase___client_strands.py.template +30 -0
- package/src/py/agent/a2a-connection/files/langchain/agent-connection/app/__targetAgentSnakeCase___client_langchain.py.template +28 -0
- package/src/py/agent/a2a-connection/generator.d.ts +3 -3
- package/src/py/agent/a2a-connection/generator.js +113 -85
- package/src/py/agent/a2a-connection/generator.js.map +1 -1
- package/src/py/agent/a2a-connection/schema.d.js +8 -0
- package/src/py/agent/a2a-connection/schema.d.js.map +1 -0
- package/src/py/agent/a2a-connection/schema.d.ts +1 -0
- package/src/py/agent/a2a-connection/schema.json +5 -0
- package/src/py/agent/files/a2a-langchain/main.py.template +89 -0
- package/src/py/agent/files/ag-ui-langchain/main.py.template +83 -0
- package/src/py/agent/files/common/agent.py.template +2 -0
- package/src/py/agent/files/common-langchain/agent.py.template +30 -0
- package/src/py/agent/files/deploy/Dockerfile.template +1 -1
- package/src/py/agent/files/http/init.py.template +7 -25
- package/src/py/agent/files/http/main.py.template +3 -4
- package/src/py/agent/files/http-langchain/main.py.template +84 -0
- package/src/py/agent/gateway-connection/__snapshots__/generator.spec.ts.snap +184 -0
- package/src/py/agent/gateway-connection/files/agent-connection/app/__gatewaySnakeCase___client_strands.py.template +35 -0
- package/src/py/agent/gateway-connection/files/langchain/agent-connection/app/__gatewaySnakeCase___client_langchain.py.template +34 -0
- package/src/py/agent/gateway-connection/generator.d.ts +10 -0
- package/src/py/agent/gateway-connection/generator.js +119 -0
- package/src/py/agent/gateway-connection/generator.js.map +1 -0
- package/src/py/agent/gateway-connection/schema.d.js +6 -0
- package/src/py/agent/gateway-connection/schema.d.js.map +1 -0
- package/src/py/agent/gateway-connection/schema.d.ts +13 -0
- package/src/py/agent/gateway-connection/schema.json +31 -0
- package/src/py/agent/generator.d.ts +3 -3
- package/src/py/agent/generator.js +290 -179
- package/src/py/agent/generator.js.map +1 -1
- package/src/py/agent/mcp-connection/__snapshots__/generator.spec.ts.snap +153 -89
- package/src/py/agent/mcp-connection/files/agent-connection/app/__mcpServerSnakeCase___client_strands.py.template +30 -0
- package/src/py/agent/mcp-connection/files/langchain/agent-connection/app/__mcpServerSnakeCase___client_langchain.py.template +30 -0
- package/src/py/agent/mcp-connection/generator.d.ts +3 -3
- package/src/py/agent/mcp-connection/generator.js +65 -126
- package/src/py/agent/mcp-connection/generator.js.map +1 -1
- package/src/py/agent/mcp-connection/schema.d.js +8 -0
- package/src/py/agent/mcp-connection/schema.d.js.map +1 -0
- package/src/py/agent/mcp-connection/schema.d.ts +1 -0
- package/src/py/agent/mcp-connection/schema.json +5 -0
- package/src/py/agent/react-connection/__snapshots__/generator.spec.ts.snap +11 -19
- package/src/py/agent/react-connection/generator.d.ts +4 -4
- package/src/py/agent/react-connection/generator.js +55 -59
- package/src/py/agent/react-connection/generator.js.map +1 -1
- package/src/py/agent/react-connection/{serve-local.d.ts → local-dev.d.ts} +6 -6
- package/src/py/agent/react-connection/local-dev.js +36 -0
- package/src/py/agent/react-connection/local-dev.js.map +1 -0
- package/src/py/agent/react-connection/schema.d.js +8 -0
- package/src/py/agent/react-connection/schema.d.js.map +1 -0
- package/src/py/agent/react-connection/schema.d.ts +1 -0
- package/src/py/agent/react-connection/schema.json +5 -0
- package/src/py/agent/schema.d.js +6 -0
- package/src/py/agent/schema.d.js.map +1 -0
- package/src/py/agent/schema.d.ts +2 -1
- package/src/py/agent/schema.json +6 -1
- package/src/py/api/generator.d.ts +3 -3
- package/src/py/api/generator.js +12 -11
- package/src/py/api/generator.js.map +1 -1
- package/src/py/api/schema.d.js +6 -0
- package/src/py/api/schema.d.js.map +1 -0
- package/src/py/api/schema.d.ts +1 -0
- package/src/py/api/schema.json +5 -0
- package/src/py/dynamodb/__snapshots__/generator.spec.ts.snap +1526 -0
- package/src/py/dynamodb/agent-connection/__snapshots__/generator.spec.ts.snap +45 -0
- package/src/py/dynamodb/agent-connection/generator.d.ts +10 -0
- package/src/py/dynamodb/agent-connection/generator.js +39 -0
- package/src/py/dynamodb/agent-connection/generator.js.map +1 -0
- package/src/py/dynamodb/agent-connection/schema.d.js +8 -0
- package/src/py/dynamodb/agent-connection/schema.d.js.map +1 -0
- package/src/py/dynamodb/agent-connection/schema.d.ts +15 -0
- package/src/py/dynamodb/agent-connection/schema.json +27 -0
- package/src/py/dynamodb/fast-api-connection/__snapshots__/generator.spec.ts.snap +23 -0
- package/src/py/dynamodb/fast-api-connection/generator.d.ts +10 -0
- package/src/py/dynamodb/fast-api-connection/generator.js +37 -0
- package/src/py/dynamodb/fast-api-connection/generator.js.map +1 -0
- package/src/py/dynamodb/fast-api-connection/schema.d.js +8 -0
- package/src/py/dynamodb/fast-api-connection/schema.d.js.map +1 -0
- package/src/py/dynamodb/fast-api-connection/schema.d.ts +13 -0
- package/src/py/dynamodb/fast-api-connection/schema.json +23 -0
- package/src/py/dynamodb/files/__name__/__init__.py.template +6 -0
- package/src/py/dynamodb/files/__name__/client.py.template +39 -0
- package/src/py/dynamodb/files/__name__/entities/__init__.py.template +4 -0
- package/src/py/dynamodb/files/__name__/entities/base.py.template +63 -0
- package/src/py/dynamodb/files/__name__/entities/example.py.template +64 -0
- package/src/py/dynamodb/files/config.json.template +24 -0
- package/src/py/dynamodb/generator.d.ts +10 -0
- package/src/py/dynamodb/generator.js +110 -0
- package/src/py/dynamodb/generator.js.map +1 -0
- package/src/py/dynamodb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +45 -0
- package/src/py/dynamodb/mcp-server-connection/generator.d.ts +10 -0
- package/src/py/dynamodb/mcp-server-connection/generator.js +39 -0
- package/src/py/dynamodb/mcp-server-connection/generator.js.map +1 -0
- package/src/py/dynamodb/mcp-server-connection/schema.d.js +8 -0
- package/src/py/dynamodb/mcp-server-connection/schema.d.js.map +1 -0
- package/src/py/dynamodb/mcp-server-connection/schema.d.ts +15 -0
- package/src/py/dynamodb/mcp-server-connection/schema.json +27 -0
- package/src/py/dynamodb/schema.d.js +6 -0
- package/src/py/dynamodb/schema.d.js.map +1 -0
- package/src/py/dynamodb/schema.d.ts +16 -0
- package/src/py/dynamodb/schema.json +75 -0
- package/src/py/fast-api/__snapshots__/generator.spec.ts.snap +212 -4678
- package/src/py/fast-api/__snapshots__/generator.terraform.spec.ts.snap +5409 -0
- package/src/py/fast-api/files/app/__name__/init.py.template +5 -22
- package/src/py/fast-api/files/app/__name__/main.py.template +4 -1
- package/src/py/fast-api/generator.d.ts +3 -3
- package/src/py/fast-api/generator.js +90 -87
- package/src/py/fast-api/generator.js.map +1 -1
- package/src/py/fast-api/react/__snapshots__/generator.spec.ts.snap +4 -3
- package/src/py/fast-api/react/generator.d.ts +4 -4
- package/src/py/fast-api/react/generator.js +25 -25
- package/src/py/fast-api/react/generator.js.map +1 -1
- package/src/py/fast-api/react/open-api.d.ts +1 -1
- package/src/py/fast-api/react/open-api.js +31 -29
- package/src/py/fast-api/react/open-api.js.map +1 -1
- package/src/py/fast-api/react/schema.d.js +6 -0
- package/src/py/fast-api/react/schema.d.js.map +1 -0
- package/src/py/fast-api/react/schema.d.ts +1 -0
- package/src/py/fast-api/react/schema.json +5 -0
- package/src/py/fast-api/schema.d.js +6 -0
- package/src/py/fast-api/schema.d.js.map +1 -0
- package/src/py/fast-api/schema.d.ts +1 -0
- package/src/py/fast-api/schema.json +5 -0
- package/src/py/lambda-function/__snapshots__/generator.spec.ts.snap +4 -4
- package/src/py/lambda-function/generator.d.ts +3 -3
- package/src/py/lambda-function/generator.js +60 -59
- package/src/py/lambda-function/generator.js.map +1 -1
- package/src/py/lambda-function/schema.d.js +6 -0
- package/src/py/lambda-function/schema.d.js.map +1 -0
- package/src/py/lambda-function/schema.d.ts +1 -0
- package/src/py/lambda-function/schema.json +5 -0
- package/src/py/mcp-server/__snapshots__/generator.spec.ts.snap +208 -19
- package/src/py/mcp-server/files/deploy/Dockerfile.template +1 -1
- package/src/py/mcp-server/generator.d.ts +3 -3
- package/src/py/mcp-server/generator.js +162 -124
- package/src/py/mcp-server/generator.js.map +1 -1
- package/src/py/mcp-server/schema.d.js +6 -0
- package/src/py/mcp-server/schema.d.js.map +1 -0
- package/src/py/mcp-server/schema.d.ts +1 -0
- package/src/py/mcp-server/schema.json +5 -0
- package/src/py/project/generator.d.ts +17 -4
- package/src/py/project/generator.js +205 -127
- package/src/py/project/generator.js.map +1 -1
- package/src/py/project/schema.d.js +6 -0
- package/src/py/project/schema.d.js.map +1 -0
- package/src/py/project/schema.d.ts +1 -0
- package/src/py/project/schema.json +5 -0
- package/src/py/rdb/__snapshots__/generator.spec.ts.snap +2038 -0
- package/src/py/rdb/agent-connection/__snapshots__/generator.spec.ts.snap +104 -0
- package/src/py/rdb/agent-connection/generator.d.ts +10 -0
- package/src/py/rdb/agent-connection/generator.js +46 -0
- package/src/py/rdb/agent-connection/generator.js.map +1 -0
- package/src/py/rdb/agent-connection/schema.d.js +8 -0
- package/src/py/rdb/agent-connection/schema.d.js.map +1 -0
- package/src/py/rdb/agent-connection/schema.d.ts +15 -0
- package/src/py/rdb/agent-connection/schema.json +27 -0
- package/src/py/rdb/fast-api-connection/__snapshots__/generator.spec.ts.snap +44 -0
- package/src/py/rdb/fast-api-connection/files/__apiModuleName__/dependencies/__rdbNameSnake__.py.template +14 -0
- package/src/py/rdb/fast-api-connection/generator.d.ts +10 -0
- package/src/py/rdb/fast-api-connection/generator.js +54 -0
- package/src/py/rdb/fast-api-connection/generator.js.map +1 -0
- package/src/py/rdb/fast-api-connection/schema.d.js +8 -0
- package/src/py/rdb/fast-api-connection/schema.d.js.map +1 -0
- package/src/py/rdb/fast-api-connection/schema.d.ts +13 -0
- package/src/py/rdb/fast-api-connection/schema.json +23 -0
- package/src/py/rdb/files/Dockerfile.create-db-user.template +10 -0
- package/src/py/rdb/files/Dockerfile.migration.template +10 -0
- package/src/py/rdb/files/__name__/__init__.py.template +3 -0
- package/src/py/rdb/files/__name__/connection.py.template +55 -0
- package/src/py/rdb/files/__name__/create_db_user_handler.py.template +97 -0
- package/src/py/rdb/files/__name__/migration_handler.py.template +36 -0
- package/src/py/rdb/files/__name__/models/__init__.py.template +3 -0
- package/src/py/rdb/files/__name__/models/example.py.template +8 -0
- package/src/py/rdb/files/__name__/utils.py.template +104 -0
- package/src/py/rdb/files/alembic.ini.template +38 -0
- package/src/py/rdb/files/config.json.template +14 -0
- package/src/py/rdb/files/migrations/env.py.template +80 -0
- package/src/py/rdb/files/migrations/script.py.mako.template +28 -0
- package/src/py/rdb/generator.d.ts +6 -0
- package/src/py/rdb/generator.js +274 -0
- package/src/py/rdb/generator.js.map +1 -0
- package/src/py/rdb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +101 -0
- package/src/py/rdb/mcp-server-connection/generator.d.ts +10 -0
- package/src/py/rdb/mcp-server-connection/generator.js +46 -0
- package/src/py/rdb/mcp-server-connection/generator.js.map +1 -0
- package/src/py/rdb/mcp-server-connection/schema.d.js +8 -0
- package/src/py/rdb/mcp-server-connection/schema.d.js.map +1 -0
- package/src/py/rdb/mcp-server-connection/schema.d.ts +15 -0
- package/src/py/rdb/mcp-server-connection/schema.json +27 -0
- package/src/py/rdb/schema.d.js +6 -0
- package/src/py/rdb/schema.d.js.map +1 -0
- package/src/py/rdb/schema.d.ts +16 -0
- package/src/py/rdb/schema.json +77 -0
- package/src/py/rdb/utils.d.ts +6 -0
- package/src/py/rdb/utils.js +16 -0
- package/src/py/rdb/utils.js.map +1 -0
- package/src/sdk/agentcore-gateway.d.ts +6 -0
- package/src/sdk/agentcore-gateway.js +7 -0
- package/src/sdk/agentcore-gateway.js.map +1 -0
- package/src/sdk/connection.d.ts +6 -0
- package/src/sdk/connection.js +6 -0
- package/src/sdk/connection.js.map +1 -0
- package/src/sdk/license.d.ts +8 -0
- package/src/sdk/license.js +7 -0
- package/src/sdk/license.js.map +1 -0
- package/src/sdk/open-api.d.ts +10 -0
- package/src/sdk/open-api.js +8 -0
- package/src/sdk/open-api.js.map +1 -0
- package/src/sdk/py.d.ts +16 -0
- package/src/sdk/py.js +11 -0
- package/src/sdk/py.js.map +1 -0
- package/src/sdk/terraform.d.ts +6 -0
- package/src/sdk/terraform.js +7 -0
- package/src/sdk/terraform.js.map +1 -0
- package/src/sdk/ts.d.ts +33 -0
- package/src/sdk/ts.js +35 -0
- package/src/sdk/ts.js.map +1 -0
- package/{sdk → src/sdk}/utils/ast.d.ts +1 -2
- package/src/sdk/utils/ast.js +6 -0
- package/src/sdk/utils/ast.js.map +1 -0
- package/{sdk → src/sdk}/utils/format.d.ts +1 -1
- package/src/sdk/utils/format.js +6 -0
- package/src/sdk/utils/format.js.map +1 -0
- package/{sdk → src/sdk}/utils/test.d.ts +1 -1
- package/src/sdk/utils/test.js +6 -0
- package/src/sdk/utils/test.js.map +1 -0
- package/src/smithy/project/__snapshots__/generator.spec.ts.snap +19 -24
- package/src/smithy/project/files/build.Dockerfile.template +1 -4
- package/src/smithy/project/files/src/operations/echo.smithy.template +1 -0
- package/src/smithy/project/generator.d.ts +3 -3
- package/src/smithy/project/generator.js +64 -57
- package/src/smithy/project/generator.js.map +1 -1
- package/src/smithy/project/schema.d.js +6 -0
- package/src/smithy/project/schema.d.js.map +1 -0
- package/src/smithy/project/schema.d.ts +1 -0
- package/src/smithy/project/schema.json +5 -0
- package/src/smithy/react-connection/__snapshots__/generator.spec.ts.snap +1 -1
- package/src/smithy/react-connection/generator.d.ts +3 -3
- package/src/smithy/react-connection/generator.js +39 -47
- package/src/smithy/react-connection/generator.js.map +1 -1
- package/src/smithy/react-connection/schema.d.js +6 -0
- package/src/smithy/react-connection/schema.d.js.map +1 -0
- package/src/smithy/react-connection/schema.d.ts +1 -0
- package/src/smithy/react-connection/schema.json +5 -0
- package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +824 -120
- package/src/smithy/ts/api/files/handler.ts.template +2 -2
- package/src/smithy/ts/api/files/local-server.ts.template +2 -2
- package/src/smithy/ts/api/files/operations/echo.ts.template +2 -2
- package/src/smithy/ts/api/files/service.ts.template +3 -3
- package/src/smithy/ts/api/generator.d.ts +3 -3
- package/src/smithy/ts/api/generator.js +128 -105
- package/src/smithy/ts/api/generator.js.map +1 -1
- package/src/smithy/ts/api/schema.d.js +6 -0
- package/src/smithy/ts/api/schema.d.js.map +1 -0
- package/src/smithy/ts/api/schema.d.ts +1 -0
- package/src/smithy/ts/api/schema.json +5 -0
- package/src/terraform/project/files/application/src/main.tf.template +6 -1
- package/src/terraform/project/files/application/src/providers.tf.template +1 -1
- package/src/terraform/project/generator.d.ts +3 -3
- package/src/terraform/project/generator.js +156 -104
- package/src/terraform/project/generator.js.map +1 -1
- package/src/terraform/project/schema.d.js +9 -0
- package/src/terraform/project/schema.d.js.map +1 -0
- package/src/terraform/project/schema.d.ts +1 -0
- package/src/terraform/project/schema.json +5 -0
- package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +1099 -134
- package/src/trpc/backend/files/src/client/index.ts.template +1 -1
- package/src/trpc/backend/files/src/handler.ts.template +1 -1
- package/src/trpc/backend/files/src/index.ts.template +5 -5
- package/src/trpc/backend/files/src/init.ts.template +1 -1
- package/src/trpc/backend/files/src/local-server.ts.template +1 -1
- package/src/trpc/backend/files/src/middleware/index.ts.template +7 -7
- package/src/trpc/backend/files/src/procedures/echo.ts.template +3 -3
- package/src/trpc/backend/files/src/router.ts.template +2 -2
- package/src/trpc/backend/files/src/schema/echo.ts.template +2 -2
- package/src/trpc/backend/files/src/schema/index.ts.template +1 -1
- package/src/trpc/backend/generator.d.ts +4 -4
- package/src/trpc/backend/generator.js +98 -84
- package/src/trpc/backend/generator.js.map +1 -1
- package/src/trpc/backend/schema.d.js +6 -0
- package/src/trpc/backend/schema.d.js.map +1 -0
- package/src/trpc/backend/schema.d.ts +3 -2
- package/src/trpc/backend/schema.json +5 -0
- package/src/trpc/react/__snapshots__/generator.spec.ts.snap +4 -4
- package/src/trpc/react/files/src/components/__apiNameClassName__ClientProvider.tsx.template +3 -3
- package/src/trpc/react/generator.d.ts +4 -4
- package/src/trpc/react/generator.js +63 -58
- package/src/trpc/react/generator.js.map +1 -1
- package/src/trpc/react/schema.d.js +6 -0
- package/src/trpc/react/schema.d.js.map +1 -0
- package/src/trpc/react/schema.d.ts +1 -0
- package/src/trpc/react/schema.json +5 -0
- package/src/ts/agent/__snapshots__/generator.spec.ts.snap +781 -22
- package/src/ts/agent/a2a-connection/__snapshots__/generator.spec.ts.snap +256 -0
- package/src/ts/agent/a2a-connection/files/agent-connection/app/__targetAgentKebabCase__-client-strands.ts.template +23 -0
- package/src/ts/agent/a2a-connection/generator.d.ts +3 -3
- package/src/ts/agent/a2a-connection/generator.js +64 -55
- package/src/ts/agent/a2a-connection/generator.js.map +1 -1
- package/src/ts/agent/a2a-connection/schema.d.js +8 -0
- package/src/ts/agent/a2a-connection/schema.d.js.map +1 -0
- package/src/ts/agent/a2a-connection/schema.d.ts +1 -0
- package/src/ts/agent/a2a-connection/schema.json +5 -0
- package/src/ts/agent/files/a2a/index.ts.template +1 -1
- package/src/ts/agent/files/ag-ui/index.ts.template +1 -1
- package/src/ts/agent/files/common/agent.ts.template +6 -2
- package/src/ts/agent/files/deploy/Dockerfile.template +4 -1
- package/src/ts/agent/files/http/client.ts.template +2 -2
- package/src/ts/agent/files/http/index.ts.template +2 -2
- package/src/ts/agent/files/http/router.ts.template +5 -5
- package/src/ts/agent/gateway-connection/__snapshots__/generator.spec.ts.snap +220 -0
- package/src/ts/agent/gateway-connection/files/agent-connection/app/__gatewayKebabCase__-client-strands.ts.template +30 -0
- package/src/ts/agent/gateway-connection/generator.d.ts +10 -0
- package/src/ts/agent/gateway-connection/generator.js +116 -0
- package/src/ts/agent/gateway-connection/generator.js.map +1 -0
- package/src/ts/agent/gateway-connection/schema.d.js +6 -0
- package/src/ts/agent/gateway-connection/schema.d.js.map +1 -0
- package/src/ts/agent/gateway-connection/schema.d.ts +13 -0
- package/src/ts/agent/gateway-connection/schema.json +31 -0
- package/src/ts/agent/generator.d.ts +3 -3
- package/src/ts/agent/generator.js +203 -144
- package/src/ts/agent/generator.js.map +1 -1
- package/src/ts/agent/mcp-connection/__snapshots__/generator.spec.ts.snap +192 -111
- package/src/ts/agent/mcp-connection/files/agent-connection/app/__mcpServerKebabCase__-client-strands.ts.template +22 -0
- package/src/ts/agent/mcp-connection/generator.d.ts +3 -3
- package/src/ts/agent/mcp-connection/generator.js +54 -59
- package/src/ts/agent/mcp-connection/generator.js.map +1 -1
- package/src/ts/agent/mcp-connection/schema.d.js +8 -0
- package/src/ts/agent/mcp-connection/schema.d.js.map +1 -0
- package/src/ts/agent/mcp-connection/schema.d.ts +1 -0
- package/src/ts/agent/mcp-connection/schema.json +5 -0
- package/src/ts/agent/react-connection/generator.d.ts +4 -4
- package/src/ts/agent/react-connection/generator.js +86 -80
- package/src/ts/agent/react-connection/generator.js.map +1 -1
- package/src/ts/agent/react-connection/local-dev.d.ts +13 -0
- package/src/ts/agent/react-connection/local-dev.js +17 -0
- package/src/ts/agent/react-connection/local-dev.js.map +1 -0
- package/src/ts/agent/react-connection/schema.d.js +8 -0
- package/src/ts/agent/react-connection/schema.d.js.map +1 -0
- package/src/ts/agent/react-connection/schema.d.ts +1 -0
- package/src/ts/agent/react-connection/schema.json +5 -0
- package/src/ts/agent/schema.d.js +6 -0
- package/src/ts/agent/schema.d.js.map +1 -0
- package/src/ts/agent/schema.d.ts +1 -0
- package/src/ts/agent/schema.json +5 -0
- package/src/ts/api/generator.d.ts +3 -3
- package/src/ts/api/generator.js +16 -16
- package/src/ts/api/generator.js.map +1 -1
- package/src/ts/api/schema.d.js +6 -0
- package/src/ts/api/schema.d.js.map +1 -0
- package/src/ts/api/schema.d.ts +3 -1
- package/src/ts/api/schema.json +5 -0
- package/src/ts/astro-docs/__snapshots__/generator.spec.ts.snap +15 -16
- package/src/ts/astro-docs/files/translation/scripts/translate.ts.template +3 -2
- package/src/ts/astro-docs/generator.d.ts +3 -3
- package/src/ts/astro-docs/generator.js +71 -54
- package/src/ts/astro-docs/generator.js.map +1 -1
- package/src/ts/astro-docs/schema.d.js +6 -0
- package/src/ts/astro-docs/schema.d.js.map +1 -0
- package/src/ts/astro-docs/schema.d.ts +2 -2
- package/src/ts/astro-docs/schema.json +3 -3
- package/src/ts/docs/generator.d.ts +3 -3
- package/src/ts/docs/generator.js +10 -10
- package/src/ts/docs/generator.js.map +1 -1
- package/src/ts/docs/schema.d.js +6 -0
- package/src/ts/docs/schema.d.js.map +1 -0
- package/src/ts/docs/schema.d.ts +1 -4
- package/src/ts/docs/schema.json +3 -3
- package/src/ts/dynamodb/__snapshots__/generator.spec.ts.snap +400 -512
- package/src/ts/dynamodb/agent-connection/__snapshots__/generator.spec.ts.snap +5 -5
- package/src/ts/dynamodb/agent-connection/generator.d.ts +3 -3
- package/src/ts/dynamodb/agent-connection/generator.js +21 -23
- package/src/ts/dynamodb/agent-connection/generator.js.map +1 -1
- package/src/ts/dynamodb/agent-connection/schema.d.js +8 -0
- package/src/ts/dynamodb/agent-connection/schema.d.js.map +1 -0
- package/src/ts/dynamodb/agent-connection/schema.d.ts +1 -0
- package/src/ts/dynamodb/agent-connection/schema.json +5 -0
- package/src/ts/dynamodb/files/config.json.template +24 -0
- package/src/ts/dynamodb/files/src/client.ts.template +30 -11
- package/src/ts/dynamodb/files/src/entities/example.ts.template +1 -1
- package/src/ts/dynamodb/files/src/entities/index.ts.template +1 -1
- package/src/ts/dynamodb/files/src/index.ts.template +2 -11
- package/src/ts/dynamodb/generator.d.ts +3 -3
- package/src/ts/dynamodb/generator.js +73 -63
- package/src/ts/dynamodb/generator.js.map +1 -1
- package/src/ts/dynamodb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +5 -5
- package/src/ts/dynamodb/mcp-server-connection/generator.d.ts +3 -3
- package/src/ts/dynamodb/mcp-server-connection/generator.js +21 -23
- package/src/ts/dynamodb/mcp-server-connection/generator.js.map +1 -1
- package/src/ts/dynamodb/mcp-server-connection/schema.d.js +8 -0
- package/src/ts/dynamodb/mcp-server-connection/schema.d.js.map +1 -0
- package/src/ts/dynamodb/mcp-server-connection/schema.d.ts +1 -0
- package/src/ts/dynamodb/mcp-server-connection/schema.json +5 -0
- package/src/ts/dynamodb/schema.d.js +6 -0
- package/src/ts/dynamodb/schema.d.js.map +1 -0
- package/src/ts/dynamodb/schema.d.ts +2 -0
- package/src/ts/dynamodb/schema.json +25 -2
- package/src/ts/dynamodb/smithy-connection/__snapshots__/generator.spec.ts.snap +3 -3
- package/src/ts/dynamodb/smithy-connection/generator.d.ts +3 -3
- package/src/ts/dynamodb/smithy-connection/generator.js +20 -22
- package/src/ts/dynamodb/smithy-connection/generator.js.map +1 -1
- package/src/ts/dynamodb/smithy-connection/schema.d.js +8 -0
- package/src/ts/dynamodb/smithy-connection/schema.d.js.map +1 -0
- package/src/ts/dynamodb/smithy-connection/schema.d.ts +1 -0
- package/src/ts/dynamodb/smithy-connection/schema.json +5 -0
- package/src/ts/dynamodb/trpc-connection/__snapshots__/generator.spec.ts.snap +3 -3
- package/src/ts/dynamodb/trpc-connection/generator.d.ts +3 -3
- package/src/ts/dynamodb/trpc-connection/generator.js +20 -22
- package/src/ts/dynamodb/trpc-connection/generator.js.map +1 -1
- package/src/ts/dynamodb/trpc-connection/schema.d.js +8 -0
- package/src/ts/dynamodb/trpc-connection/schema.d.js.map +1 -0
- package/src/ts/dynamodb/trpc-connection/schema.d.ts +1 -0
- package/src/ts/dynamodb/trpc-connection/schema.json +5 -0
- package/src/ts/lambda-function/__snapshots__/generator.spec.ts.snap +4 -4
- package/src/ts/lambda-function/generator.d.ts +3 -3
- package/src/ts/lambda-function/generator.js +59 -56
- package/src/ts/lambda-function/generator.js.map +1 -1
- package/src/ts/lambda-function/io.js +83 -52
- package/src/ts/lambda-function/io.js.map +1 -1
- package/src/ts/lambda-function/schema.d.js +6 -0
- package/src/ts/lambda-function/schema.d.js.map +1 -0
- package/src/ts/lambda-function/schema.d.ts +1 -0
- package/src/ts/lambda-function/schema.json +5 -0
- package/src/ts/lib/__snapshots__/generator.spec.ts.snap +98 -93
- package/src/ts/lib/__snapshots__/vitest.spec.ts.snap +24 -0
- package/src/ts/lib/biome.d.ts +7 -0
- package/src/ts/lib/biome.js +91 -0
- package/src/ts/lib/biome.js.map +1 -0
- package/src/ts/lib/generator.d.ts +3 -3
- package/src/ts/lib/generator.js +107 -108
- package/src/ts/lib/generator.js.map +1 -1
- package/src/ts/lib/grit/vitest-pass-with-no-tests.grit +1 -4
- package/src/ts/lib/schema.d.js +6 -0
- package/src/ts/lib/schema.d.js.map +1 -0
- package/src/ts/lib/schema.d.ts +1 -1
- package/src/ts/lib/schema.json +5 -0
- package/src/ts/lib/ts-project-utils.d.ts +12 -2
- package/src/ts/lib/ts-project-utils.js +90 -67
- package/src/ts/lib/ts-project-utils.js.map +1 -1
- package/src/ts/lib/types.d.ts +6 -0
- package/src/ts/lib/types.js +5 -2
- package/src/ts/lib/types.js.map +1 -1
- package/src/ts/lib/vitest.d.ts +2 -2
- package/src/ts/lib/vitest.js +29 -26
- package/src/ts/lib/vitest.js.map +1 -1
- package/src/ts/mcp-server/__snapshots__/generator.spec.ts.snap +208 -42
- package/src/ts/mcp-server/files/Dockerfile.template +4 -1
- package/src/ts/mcp-server/generator.d.ts +3 -3
- package/src/ts/mcp-server/generator.js +181 -136
- package/src/ts/mcp-server/generator.js.map +1 -1
- package/src/ts/mcp-server/schema.d.js +6 -0
- package/src/ts/mcp-server/schema.d.js.map +1 -0
- package/src/ts/mcp-server/schema.d.ts +1 -0
- package/src/ts/mcp-server/schema.json +5 -0
- package/src/ts/nx-generator/__snapshots__/generator.spec.ts.snap +46 -26
- package/src/ts/nx-generator/files/common/schema.d.ts.template +1 -0
- package/src/ts/nx-generator/files/common/schema.json.template +5 -0
- package/src/ts/nx-generator/files/local/generator.ts.template +3 -3
- package/src/ts/nx-generator/files/nx-plugin-for-aws/generator/generator.ts.template +6 -7
- package/src/ts/nx-generator/generator.d.ts +2 -2
- package/src/ts/nx-generator/generator.js +113 -73
- package/src/ts/nx-generator/generator.js.map +1 -1
- package/src/ts/nx-generator/schema.d.js +6 -0
- package/src/ts/nx-generator/schema.d.js.map +1 -0
- package/src/ts/nx-generator/schema.d.ts +1 -0
- package/src/ts/nx-generator/schema.json +5 -0
- package/src/ts/nx-plugin/__snapshots__/generator.spec.ts.snap +30 -18
- package/src/ts/nx-plugin/files/mcp-server/server.ts.template +5 -5
- package/src/ts/nx-plugin/files/mcp-server/tools/create-workspace-command.ts.template +2 -2
- package/src/ts/nx-plugin/files/mcp-server/tools/general-guidance.ts.template +1 -1
- package/src/ts/nx-plugin/files/mcp-server/tools/generator-guide.ts.template +2 -2
- package/src/ts/nx-plugin/files/mcp-server/tools/list-generators.ts.template +2 -2
- package/src/ts/nx-plugin/files/mcp-server/utils.ts.template +3 -3
- package/src/ts/nx-plugin/generator.d.ts +3 -3
- package/src/ts/nx-plugin/generator.js +61 -50
- package/src/ts/nx-plugin/generator.js.map +1 -1
- package/src/ts/nx-plugin/schema.d.js +9 -0
- package/src/ts/nx-plugin/schema.d.js.map +1 -0
- package/src/ts/nx-plugin/schema.json +5 -0
- package/src/ts/nx-plugin/utils.d.ts +1 -1
- package/src/ts/nx-plugin/utils.js +36 -39
- package/src/ts/nx-plugin/utils.js.map +1 -1
- package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +455 -646
- package/src/ts/rdb/agent-connection/__snapshots__/generator.spec.ts.snap +6 -6
- package/src/ts/rdb/agent-connection/generator.d.ts +3 -3
- package/src/ts/rdb/agent-connection/generator.js +38 -39
- package/src/ts/rdb/agent-connection/generator.js.map +1 -1
- package/src/ts/rdb/agent-connection/schema.d.js +8 -0
- package/src/ts/rdb/agent-connection/schema.d.js.map +1 -0
- package/src/ts/rdb/agent-connection/schema.d.ts +1 -0
- package/src/ts/rdb/agent-connection/schema.json +5 -0
- package/src/ts/rdb/files/Dockerfile.template +8 -1
- package/src/ts/rdb/files/config.json.template +14 -0
- package/src/ts/rdb/files/prisma.config.ts.template +6 -5
- package/src/ts/rdb/files/src/create-db-user-handler.ts.template +9 -11
- package/src/ts/rdb/files/src/index.ts.template +1 -2
- package/src/ts/rdb/files/src/migration-handler.ts.template +2 -29
- package/src/ts/rdb/files/src/prisma.ts.template +33 -25
- package/src/ts/rdb/files/src/utils.ts.template +3 -0
- package/src/ts/rdb/generator.d.ts +3 -7
- package/src/ts/rdb/generator.js +173 -131
- package/src/ts/rdb/generator.js.map +1 -1
- package/src/ts/rdb/mcp-server-connection/__snapshots__/generator.spec.ts.snap +6 -6
- package/src/ts/rdb/mcp-server-connection/generator.d.ts +3 -3
- package/src/ts/rdb/mcp-server-connection/generator.js +36 -37
- package/src/ts/rdb/mcp-server-connection/generator.js.map +1 -1
- package/src/ts/rdb/mcp-server-connection/schema.d.js +8 -0
- package/src/ts/rdb/mcp-server-connection/schema.d.js.map +1 -0
- package/src/ts/rdb/mcp-server-connection/schema.d.ts +1 -0
- package/src/ts/rdb/mcp-server-connection/schema.json +5 -0
- package/src/ts/rdb/schema.d.js +6 -0
- package/src/ts/rdb/schema.d.js.map +1 -0
- package/src/ts/rdb/schema.d.ts +1 -0
- package/src/ts/rdb/schema.json +6 -1
- package/src/ts/rdb/smithy-connection/__snapshots__/generator.spec.ts.snap +3 -3
- package/src/ts/rdb/smithy-connection/generator.d.ts +3 -3
- package/src/ts/rdb/smithy-connection/generator.js +46 -43
- package/src/ts/rdb/smithy-connection/generator.js.map +1 -1
- package/src/ts/rdb/smithy-connection/schema.d.js +8 -0
- package/src/ts/rdb/smithy-connection/schema.d.js.map +1 -0
- package/src/ts/rdb/smithy-connection/schema.d.ts +1 -0
- package/src/ts/rdb/smithy-connection/schema.json +5 -0
- package/src/ts/rdb/trpc-connection/__snapshots__/generator.spec.ts.snap +3 -3
- package/src/ts/rdb/trpc-connection/generator.d.ts +3 -3
- package/src/ts/rdb/trpc-connection/generator.js +36 -31
- package/src/ts/rdb/trpc-connection/generator.js.map +1 -1
- package/src/ts/rdb/trpc-connection/schema.d.js +8 -0
- package/src/ts/rdb/trpc-connection/schema.d.js.map +1 -0
- package/src/ts/rdb/trpc-connection/schema.d.ts +1 -0
- package/src/ts/rdb/trpc-connection/schema.json +5 -0
- package/src/ts/rdb/utils.d.ts +1 -1
- package/src/ts/rdb/utils.js +9 -11
- package/src/ts/rdb/utils.js.map +1 -1
- package/src/ts/react-website/agui/files/common/src/hooks/useAgui__agentNameClassName__.tsx.template +1 -16
- package/src/ts/react-website/agui/generator.d.ts +1 -1
- package/src/ts/react-website/agui/generator.js +69 -62
- package/src/ts/react-website/agui/generator.js.map +1 -1
- package/src/ts/react-website/app/__snapshots__/generator.spec.ts.snap +1190 -799
- package/src/ts/react-website/app/generator.d.ts +4 -4
- package/src/ts/react-website/app/generator.js +217 -192
- package/src/ts/react-website/app/generator.js.map +1 -1
- package/src/ts/react-website/app/schema.d.js +6 -0
- package/src/ts/react-website/app/schema.d.js.map +1 -0
- package/src/ts/react-website/app/schema.d.ts +1 -1
- package/src/ts/react-website/app/schema.json +11 -6
- package/src/ts/react-website/cognito-auth/__snapshots__/generator.spec.ts.snap +129 -18
- package/src/ts/react-website/cognito-auth/__snapshots__/generator.terraform.spec.ts.snap +36 -10
- package/src/ts/react-website/cognito-auth/__snapshots__/generator.ux-provider.spec.ts.snap +0 -20
- package/src/ts/react-website/cognito-auth/files/app/components/CognitoAuth/index.tsx.template +2 -2
- package/src/ts/react-website/cognito-auth/generator.d.ts +4 -4
- package/src/ts/react-website/cognito-auth/generator.js +64 -63
- package/src/ts/react-website/cognito-auth/generator.js.map +1 -1
- package/src/ts/react-website/cognito-auth/grit/cloudscape-auth-menu.grit +8 -6
- package/src/ts/react-website/cognito-auth/grit/cognito-auth-wrapper.grit +1 -1
- package/src/ts/react-website/cognito-auth/grit/none-auth-menu.grit +1 -0
- package/src/ts/react-website/cognito-auth/grit/shadcn-auth-menu.grit +3 -1
- package/src/ts/react-website/cognito-auth/grit/shadcn-state-declarations.grit +3 -1
- package/src/ts/react-website/cognito-auth/schema.d.js +6 -0
- package/src/ts/react-website/cognito-auth/schema.d.js.map +1 -0
- package/src/ts/react-website/cognito-auth/schema.d.ts +1 -0
- package/src/ts/react-website/cognito-auth/schema.json +5 -0
- package/src/ts/react-website/cognito-auth/utils.d.ts +1 -1
- package/src/ts/react-website/cognito-auth/utils.js +34 -32
- package/src/ts/react-website/cognito-auth/utils.js.map +1 -1
- package/src/ts/react-website/runtime-config/__snapshots__/generator.spec.ts.snap +2 -2
- package/src/ts/react-website/runtime-config/files/app/components/RuntimeConfig/index.tsx.template +2 -2
- package/src/ts/react-website/runtime-config/generator.d.ts +3 -3
- package/src/ts/react-website/runtime-config/generator.js +29 -31
- package/src/ts/react-website/runtime-config/generator.js.map +1 -1
- package/src/ts/react-website/runtime-config/schema.d.js +6 -0
- package/src/ts/react-website/runtime-config/schema.d.js.map +1 -0
- package/src/ts/react-website/runtime-config/schema.d.ts +1 -0
- package/src/ts/react-website/runtime-config/schema.json +5 -0
- package/src/ts/sync/generator.d.ts +3 -3
- package/src/ts/sync/generator.js +58 -59
- package/src/ts/sync/generator.js.map +1 -1
- package/src/ts/website/app/generator.d.ts +3 -3
- package/src/ts/website/app/generator.js +10 -10
- package/src/ts/website/app/generator.js.map +1 -1
- package/src/ts/website/app/schema.d.js +6 -0
- package/src/ts/website/app/schema.d.js.map +1 -0
- package/src/ts/website/app/schema.d.ts +1 -1
- package/src/ts/website/app/schema.json +11 -6
- package/src/ts/website/auth/generator.d.ts +4 -4
- package/src/ts/website/auth/generator.js +11 -10
- package/src/ts/website/auth/generator.js.map +1 -1
- package/src/ts/website/auth/schema.d.js +6 -0
- package/src/ts/website/auth/schema.d.js.map +1 -0
- package/src/ts/website/auth/schema.d.ts +1 -0
- package/src/ts/website/auth/schema.json +5 -0
- package/src/utils/agent-chat/agent-chat.d.ts +31 -0
- package/src/utils/agent-chat/agent-chat.js +31 -0
- package/src/utils/agent-chat/agent-chat.js.map +1 -0
- package/src/utils/agent-chat/files/a2a/chat.ts.template +33 -0
- package/src/utils/agent-chat/files/ag-ui/chat.ts.template +17 -0
- package/src/utils/agent-chat/files/common/agentcore.ts.template +81 -0
- package/src/utils/agent-chat/files/http-py/chat.ts.template +43 -0
- package/src/utils/agent-chat/files/http-ts/chat.ts.template +54 -0
- package/src/utils/agent-connection/agent-connection.d.ts +117 -25
- package/src/utils/agent-connection/agent-connection.js +414 -103
- package/src/utils/agent-connection/agent-connection.js.map +1 -1
- package/src/utils/agent-connection/files/core-a2a/agentcore-a2a-client-config.ts.template +93 -0
- package/src/utils/agent-connection/files/core-auth/agentcore-endpoints.ts.template +37 -0
- package/src/utils/agent-connection/files/core-auth/agentcore-fetch.ts.template +54 -0
- package/src/utils/agent-connection/files/core-gateway/agentcore-gateway-mcp-transport.ts.template +41 -0
- package/src/utils/agent-connection/files/core-mcp/agentcore-mcp-transport.ts.template +70 -0
- package/src/utils/agent-connection/files/core-runtime-config/runtime-config.ts.template +22 -32
- package/src/utils/agent-connection/files/core-shared/agentcore-transport.ts.template +39 -0
- package/src/utils/agent-connection/files/core-strands/a2a/agentcore-a2a-client-strands.ts.template +61 -0
- package/src/utils/agent-connection/files/core-strands/base/model-errors-strands.ts.template +36 -0
- package/src/utils/agent-connection/files/{core-runtime-config/with-session-id.ts.template → core-strands/base/with-session-id-strands.ts.template} +1 -1
- package/src/utils/agent-connection/files/core-strands/gateway/agentcore-gateway-mcp-client-strands.ts.template +26 -0
- package/src/utils/agent-connection/files/core-strands/mcp/agentcore-mcp-client-strands.ts.template +27 -0
- package/src/utils/agent-connection/files/py-core-a2a/agentcore_a2a_client_config.py.template +43 -0
- package/src/utils/agent-connection/files/py-core-auth/agentcore_endpoints.py.template +47 -0
- package/src/utils/agent-connection/files/py-core-auth/auth/session.py.template +51 -0
- package/src/utils/agent-connection/files/py-core-gateway/agentcore_gateway_mcp_transport.py.template +28 -0
- package/src/utils/agent-connection/files/py-core-langchain/a2a/agentcore_a2a_client_langchain.py.template +99 -0
- package/src/utils/agent-connection/files/py-core-langchain/gateway/agentcore_gateway_mcp_client_langchain.py.template +57 -0
- package/src/utils/agent-connection/files/py-core-langchain/mcp/agentcore_mcp_client_langchain.py.template +64 -0
- package/src/utils/agent-connection/files/py-core-mcp/agentcore_mcp_transport.py.template +34 -0
- package/src/utils/agent-connection/files/py-core-runtime-config/runtime_config.py.template +5 -18
- package/src/utils/agent-connection/files/py-core-shared/agentcore_transport.py.template +40 -0
- package/src/utils/agent-connection/files/py-core-strands/a2a/agentcore_a2a_client_strands.py.template +66 -0
- package/src/utils/agent-connection/files/py-core-strands/base/model_errors_strands.py.template +40 -0
- package/src/utils/agent-connection/files/py-core-strands/gateway/agentcore_gateway_mcp_client_strands.py.template +22 -0
- package/src/utils/agent-connection/files/py-core-strands/mcp/agentcore_mcp_client_strands.py.template +30 -0
- package/src/utils/agent-core-constructs/agent-core-constructs.d.ts +11 -3
- package/src/utils/agent-core-constructs/agent-core-constructs.js +93 -38
- package/src/utils/agent-core-constructs/agent-core-constructs.js.map +1 -1
- package/src/utils/agent-core-constructs/files/cdk/app/agent-core/__nameKebabCase__/__nameKebabCase__.ts.template +31 -4
- package/src/utils/agent-core-constructs/files/cdk/app/agentcore-gateway/__nameKebabCase__/__nameKebabCase__.ts.template +50 -0
- package/src/utils/agent-core-constructs/files/cdk/core/agentcore-gateway/agentcore-gateway.ts.template +487 -0
- package/src/utils/agent-core-constructs/files/cdk/core/agentcore-gateway/readiness-probe/index.js.template +55 -0
- package/src/utils/agent-core-constructs/files/terraform/app/agent-core/__nameKebabCase__/__nameKebabCase__.tf.template +32 -0
- package/src/utils/agent-core-constructs/files/terraform/app/agentcore-gateway/__nameKebabCase__/__nameKebabCase__.tf.template +449 -0
- package/src/utils/agent-core-constructs/files/terraform/app/agentcore-gateway/__nameKebabCase__/render-cedar.cjs.template +13 -0
- package/src/utils/agent-core-constructs/files/terraform/core/agent-core/runtime.tf.template +151 -13
- package/src/utils/agent-core-constructs/files/terraform/core/agentcore-gateway/gateway.tf.template +14 -0
- package/src/utils/api-constructs/api-constructs.d.ts +2 -2
- package/src/utils/api-constructs/api-constructs.js +36 -31
- package/src/utils/api-constructs/api-constructs.js.map +1 -1
- package/src/utils/api-constructs/files/cdk/app/apis/http/__apiNameKebabCase__.ts.template +8 -8
- package/src/utils/api-constructs/files/cdk/app/apis/rest/__apiNameKebabCase__.ts.template +11 -8
- package/src/utils/api-constructs/files/cdk/core/api/http/http-api.ts.template +26 -9
- package/src/utils/api-constructs/files/cdk/core/api/rest/api-gateway-account/index.js.template +70 -0
- package/src/utils/api-constructs/files/cdk/core/api/rest/api-gateway-account.ts.template +82 -0
- package/src/utils/api-constructs/files/cdk/core/api/rest/rest-api.ts.template +54 -18
- package/src/utils/api-constructs/files/cdk/core/api/trpc/trpc-utils.ts.template +1 -1
- package/src/utils/api-constructs/files/cdk/core/api/utils/utils.ts.template +61 -7
- package/src/utils/api-constructs/files/terraform/app/apis/http/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +101 -12
- package/src/utils/api-constructs/files/terraform/app/apis/rest/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +194 -8
- package/src/utils/api-constructs/files/terraform/core/api/http/http-api/http-api.tf.template +1 -1
- package/src/utils/api-constructs/files/terraform/core/api/rest/api-gateway-account/api-gateway-account.tf.template +83 -0
- package/src/utils/api-constructs/files/terraform/core/api/rest/rest-api/rest-api.tf.template +5 -11
- package/src/utils/api-constructs/open-api-metadata.d.ts +2 -2
- package/src/utils/api-constructs/open-api-metadata.js +22 -22
- package/src/utils/api-constructs/open-api-metadata.js.map +1 -1
- package/src/utils/ast/website.d.ts +5 -1
- package/src/utils/ast/website.js +18 -20
- package/src/utils/ast/website.js.map +1 -1
- package/src/utils/ast.d.ts +33 -1
- package/src/utils/ast.js +146 -70
- package/src/utils/ast.js.map +1 -1
- package/src/utils/base-tsconfig.d.ts +30 -0
- package/src/utils/base-tsconfig.js +32 -0
- package/src/utils/base-tsconfig.js.map +1 -0
- package/src/utils/bundle/bundle.d.ts +1 -1
- package/src/utils/bundle/bundle.js +50 -47
- package/src/utils/bundle/bundle.js.map +1 -1
- package/src/utils/commands.d.ts +10 -3
- package/src/utils/commands.js +60 -26
- package/src/utils/commands.js.map +1 -1
- package/src/utils/config/index.d.ts +5 -5
- package/src/utils/config/index.js +5 -4
- package/src/utils/config/index.js.map +1 -1
- package/src/utils/config/utils.d.ts +13 -3
- package/src/utils/config/utils.js +65 -43
- package/src/utils/config/utils.js.map +1 -1
- package/src/utils/connection/open-api/files/components/__apiNameClassName__Provider.tsx.template +1 -1
- package/src/utils/connection/open-api/react.d.ts +6 -6
- package/src/utils/connection/open-api/react.js +81 -77
- package/src/utils/connection/open-api/react.js.map +1 -1
- package/src/utils/containers.d.ts +1 -1
- package/src/utils/containers.js +22 -23
- package/src/utils/containers.js.map +1 -1
- package/src/utils/docker.d.ts +44 -0
- package/src/utils/docker.js +81 -0
- package/src/utils/docker.js.map +1 -0
- package/src/utils/dynamodb-constructs/dynamodb-constructs.d.ts +3 -3
- package/src/utils/dynamodb-constructs/dynamodb-constructs.js +39 -41
- package/src/utils/dynamodb-constructs/dynamodb-constructs.js.map +1 -1
- package/src/utils/dynamodb-constructs/files/cdk/app/dynamodb/__nameKebabCase__.ts.template +18 -5
- package/src/utils/dynamodb-constructs/files/cdk/core/dynamodb.ts.template +1 -1
- package/src/utils/dynamodb-constructs/files/terraform/app/dynamodb/__nameKebabCase__/__nameKebabCase__.tf.template +24 -17
- package/src/utils/dynamodb-constructs/files/terraform/core/dynamodb/dynamodb.tf.template +1 -1
- package/src/utils/files/common/constructs/src/core/index.ts.template +4 -4
- package/src/utils/files/common/constructs/src/index.ts.template +2 -2
- package/src/utils/files/common/infra-config/src/index.ts.template +3 -3
- package/src/utils/files/common/infra-config/src/resolve-stage.ts.template +2 -2
- package/src/utils/files/common/infra-config/src/stages.config.ts.template +1 -1
- package/src/{ts/dynamodb/files/scripts → utils/files/common/scripts/src/dynamodb}/create-local-table.ts.template +65 -31
- package/src/utils/files/common/scripts/src/dynamodb/pull-image.ts.template +13 -0
- package/src/utils/files/common/scripts/src/dynamodb/start-container.ts.template +106 -0
- package/src/utils/files/common/scripts/src/infra/infra-deploy.ts.template +2 -0
- package/src/utils/files/common/scripts/src/infra/infra-destroy.ts.template +2 -0
- package/src/utils/files/common/scripts/src/{stage-credentials → infra/stage-credentials}/cdk-command.ts.template +6 -3
- package/src/utils/files/common/scripts/src/{stage-credentials → infra/stage-credentials}/run.ts.template +3 -3
- package/src/utils/files/common/scripts/src/rdb/mysql/wait-for-mysql-db.ts.template +32 -0
- package/src/utils/files/common/scripts/src/rdb/postgres/wait-for-postgres-db.ts.template +32 -0
- package/src/utils/files/common/scripts/src/rdb/shared/pull-image.ts.template +16 -0
- package/src/utils/files/common/scripts/src/rdb/shared/start-container.ts.template +117 -0
- package/src/utils/files/common/shadcn/src/index.ts.template +2 -2
- package/src/utils/files/terraform/src/core/asset-bucket/asset-bucket.tf.template +63 -72
- package/src/utils/files/terraform/src/core/runtime-config/appconfig/appconfig.tf.template +1 -1
- package/src/utils/files/terraform/src/core/runtime-config/appconfig-deployment/appconfig-deployment.tf.template +12 -6
- package/src/utils/files/terraform/src/core/runtime-config/entry/entry.tf.template +1 -1
- package/src/utils/files/terraform/src/core/runtime-config/read/read.tf.template +9 -4
- package/src/utils/files/website/hooks/sigv4/useSigV4.tsx.template +1 -1
- package/src/utils/format.d.ts +45 -2
- package/src/utils/format.js +332 -81
- package/src/utils/format.js.map +1 -1
- package/src/utils/fs.d.ts +1 -1
- package/src/utils/fs.js +14 -13
- package/src/utils/fs.js.map +1 -1
- package/src/utils/function-constructs/files/cdk/app/lambda-functions/__nameKebabCase__.ts.template +1 -1
- package/src/utils/function-constructs/files/terraform/app/lambda-functions/__nameKebabCase__/__nameKebabCase__.tf.template +2 -2
- package/src/utils/function-constructs/function-constructs.d.ts +2 -2
- package/src/utils/function-constructs/function-constructs.js +22 -25
- package/src/utils/function-constructs/function-constructs.js.map +1 -1
- package/src/utils/generators.d.ts +4 -0
- package/src/utils/generators.js +18 -20
- package/src/utils/generators.js.map +1 -1
- package/src/utils/git.d.ts +1 -1
- package/src/utils/git.js +19 -34
- package/src/utils/git.js.map +1 -1
- package/src/utils/iac-providers.js +5 -5
- package/src/utils/iac-providers.js.map +1 -1
- package/src/utils/iac.d.ts +1 -1
- package/src/utils/iac.js +12 -14
- package/src/utils/iac.js.map +1 -1
- package/src/utils/identity-constructs/files/cdk/core/user-identity.ts.template +125 -16
- package/src/utils/identity-constructs/files/terraform/core/user-identity/add-callback-url/add-callback-url.tf.template +28 -9
- package/src/utils/identity-constructs/files/terraform/core/user-identity/identity/identity.tf.template +106 -6
- package/src/utils/identity-constructs/files/terraform/core/user-identity/main.tf.template +7 -0
- package/src/utils/identity-constructs/identity-constructs.d.ts +2 -2
- package/src/utils/identity-constructs/identity-constructs.js +28 -28
- package/src/utils/identity-constructs/identity-constructs.js.map +1 -1
- package/src/utils/init.d.ts +53 -0
- package/src/utils/init.js +252 -0
- package/src/utils/init.js.map +1 -0
- package/src/utils/install.d.ts +32 -0
- package/src/utils/install.js +56 -0
- package/src/utils/install.js.map +1 -0
- package/src/utils/js.d.ts +4 -0
- package/src/utils/js.js +27 -20
- package/src/utils/js.js.map +1 -1
- package/src/utils/mcp.d.ts +1 -1
- package/src/utils/mcp.js +34 -41
- package/src/utils/mcp.js.map +1 -1
- package/src/utils/metrics.d.ts +9 -3
- package/src/utils/metrics.js +61 -46
- package/src/utils/metrics.js.map +1 -1
- package/src/utils/mock-project-graph.js +8 -12
- package/src/utils/mock-project-graph.js.map +1 -1
- package/src/utils/module-format.d.ts +28 -0
- package/src/utils/module-format.js +28 -0
- package/src/utils/module-format.js.map +1 -0
- package/src/utils/names.d.ts +22 -0
- package/src/utils/names.js +44 -48
- package/src/utils/names.js.map +1 -1
- package/src/utils/npm-scope.d.ts +1 -1
- package/src/utils/npm-scope.js +9 -17
- package/src/utils/npm-scope.js.map +1 -1
- package/src/utils/nx.d.ts +39 -4
- package/src/utils/nx.js +169 -75
- package/src/utils/nx.js.map +1 -1
- package/src/utils/nxlv-python.d.ts +1 -1
- package/src/utils/nxlv-python.js +27 -15
- package/src/utils/nxlv-python.js.map +1 -1
- package/src/utils/object.js +5 -11
- package/src/utils/object.js.map +1 -1
- package/src/utils/paths.d.ts +1 -1
- package/src/utils/paths.js +11 -15
- package/src/utils/paths.js.map +1 -1
- package/src/utils/pkg-manager.js +4 -9
- package/src/utils/pkg-manager.js.map +1 -1
- package/src/utils/pnpm-workspace.d.ts +1 -1
- package/src/utils/pnpm-workspace.js +22 -22
- package/src/utils/pnpm-workspace.js.map +1 -1
- package/src/utils/port.d.ts +29 -7
- package/src/utils/port.js +67 -28
- package/src/utils/port.js.map +1 -1
- package/src/utils/py.d.ts +16 -3
- package/src/utils/py.js +72 -47
- package/src/utils/py.js.map +1 -1
- package/src/utils/rdb-constructs/files/cdk/app/dbs/__nameKebabCase__.ts.template +72 -18
- package/src/utils/rdb-constructs/files/cdk/core/rdb/aurora.ts.template +97 -88
- package/src/utils/rdb-constructs/files/terraform/app/dbs/__nameKebabCase__/__nameKebabCase__.tf.template +127 -53
- package/src/utils/rdb-constructs/files/terraform/core/rdb/aurora/aurora.tf.template +36 -48
- package/src/utils/rdb-constructs/rdb-constructs.d.ts +16 -5
- package/src/utils/rdb-constructs/rdb-constructs.js +38 -41
- package/src/utils/rdb-constructs/rdb-constructs.js.map +1 -1
- package/src/utils/shared-constructs-constants.d.ts +1 -0
- package/src/utils/shared-constructs-constants.js +16 -15
- package/src/utils/shared-constructs-constants.js.map +1 -1
- package/src/utils/shared-constructs.d.ts +2 -2
- package/src/utils/shared-constructs.js +60 -67
- package/src/utils/shared-constructs.js.map +1 -1
- package/src/utils/shared-dynamodb-scripts.d.ts +11 -0
- package/src/utils/shared-dynamodb-scripts.js +25 -0
- package/src/utils/shared-dynamodb-scripts.js.map +1 -0
- package/src/utils/shared-infra-config.d.ts +1 -1
- package/src/utils/shared-infra-config.js +31 -30
- package/src/utils/shared-infra-config.js.map +1 -1
- package/src/utils/shared-infra-scripts.d.ts +11 -0
- package/src/utils/shared-infra-scripts.js +42 -0
- package/src/utils/shared-infra-scripts.js.map +1 -0
- package/src/utils/shared-rdb-scripts.d.ts +16 -0
- package/src/utils/shared-rdb-scripts.js +32 -0
- package/src/utils/shared-rdb-scripts.js.map +1 -0
- package/src/utils/shared-scripts.d.ts +2 -5
- package/src/utils/shared-scripts.js +12 -38
- package/src/utils/shared-scripts.js.map +1 -1
- package/src/utils/shared-shadcn.d.ts +1 -1
- package/src/utils/shared-shadcn.js +65 -71
- package/src/utils/shared-shadcn.js.map +1 -1
- package/src/utils/test.d.ts +15 -1
- package/src/utils/test.js +41 -23
- package/src/utils/test.js.map +1 -1
- package/src/utils/toml.d.ts +1 -1
- package/src/utils/toml.js +10 -14
- package/src/utils/toml.js.map +1 -1
- package/src/utils/versions.d.ts +150 -97
- package/src/utils/versions.js +157 -115
- package/src/utils/versions.js.map +1 -1
- package/src/utils/warm-ruff-cache.d.ts +12 -0
- package/src/utils/warm-ruff-cache.js +39 -0
- package/src/utils/warm-ruff-cache.js.map +1 -0
- package/src/utils/website-constructs/files/cdk/app/static-websites/__websiteNameKebabCase__.ts.template +2 -2
- package/src/utils/website-constructs/files/cdk/core/static-website.ts.template +200 -41
- package/src/utils/website-constructs/files/terraform/app/static-websites/__websiteNameKebabCase__/__websiteNameKebabCase__.tf.template +1 -1
- package/src/utils/website-constructs/files/terraform/core/static-website/static-website.tf.template +145 -93
- package/src/utils/website-constructs/website-constructs.d.ts +2 -2
- package/src/utils/website-constructs/website-constructs.js +38 -30
- package/src/utils/website-constructs/website-constructs.js.map +1 -1
- package/bin/aws-nx-mcp.js +0 -17
- package/bin/aws-nx-mcp.js.map +0 -1
- package/sdk/connection.d.ts +0 -6
- package/sdk/connection.js +0 -10
- package/sdk/connection.js.map +0 -1
- package/sdk/open-api.d.ts +0 -10
- package/sdk/open-api.js +0 -15
- package/sdk/open-api.js.map +0 -1
- package/sdk/py.d.ts +0 -14
- package/sdk/py.js +0 -18
- package/sdk/py.js.map +0 -1
- package/sdk/terraform.d.ts +0 -6
- package/sdk/terraform.js +0 -11
- package/sdk/terraform.js.map +0 -1
- package/sdk/ts.d.ts +0 -29
- package/sdk/ts.js +0 -47
- package/sdk/ts.js.map +0 -1
- package/sdk/utils/ast.js +0 -12
- package/sdk/utils/ast.js.map +0 -1
- package/sdk/utils/format.js +0 -10
- package/sdk/utils/format.js.map +0 -1
- package/sdk/utils/test.js +0 -10
- package/sdk/utils/test.js.map +0 -1
- package/src/connection/agent-serve-local.js +0 -48
- package/src/connection/agent-serve-local.js.map +0 -1
- package/src/connection/serve-local.d.ts +0 -15
- package/src/connection/serve-local.js +0 -41
- package/src/connection/serve-local.js.map +0 -1
- package/src/py/agent/a2a-connection/files/agent-connection/app/__targetAgentSnakeCase___client.py.template +0 -22
- package/src/py/agent/mcp-connection/files/agent-connection/app/__mcpServerSnakeCase___client.py.template +0 -22
- package/src/py/agent/react-connection/serve-local.js +0 -30
- package/src/py/agent/react-connection/serve-local.js.map +0 -1
- package/src/py/agent/scripts/http/chat.ts.template +0 -38
- package/src/ts/agent/a2a-connection/files/agent-connection/app/__targetAgentKebabCase__-client.ts.template +0 -19
- package/src/ts/agent/mcp-connection/files/agent-connection/app/__mcpServerKebabCase__-client.ts.template +0 -19
- package/src/ts/agent/react-connection/serve-local.d.ts +0 -13
- package/src/ts/agent/react-connection/serve-local.js +0 -19
- package/src/ts/agent/react-connection/serve-local.js.map +0 -1
- package/src/ts/agent/scripts/http/chat.ts.template +0 -35
- package/src/ts/dynamodb/files/scripts/pull-image.ts.template +0 -15
- package/src/ts/dynamodb/files/scripts/start-container.ts.template +0 -81
- package/src/ts/dynamodb/files/src/constants.ts.template +0 -9
- package/src/ts/dynamodb/files/src/gsi.ts.template +0 -14
- package/src/ts/lib/eslint.d.ts +0 -14
- package/src/ts/lib/eslint.js +0 -90
- package/src/ts/lib/eslint.js.map +0 -1
- package/src/ts/lib/grit/eslint-dependency-checks-warn.grit +0 -1
- package/src/ts/rdb/files/scripts/docker-pull.ts.template +0 -15
- package/src/ts/rdb/files/scripts/docker-start.ts.template +0 -84
- package/src/ts/rdb/files/scripts/wait-for-db.ts.template +0 -55
- package/src/ts/rdb/files/src/constants.ts.template +0 -8
- package/src/utils/agent-connection/files/core-a2a/agentcore-a2a-client.ts.template +0 -123
- package/src/utils/agent-connection/files/core-mcp/agentcore-mcp-client.ts.template +0 -128
- package/src/utils/agent-connection/files/py-core-a2a/agentcore_a2a_client.py.template +0 -120
- package/src/utils/agent-connection/files/py-core-mcp/agentcore_mcp_client.py.template +0 -89
- package/src/utils/files/common/scripts/src/infra-deploy.ts.template +0 -2
- package/src/utils/files/common/scripts/src/infra-destroy.ts.template +0 -2
- package/src/utils/files/terraform/scripts/reset-runtime-config.ts.template +0 -25
- /package/{bin → src/bin}/aws-nx-mcp.d.ts +0 -0
- /package/src/utils/agent-connection/files/{py-core-runtime-config/with_session_id.py.template → py-core-strands/base/with_session_id_strands.py.template} +0 -0
- /package/src/utils/files/common/scripts/src/{index.ts.template → infra/index.ts.template} +0 -0
- /package/src/utils/files/common/scripts/src/{stage-credentials → infra/stage-credentials}/credentials.ts.template +0 -0
- /package/src/utils/files/common/scripts/src/{stage-credentials → infra/stage-credentials}/stage-parser.ts.template +0 -0
|
@@ -0,0 +1,2038 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`py#rdb generator > should generate MySQL dependencies and templates 1`] = `
|
|
4
|
+
"import ssl
|
|
5
|
+
from collections.abc import AsyncGenerator
|
|
6
|
+
from contextlib import asynccontextmanager
|
|
7
|
+
|
|
8
|
+
import boto3
|
|
9
|
+
from sqlalchemy import event
|
|
10
|
+
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
|
|
11
|
+
|
|
12
|
+
from .utils import build_database_url, get_database_config, get_local_dev_config, is_local_dev
|
|
13
|
+
|
|
14
|
+
# Generated: must match runtimeConfigKey in config.json
|
|
15
|
+
_runtime_config_key = "Db"
|
|
16
|
+
|
|
17
|
+
_engine = None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def get_engine():
|
|
21
|
+
global _engine
|
|
22
|
+
if _engine is not None:
|
|
23
|
+
return _engine
|
|
24
|
+
if is_local_dev():
|
|
25
|
+
cfg = get_local_dev_config()
|
|
26
|
+
url = build_database_url(cfg["dbUser"], cfg["host"], cfg["port"], cfg["dbName"])
|
|
27
|
+
ssl_args: dict = {}
|
|
28
|
+
else:
|
|
29
|
+
config = get_database_config(_runtime_config_key)
|
|
30
|
+
url = build_database_url(
|
|
31
|
+
config["dbUser"],
|
|
32
|
+
config["hostname"],
|
|
33
|
+
config["port"],
|
|
34
|
+
config["database"],
|
|
35
|
+
)
|
|
36
|
+
ssl_args = {"ssl": ssl.create_default_context()}
|
|
37
|
+
_engine = create_async_engine(url, connect_args=ssl_args)
|
|
38
|
+
|
|
39
|
+
@event.listens_for(_engine.sync_engine, "do_connect")
|
|
40
|
+
def provide_password(_dialect, _connection_record, _cargs, connection_params):
|
|
41
|
+
if is_local_dev():
|
|
42
|
+
connection_params["password"] = get_local_dev_config()["dbPassword"]
|
|
43
|
+
else:
|
|
44
|
+
config = get_database_config(_runtime_config_key)
|
|
45
|
+
connection_params["password"] = boto3.client(
|
|
46
|
+
"rds",
|
|
47
|
+
region_name=config["region"],
|
|
48
|
+
).generate_db_auth_token(
|
|
49
|
+
DBHostname=config["hostname"],
|
|
50
|
+
Port=config["port"],
|
|
51
|
+
DBUsername=config["dbUser"],
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
return _engine
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@asynccontextmanager
|
|
58
|
+
async def session_context() -> AsyncGenerator[AsyncSession]:
|
|
59
|
+
async with AsyncSession(get_engine()) as session:
|
|
60
|
+
yield session
|
|
61
|
+
"
|
|
62
|
+
`;
|
|
63
|
+
|
|
64
|
+
exports[`py#rdb generator > should generate MySQL dependencies and templates 2`] = `
|
|
65
|
+
"import asyncio
|
|
66
|
+
import ssl
|
|
67
|
+
|
|
68
|
+
from alembic import command
|
|
69
|
+
from alembic.config import Config
|
|
70
|
+
from sqlalchemy.ext.asyncio import create_async_engine
|
|
71
|
+
from sqlalchemy.pool import NullPool
|
|
72
|
+
|
|
73
|
+
from .utils import build_database_url, get_database_secret, with_connection_retry
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _apply_migrations(sync_conn, alembic_cfg: Config) -> None:
|
|
77
|
+
alembic_cfg.attributes["connection"] = sync_conn
|
|
78
|
+
command.upgrade(alembic_cfg, "head")
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
async def _run_migrations() -> None:
|
|
82
|
+
secret = get_database_secret()
|
|
83
|
+
database_url = build_database_url(
|
|
84
|
+
secret["username"],
|
|
85
|
+
secret["host"],
|
|
86
|
+
secret["port"],
|
|
87
|
+
secret["dbname"],
|
|
88
|
+
password=secret["password"],
|
|
89
|
+
)
|
|
90
|
+
alembic_cfg = Config("alembic.ini")
|
|
91
|
+
engine = create_async_engine(
|
|
92
|
+
database_url,
|
|
93
|
+
poolclass=NullPool,
|
|
94
|
+
connect_args={"ssl": ssl.create_default_context()},
|
|
95
|
+
)
|
|
96
|
+
try:
|
|
97
|
+
async with engine.begin() as conn:
|
|
98
|
+
await conn.run_sync(lambda c: _apply_migrations(c, alembic_cfg))
|
|
99
|
+
finally:
|
|
100
|
+
await engine.dispose()
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def handler(_event, _context):
|
|
104
|
+
with_connection_retry(lambda: asyncio.run(_run_migrations()))
|
|
105
|
+
"
|
|
106
|
+
`;
|
|
107
|
+
|
|
108
|
+
exports[`py#rdb generator > should generate MySQL dependencies and templates 3`] = `
|
|
109
|
+
"import asyncio
|
|
110
|
+
import secrets
|
|
111
|
+
import ssl
|
|
112
|
+
from typing import Any
|
|
113
|
+
|
|
114
|
+
import aiomysql
|
|
115
|
+
|
|
116
|
+
from .utils import get_database_secret, with_connection_retry
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
async def _ensure_database_user(db_user: str) -> None:
|
|
120
|
+
secret = get_database_secret()
|
|
121
|
+
conn = await aiomysql.connect(
|
|
122
|
+
host=secret["host"],
|
|
123
|
+
port=int(secret["port"]),
|
|
124
|
+
db=secret["dbname"],
|
|
125
|
+
user=secret["username"],
|
|
126
|
+
password=secret["password"],
|
|
127
|
+
ssl=ssl.create_default_context(),
|
|
128
|
+
)
|
|
129
|
+
try:
|
|
130
|
+
async with conn.cursor() as cursor:
|
|
131
|
+
await cursor.execute(
|
|
132
|
+
"CREATE USER IF NOT EXISTS %s@'%%' IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS'",
|
|
133
|
+
(db_user,),
|
|
134
|
+
)
|
|
135
|
+
await cursor.execute(
|
|
136
|
+
"ALTER USER %s@'%%' IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS' REQUIRE SSL",
|
|
137
|
+
(db_user,),
|
|
138
|
+
)
|
|
139
|
+
await cursor.execute(
|
|
140
|
+
f"GRANT SELECT, INSERT, UPDATE, DELETE ON \`{secret['dbname']}\`.* TO %s@'%%'",
|
|
141
|
+
(db_user,),
|
|
142
|
+
)
|
|
143
|
+
await conn.commit()
|
|
144
|
+
finally:
|
|
145
|
+
conn.close()
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
_PHYSICAL_RESOURCE_ID_PREFIX = "db-user:"
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _resolve_db_user(physical_resource_id: str | None) -> str:
|
|
152
|
+
if physical_resource_id and physical_resource_id.startswith(_PHYSICAL_RESOURCE_ID_PREFIX):
|
|
153
|
+
return physical_resource_id[len(_PHYSICAL_RESOURCE_ID_PREFIX) :]
|
|
154
|
+
return f"db_{secrets.token_hex(8)}"
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def handler(event: dict[str, Any], _context: Any) -> dict[str, Any]:
|
|
158
|
+
db_user = _resolve_db_user(event.get("PhysicalResourceId"))
|
|
159
|
+
|
|
160
|
+
if event.get("RequestType") != "Delete":
|
|
161
|
+
with_connection_retry(lambda: asyncio.run(_ensure_database_user(db_user)))
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
"PhysicalResourceId": f"{_PHYSICAL_RESOURCE_ID_PREFIX}{db_user}",
|
|
165
|
+
"Data": {"dbUser": db_user},
|
|
166
|
+
}
|
|
167
|
+
"
|
|
168
|
+
`;
|
|
169
|
+
|
|
170
|
+
exports[`py#rdb generator > should generate MySQL dependencies and templates 4`] = `
|
|
171
|
+
"FROM public.ecr.aws/lambda/python:3.14
|
|
172
|
+
|
|
173
|
+
WORKDIR \${LAMBDA_TASK_ROOT}
|
|
174
|
+
|
|
175
|
+
COPY . .
|
|
176
|
+
|
|
177
|
+
ADD https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem /etc/pki/ca-trust/source/anchors/global-bundle.pem
|
|
178
|
+
RUN update-ca-trust
|
|
179
|
+
|
|
180
|
+
CMD ["proj_db.migration_handler.handler"]
|
|
181
|
+
"
|
|
182
|
+
`;
|
|
183
|
+
|
|
184
|
+
exports[`py#rdb generator > should generate MySQL dependencies and templates 5`] = `
|
|
185
|
+
"FROM public.ecr.aws/lambda/python:3.14
|
|
186
|
+
|
|
187
|
+
WORKDIR \${LAMBDA_TASK_ROOT}
|
|
188
|
+
|
|
189
|
+
COPY . .
|
|
190
|
+
|
|
191
|
+
ADD https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem /etc/pki/ca-trust/source/anchors/global-bundle.pem
|
|
192
|
+
RUN update-ca-trust
|
|
193
|
+
|
|
194
|
+
CMD ["proj_db.create_db_user_handler.handler"]
|
|
195
|
+
"
|
|
196
|
+
`;
|
|
197
|
+
|
|
198
|
+
exports[`py#rdb generator > should generate Terraform modules 1`] = `
|
|
199
|
+
"terraform {
|
|
200
|
+
required_version = ">= 1.0"
|
|
201
|
+
|
|
202
|
+
required_providers {
|
|
203
|
+
archive = {
|
|
204
|
+
source = "hashicorp/archive"
|
|
205
|
+
version = "2.8.0"
|
|
206
|
+
}
|
|
207
|
+
aws = {
|
|
208
|
+
source = "hashicorp/aws"
|
|
209
|
+
version = "6.54.0"
|
|
210
|
+
}
|
|
211
|
+
null = {
|
|
212
|
+
source = "hashicorp/null"
|
|
213
|
+
version = "3.3.0"
|
|
214
|
+
}
|
|
215
|
+
random = {
|
|
216
|
+
source = "hashicorp/random"
|
|
217
|
+
version = "3.9.0"
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
variable "vpc_id" {
|
|
223
|
+
description = "VPC where the Aurora cluster will be deployed."
|
|
224
|
+
type = string
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
variable "database_subnet_ids" {
|
|
228
|
+
description = "Subnet IDs for the Aurora cluster and RDS Proxy. Private isolated subnets are fine — no outbound egress required."
|
|
229
|
+
type = list(string)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
variable "lambda_subnet_ids" {
|
|
233
|
+
description = "Subnet IDs for the create-db-user and migration Lambda functions. Must have outbound egress to AWS service endpoints (e.g. Secrets Manager) — use private subnets with a NAT gateway."
|
|
234
|
+
type = list(string)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
variable "engine_version" {
|
|
238
|
+
description = "Aurora engine version."
|
|
239
|
+
type = string
|
|
240
|
+
default = null
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
variable "port" {
|
|
244
|
+
description = "Database port for the selected Aurora engine."
|
|
245
|
+
type = number
|
|
246
|
+
default = null
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
variable "serverless_min_capacity" {
|
|
250
|
+
description = "Minimum Aurora Serverless v2 ACUs."
|
|
251
|
+
type = number
|
|
252
|
+
default = 0.5
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
variable "serverless_max_capacity" {
|
|
256
|
+
description = "Maximum Aurora Serverless v2 ACUs."
|
|
257
|
+
type = number
|
|
258
|
+
default = 4
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
variable "instance_count" {
|
|
262
|
+
description = "Number of Aurora instances to create."
|
|
263
|
+
type = number
|
|
264
|
+
default = 1
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
variable "deletion_protection" {
|
|
268
|
+
description = "Whether deletion protection is enabled."
|
|
269
|
+
type = bool
|
|
270
|
+
default = true
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
variable "skip_final_snapshot" {
|
|
274
|
+
description = "Whether to skip the final snapshot on deletion."
|
|
275
|
+
type = bool
|
|
276
|
+
default = false
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
variable "enable_rds_proxy" {
|
|
280
|
+
description = "Whether to provision an RDS Proxy in front of the Aurora cluster."
|
|
281
|
+
type = bool
|
|
282
|
+
default = true
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
variable "enable_credential_rotation" {
|
|
286
|
+
description = "Whether to enable automatic credential rotation for the admin secret."
|
|
287
|
+
type = bool
|
|
288
|
+
default = true
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
variable "enable_cloudwatch_logs" {
|
|
292
|
+
description = "Whether to export Aurora engine logs to CloudWatch. PostgreSQL also enables verbose statement logging."
|
|
293
|
+
type = bool
|
|
294
|
+
default = false
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
variable "enable_performance_insights" {
|
|
298
|
+
description = "Whether to enable Performance Insights on Aurora cluster instances."
|
|
299
|
+
type = bool
|
|
300
|
+
default = true
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
variable "performance_insights_retention_period" {
|
|
304
|
+
description = "Retention period, in days, for Performance Insights data when enabled."
|
|
305
|
+
type = number
|
|
306
|
+
default = 7
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
variable "enable_backup" {
|
|
310
|
+
description = "Whether to provision an AWS Backup plan for the Aurora cluster."
|
|
311
|
+
type = bool
|
|
312
|
+
default = false
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
variable "tags" {
|
|
316
|
+
description = "Tags to apply to all resources."
|
|
317
|
+
type = map(string)
|
|
318
|
+
default = {}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
variable "migration_docker_image_tag" {
|
|
322
|
+
description = "Docker image tag for the migration handler. Defaults to the tag built by the Nx docker target."
|
|
323
|
+
type = string
|
|
324
|
+
default = "proj-db-migration:latest"
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
variable "create_db_user_docker_image_tag" {
|
|
328
|
+
description = "Docker image tag for the Python create-db-user handler. Defaults to the tag built by the Nx docker target."
|
|
329
|
+
type = string
|
|
330
|
+
default = "proj-db-create-db-user:latest"
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
data "aws_region" "current" {}
|
|
335
|
+
data "aws_caller_identity" "current" {}
|
|
336
|
+
|
|
337
|
+
resource "random_string" "suffix" {
|
|
338
|
+
length = 8
|
|
339
|
+
special = false
|
|
340
|
+
upper = false
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
locals {
|
|
344
|
+
config = jsondecode(file("\${path.module}/../../../../../../../packages/db/config.json"))
|
|
345
|
+
runtime_config_key = local.config.runtimeConfigKey
|
|
346
|
+
migration_function_name = "db-migration-\${random_string.suffix.result}"
|
|
347
|
+
create_db_user_function_name = "db-create-db-user-\${random_string.suffix.result}"
|
|
348
|
+
database_runtime_user = "db_\${random_string.suffix.result}"
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
module "aurora" {
|
|
352
|
+
source = "../../../core/rdb/aurora"
|
|
353
|
+
#checkov:skip=CKV_AWS_139:Deletion protection is enabled but checkov is unable to detect it correctly
|
|
354
|
+
name = "db"
|
|
355
|
+
vpc_id = var.vpc_id
|
|
356
|
+
subnet_ids = var.database_subnet_ids
|
|
357
|
+
lambda_subnet_ids = var.lambda_subnet_ids
|
|
358
|
+
engine = "aurora-postgresql"
|
|
359
|
+
engine_version = var.engine_version
|
|
360
|
+
database_name = "database_name"
|
|
361
|
+
admin_user = "databaseUser"
|
|
362
|
+
port = var.port
|
|
363
|
+
serverless_min_capacity = var.serverless_min_capacity
|
|
364
|
+
serverless_max_capacity = var.serverless_max_capacity
|
|
365
|
+
instance_count = var.instance_count
|
|
366
|
+
deletion_protection = var.deletion_protection
|
|
367
|
+
skip_final_snapshot = var.skip_final_snapshot
|
|
368
|
+
enable_rds_proxy = var.enable_rds_proxy
|
|
369
|
+
enable_credential_rotation = var.enable_credential_rotation
|
|
370
|
+
enable_cloudwatch_logs = var.enable_cloudwatch_logs
|
|
371
|
+
enable_performance_insights = var.enable_performance_insights
|
|
372
|
+
performance_insights_retention_period = var.performance_insights_retention_period
|
|
373
|
+
enable_backup = var.enable_backup
|
|
374
|
+
tags = var.tags
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
resource "aws_iam_role_policy" "proxy_db_user_connect" {
|
|
378
|
+
count = var.enable_rds_proxy ? 1 : 0
|
|
379
|
+
|
|
380
|
+
role = module.aurora.proxy_role_name
|
|
381
|
+
|
|
382
|
+
policy = jsonencode({
|
|
383
|
+
Version = "2012-10-17"
|
|
384
|
+
Statement = [
|
|
385
|
+
{
|
|
386
|
+
Effect = "Allow"
|
|
387
|
+
Action = ["rds-db:connect"]
|
|
388
|
+
Resource = [
|
|
389
|
+
"arn:aws:rds-db:\${data.aws_region.current.region}:\${data.aws_caller_identity.current.account_id}:dbuser:\${module.aurora.cluster_resource_id}/\${local.database_runtime_user}"
|
|
390
|
+
]
|
|
391
|
+
}
|
|
392
|
+
]
|
|
393
|
+
})
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
module "add_rdb_to_runtime_config" {
|
|
398
|
+
source = "../../../core/runtime-config/entry"
|
|
399
|
+
|
|
400
|
+
namespace = "database"
|
|
401
|
+
key = local.runtime_config_key
|
|
402
|
+
value = {
|
|
403
|
+
hostname = module.aurora.cluster_endpoint
|
|
404
|
+
port = module.aurora.cluster_port
|
|
405
|
+
database = module.aurora.database_name
|
|
406
|
+
adminUser = module.aurora.admin_user
|
|
407
|
+
dbUser = local.database_runtime_user
|
|
408
|
+
region = data.aws_region.current.region
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
resource "aws_ecr_repository" "migration_handler" {
|
|
413
|
+
#checkov:skip=CKV_AWS_136:AES256 encryption is sufficient for ECR repositories
|
|
414
|
+
name = "db-migration-\${random_string.suffix.result}"
|
|
415
|
+
image_tag_mutability = "IMMUTABLE"
|
|
416
|
+
force_delete = true
|
|
417
|
+
|
|
418
|
+
image_scanning_configuration {
|
|
419
|
+
scan_on_push = true
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
tags = var.tags
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
resource "aws_ecr_repository_policy" "migration_handler" {
|
|
426
|
+
repository = aws_ecr_repository.migration_handler.name
|
|
427
|
+
|
|
428
|
+
policy = jsonencode({
|
|
429
|
+
Version = "2012-10-17"
|
|
430
|
+
Statement = [
|
|
431
|
+
{
|
|
432
|
+
Sid = "AllowPushPull"
|
|
433
|
+
Effect = "Allow"
|
|
434
|
+
Principal = {
|
|
435
|
+
AWS = "arn:aws:iam::\${data.aws_caller_identity.current.account_id}:root"
|
|
436
|
+
}
|
|
437
|
+
Action = [
|
|
438
|
+
"ecr:BatchCheckLayerAvailability",
|
|
439
|
+
"ecr:CompleteLayerUpload",
|
|
440
|
+
"ecr:GetDownloadUrlForLayer",
|
|
441
|
+
"ecr:InitiateLayerUpload",
|
|
442
|
+
"ecr:PutImage",
|
|
443
|
+
"ecr:UploadLayerPart"
|
|
444
|
+
]
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
Sid = "AllowLambdaPull"
|
|
448
|
+
Effect = "Allow"
|
|
449
|
+
Principal = {
|
|
450
|
+
Service = "lambda.amazonaws.com"
|
|
451
|
+
}
|
|
452
|
+
Action = [
|
|
453
|
+
"ecr:BatchCheckLayerAvailability",
|
|
454
|
+
"ecr:BatchGetImage",
|
|
455
|
+
"ecr:GetDownloadUrlForLayer"
|
|
456
|
+
]
|
|
457
|
+
}
|
|
458
|
+
]
|
|
459
|
+
})
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
data "external" "docker_digest" {
|
|
463
|
+
program = ["sh", "-c", "echo '{\\"digest\\":\\"'$(docker inspect \${var.migration_docker_image_tag} --format '{{.Id}}')'\\"}' "]
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
locals {
|
|
467
|
+
# Content-based, immutable image tag derived from the local image digest
|
|
468
|
+
image_tag = replace(data.external.docker_digest.result.digest, "sha256:", "")
|
|
469
|
+
}
|
|
470
|
+
data "external" "create_db_user_docker_digest" {
|
|
471
|
+
program = ["sh", "-c", "echo '{\\"digest\\":\\"'$(docker inspect \${var.create_db_user_docker_image_tag} --format '{{.Id}}')'\\"}' "]
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
locals {
|
|
475
|
+
create_db_user_image_tag = replace(data.external.create_db_user_docker_digest.result.digest, "sha256:", "")
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
resource "null_resource" "docker_publish" {
|
|
479
|
+
triggers = {
|
|
480
|
+
docker_digest = data.external.docker_digest.result.digest
|
|
481
|
+
repository_url = aws_ecr_repository.migration_handler.repository_url
|
|
482
|
+
migration_docker_image_tag = var.migration_docker_image_tag
|
|
483
|
+
image_tag = local.image_tag
|
|
484
|
+
create_db_user_docker_digest = data.external.create_db_user_docker_digest.result.digest
|
|
485
|
+
create_db_user_docker_image_tag = var.create_db_user_docker_image_tag
|
|
486
|
+
create_db_user_image_tag = local.create_db_user_image_tag
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
provisioner "local-exec" {
|
|
490
|
+
command = <<-EOT
|
|
491
|
+
aws ecr get-login-password --region "$AWS_REGION" | docker login --username AWS --password-stdin "$REPOSITORY_URL"
|
|
492
|
+
docker tag "$MIGRATION_DOCKER_IMAGE_TAG" "$REPOSITORY_URL:$IMAGE_TAG"
|
|
493
|
+
docker push "$REPOSITORY_URL:$IMAGE_TAG"
|
|
494
|
+
docker tag "$CREATE_DB_USER_DOCKER_IMAGE_TAG" "$REPOSITORY_URL:create-db-user-$CREATE_DB_USER_IMAGE_TAG"
|
|
495
|
+
docker push "$REPOSITORY_URL:create-db-user-$CREATE_DB_USER_IMAGE_TAG"
|
|
496
|
+
EOT
|
|
497
|
+
environment = {
|
|
498
|
+
AWS_REGION = data.aws_region.current.region
|
|
499
|
+
REPOSITORY_URL = self.triggers.repository_url
|
|
500
|
+
MIGRATION_DOCKER_IMAGE_TAG = self.triggers.migration_docker_image_tag
|
|
501
|
+
IMAGE_TAG = self.triggers.image_tag
|
|
502
|
+
CREATE_DB_USER_DOCKER_IMAGE_TAG = self.triggers.create_db_user_docker_image_tag
|
|
503
|
+
CREATE_DB_USER_IMAGE_TAG = self.triggers.create_db_user_image_tag
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
depends_on = [aws_ecr_repository_policy.migration_handler]
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
resource "aws_iam_role" "migration_handler" {
|
|
511
|
+
name = "DbMigrationHandlerRole-\${random_string.suffix.result}"
|
|
512
|
+
|
|
513
|
+
assume_role_policy = jsonencode({
|
|
514
|
+
Version = "2012-10-17"
|
|
515
|
+
Statement = [
|
|
516
|
+
{
|
|
517
|
+
Effect = "Allow"
|
|
518
|
+
Principal = {
|
|
519
|
+
Service = "lambda.amazonaws.com"
|
|
520
|
+
}
|
|
521
|
+
Action = "sts:AssumeRole"
|
|
522
|
+
}
|
|
523
|
+
]
|
|
524
|
+
})
|
|
525
|
+
|
|
526
|
+
tags = var.tags
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
resource "aws_iam_role_policy_attachment" "migration_handler_basic_execution" {
|
|
530
|
+
role = aws_iam_role.migration_handler.name
|
|
531
|
+
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
resource "aws_iam_role_policy_attachment" "migration_handler_vpc_access" {
|
|
535
|
+
role = aws_iam_role.migration_handler.name
|
|
536
|
+
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
resource "aws_iam_role_policy_attachment" "migration_handler_xray" {
|
|
540
|
+
role = aws_iam_role.migration_handler.name
|
|
541
|
+
policy_arn = "arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess"
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
resource "aws_iam_role_policy" "migration_handler_access" {
|
|
545
|
+
role = aws_iam_role.migration_handler.name
|
|
546
|
+
|
|
547
|
+
policy = jsonencode({
|
|
548
|
+
Version = "2012-10-17"
|
|
549
|
+
Statement = [
|
|
550
|
+
{
|
|
551
|
+
Effect = "Allow"
|
|
552
|
+
Action = [
|
|
553
|
+
"secretsmanager:GetSecretValue"
|
|
554
|
+
]
|
|
555
|
+
Resource = [module.aurora.secret_arn]
|
|
556
|
+
},
|
|
557
|
+
{
|
|
558
|
+
Effect = "Allow"
|
|
559
|
+
Action = [
|
|
560
|
+
"kms:Decrypt"
|
|
561
|
+
]
|
|
562
|
+
Resource = [module.aurora.kms_key_arn]
|
|
563
|
+
}
|
|
564
|
+
]
|
|
565
|
+
})
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
resource "aws_iam_role" "create_db_user" {
|
|
569
|
+
name = "DbCreateDbUserRole-\${random_string.suffix.result}"
|
|
570
|
+
|
|
571
|
+
assume_role_policy = jsonencode({
|
|
572
|
+
Version = "2012-10-17"
|
|
573
|
+
Statement = [
|
|
574
|
+
{
|
|
575
|
+
Effect = "Allow"
|
|
576
|
+
Principal = {
|
|
577
|
+
Service = "lambda.amazonaws.com"
|
|
578
|
+
}
|
|
579
|
+
Action = "sts:AssumeRole"
|
|
580
|
+
}
|
|
581
|
+
]
|
|
582
|
+
})
|
|
583
|
+
|
|
584
|
+
tags = var.tags
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
resource "aws_iam_role_policy_attachment" "create_db_user_basic_execution" {
|
|
588
|
+
role = aws_iam_role.create_db_user.name
|
|
589
|
+
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
resource "aws_iam_role_policy_attachment" "create_db_user_vpc_access" {
|
|
593
|
+
role = aws_iam_role.create_db_user.name
|
|
594
|
+
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
resource "aws_iam_role_policy_attachment" "create_db_user_xray" {
|
|
598
|
+
role = aws_iam_role.create_db_user.name
|
|
599
|
+
policy_arn = "arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess"
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
resource "aws_iam_role_policy" "create_db_user_secret_access" {
|
|
603
|
+
role = aws_iam_role.create_db_user.name
|
|
604
|
+
|
|
605
|
+
policy = jsonencode({
|
|
606
|
+
Version = "2012-10-17"
|
|
607
|
+
Statement = [
|
|
608
|
+
{
|
|
609
|
+
Effect = "Allow"
|
|
610
|
+
Action = [
|
|
611
|
+
"secretsmanager:GetSecretValue"
|
|
612
|
+
]
|
|
613
|
+
Resource = [module.aurora.secret_arn]
|
|
614
|
+
},
|
|
615
|
+
{
|
|
616
|
+
Effect = "Allow"
|
|
617
|
+
Action = [
|
|
618
|
+
"kms:Decrypt"
|
|
619
|
+
]
|
|
620
|
+
Resource = [module.aurora.kms_key_arn]
|
|
621
|
+
}
|
|
622
|
+
]
|
|
623
|
+
})
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
resource "aws_cloudwatch_log_group" "migration_handler" {
|
|
627
|
+
#checkov:skip=CKV_AWS_158:Using default CloudWatch log encryption
|
|
628
|
+
#checkov:skip=CKV_AWS_338:Log retention set to forever
|
|
629
|
+
#checkov:skip=CKV_AWS_66:Log retention set to forever
|
|
630
|
+
name = "/aws/lambda/\${local.migration_function_name}"
|
|
631
|
+
tags = var.tags
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
resource "aws_cloudwatch_log_group" "create_db_user" {
|
|
635
|
+
#checkov:skip=CKV_AWS_158:Using default CloudWatch log encryption
|
|
636
|
+
#checkov:skip=CKV_AWS_338:Log retention set to forever
|
|
637
|
+
#checkov:skip=CKV_AWS_66:Log retention set to forever
|
|
638
|
+
name = "/aws/lambda/\${local.create_db_user_function_name}"
|
|
639
|
+
tags = var.tags
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
resource "aws_security_group" "migration_handler" {
|
|
643
|
+
name_prefix = "db-migration-"
|
|
644
|
+
description = "Security group for the migration Lambda function"
|
|
645
|
+
vpc_id = var.vpc_id
|
|
646
|
+
tags = var.tags
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
resource "aws_vpc_security_group_egress_rule" "migration_handler_to_database" {
|
|
650
|
+
security_group_id = aws_security_group.migration_handler.id
|
|
651
|
+
referenced_security_group_id = module.aurora.database_security_group_id
|
|
652
|
+
from_port = module.aurora.cluster_port
|
|
653
|
+
to_port = module.aurora.cluster_port
|
|
654
|
+
ip_protocol = "tcp"
|
|
655
|
+
description = "Allow outbound traffic to Aurora on database port"
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
resource "aws_vpc_security_group_egress_rule" "migration_handler_https" {
|
|
659
|
+
security_group_id = aws_security_group.migration_handler.id
|
|
660
|
+
cidr_ipv4 = "0.0.0.0/0"
|
|
661
|
+
from_port = 443
|
|
662
|
+
to_port = 443
|
|
663
|
+
ip_protocol = "tcp"
|
|
664
|
+
description = "Allow outbound HTTPS to AWS service endpoints"
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
resource "aws_security_group" "create_db_user" {
|
|
668
|
+
name_prefix = "db-create-db-user-"
|
|
669
|
+
description = "Security group for the create-db-user Lambda function"
|
|
670
|
+
vpc_id = var.vpc_id
|
|
671
|
+
tags = var.tags
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
resource "aws_vpc_security_group_egress_rule" "create_db_user_to_database" {
|
|
675
|
+
security_group_id = aws_security_group.create_db_user.id
|
|
676
|
+
referenced_security_group_id = module.aurora.database_security_group_id
|
|
677
|
+
from_port = module.aurora.cluster_port
|
|
678
|
+
to_port = module.aurora.cluster_port
|
|
679
|
+
ip_protocol = "tcp"
|
|
680
|
+
description = "Allow outbound traffic to Aurora on database port"
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
resource "aws_vpc_security_group_egress_rule" "create_db_user_https" {
|
|
684
|
+
security_group_id = aws_security_group.create_db_user.id
|
|
685
|
+
cidr_ipv4 = "0.0.0.0/0"
|
|
686
|
+
from_port = 443
|
|
687
|
+
to_port = 443
|
|
688
|
+
ip_protocol = "tcp"
|
|
689
|
+
description = "Allow outbound HTTPS to AWS service endpoints"
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
resource "aws_vpc_security_group_ingress_rule" "migration_handler_to_database" {
|
|
693
|
+
security_group_id = module.aurora.database_security_group_id
|
|
694
|
+
referenced_security_group_id = aws_security_group.migration_handler.id
|
|
695
|
+
from_port = module.aurora.cluster_port
|
|
696
|
+
to_port = module.aurora.cluster_port
|
|
697
|
+
ip_protocol = "tcp"
|
|
698
|
+
description = "Allow inbound traffic from migration Lambda on database port"
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
resource "aws_vpc_security_group_ingress_rule" "create_db_user_to_database" {
|
|
702
|
+
security_group_id = module.aurora.database_security_group_id
|
|
703
|
+
referenced_security_group_id = aws_security_group.create_db_user.id
|
|
704
|
+
from_port = module.aurora.cluster_port
|
|
705
|
+
to_port = module.aurora.cluster_port
|
|
706
|
+
ip_protocol = "tcp"
|
|
707
|
+
description = "Allow inbound traffic from create-db-user Lambda on database port"
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
resource "aws_lambda_function" "create_db_user" {
|
|
711
|
+
#checkov:skip=CKV_AWS_116:Dead Letter Queue not required for the create-db-user handler
|
|
712
|
+
#checkov:skip=CKV_AWS_115:Concurrent execution limit not required for the create-db-user handler
|
|
713
|
+
#checkov:skip=CKV_AWS_173:Lambda environment variables encrypted by managed key
|
|
714
|
+
#checkov:skip=CKV_AWS_272:Code signing not configured as deployment packages are built and deployed within the same pipeline
|
|
715
|
+
package_type = "Image"
|
|
716
|
+
image_uri = "\${aws_ecr_repository.migration_handler.repository_url}:create-db-user-\${local.create_db_user_image_tag}"
|
|
717
|
+
function_name = local.create_db_user_function_name
|
|
718
|
+
role = aws_iam_role.create_db_user.arn
|
|
719
|
+
timeout = 300
|
|
720
|
+
architectures = ["arm64"]
|
|
721
|
+
|
|
722
|
+
image_config {
|
|
723
|
+
command = ["proj_db.create_db_user_handler.handler"]
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
tracing_config {
|
|
727
|
+
mode = "Active"
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
vpc_config {
|
|
731
|
+
subnet_ids = var.lambda_subnet_ids
|
|
732
|
+
security_group_ids = [aws_security_group.create_db_user.id]
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
environment {
|
|
736
|
+
variables = {
|
|
737
|
+
DATABASE_SECRET_ARN = module.aurora.secret_arn
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
tags = var.tags
|
|
742
|
+
|
|
743
|
+
depends_on = [
|
|
744
|
+
null_resource.docker_publish,
|
|
745
|
+
aws_iam_role_policy_attachment.create_db_user_basic_execution,
|
|
746
|
+
aws_iam_role_policy_attachment.create_db_user_vpc_access,
|
|
747
|
+
aws_iam_role_policy_attachment.create_db_user_xray,
|
|
748
|
+
aws_iam_role_policy.create_db_user_secret_access,
|
|
749
|
+
aws_cloudwatch_log_group.create_db_user,
|
|
750
|
+
aws_vpc_security_group_ingress_rule.create_db_user_to_database
|
|
751
|
+
]
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
resource "null_resource" "create_db_user_trigger" {
|
|
755
|
+
triggers = {
|
|
756
|
+
cluster_arn = module.aurora.cluster_arn
|
|
757
|
+
function_name = aws_lambda_function.create_db_user.function_name
|
|
758
|
+
db_user = local.database_runtime_user
|
|
759
|
+
bundle_hash = data.external.create_db_user_docker_digest.result.digest
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
provisioner "local-exec" {
|
|
763
|
+
command = <<-EOT
|
|
764
|
+
output_file=$(mktemp)
|
|
765
|
+
response=$(aws lambda invoke \\
|
|
766
|
+
--region "$AWS_REGION" \\
|
|
767
|
+
--function-name "$FUNCTION_NAME" \\
|
|
768
|
+
--cli-binary-format raw-in-base64-out \\
|
|
769
|
+
--payload "{\\"RequestType\\":\\"Create\\",\\"PhysicalResourceId\\":\\"db-user:$DB_USER\\"}" \\
|
|
770
|
+
"$output_file")
|
|
771
|
+
cat "$output_file"
|
|
772
|
+
echo "$response"
|
|
773
|
+
if echo "$response" | grep -q '"FunctionError"'; then
|
|
774
|
+
rm -f "$output_file"
|
|
775
|
+
exit 1
|
|
776
|
+
fi
|
|
777
|
+
rm -f "$output_file"
|
|
778
|
+
EOT
|
|
779
|
+
environment = {
|
|
780
|
+
AWS_REGION = data.aws_region.current.region
|
|
781
|
+
FUNCTION_NAME = self.triggers.function_name
|
|
782
|
+
DB_USER = self.triggers.db_user
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
depends_on = [aws_lambda_function.create_db_user, module.aurora]
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
resource "aws_lambda_function" "migration_handler" {
|
|
790
|
+
#checkov:skip=CKV_AWS_116:Dead Letter Queue not required for the migration handler
|
|
791
|
+
#checkov:skip=CKV_AWS_115:Concurrent execution limit not required for the migration handler
|
|
792
|
+
#checkov:skip=CKV_AWS_173:Lambda environment variables encrypted by managed key
|
|
793
|
+
#checkov:skip=CKV_AWS_272:Code signing does not apply to container image Lambda functions
|
|
794
|
+
package_type = "Image"
|
|
795
|
+
function_name = local.migration_function_name
|
|
796
|
+
role = aws_iam_role.migration_handler.arn
|
|
797
|
+
image_uri = "\${aws_ecr_repository.migration_handler.repository_url}:\${local.image_tag}"
|
|
798
|
+
memory_size = 1024
|
|
799
|
+
timeout = 300
|
|
800
|
+
architectures = ["arm64"]
|
|
801
|
+
|
|
802
|
+
tracing_config {
|
|
803
|
+
mode = "Active"
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
vpc_config {
|
|
807
|
+
subnet_ids = var.lambda_subnet_ids
|
|
808
|
+
security_group_ids = [aws_security_group.migration_handler.id]
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
environment {
|
|
812
|
+
variables = {
|
|
813
|
+
DATABASE_SECRET_ARN = module.aurora.secret_arn
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
tags = var.tags
|
|
818
|
+
|
|
819
|
+
depends_on = [
|
|
820
|
+
null_resource.docker_publish,
|
|
821
|
+
aws_iam_role_policy_attachment.migration_handler_basic_execution,
|
|
822
|
+
aws_iam_role_policy_attachment.migration_handler_vpc_access,
|
|
823
|
+
aws_iam_role_policy_attachment.migration_handler_xray,
|
|
824
|
+
aws_iam_role_policy.migration_handler_access,
|
|
825
|
+
aws_cloudwatch_log_group.migration_handler,
|
|
826
|
+
aws_vpc_security_group_ingress_rule.migration_handler_to_database
|
|
827
|
+
]
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
resource "null_resource" "migration_trigger" {
|
|
831
|
+
triggers = {
|
|
832
|
+
docker_digest = data.external.docker_digest.result.digest
|
|
833
|
+
cluster_arn = module.aurora.cluster_arn
|
|
834
|
+
database_ready = module.aurora.database_ready
|
|
835
|
+
function_name = aws_lambda_function.migration_handler.function_name
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
provisioner "local-exec" {
|
|
839
|
+
command = <<-EOT
|
|
840
|
+
output_file=$(mktemp)
|
|
841
|
+
response=$(aws lambda invoke \\
|
|
842
|
+
--region "$AWS_REGION" \\
|
|
843
|
+
--function-name "$FUNCTION_NAME" \\
|
|
844
|
+
--cli-binary-format raw-in-base64-out \\
|
|
845
|
+
"$output_file")
|
|
846
|
+
cat "$output_file"
|
|
847
|
+
echo "$response"
|
|
848
|
+
if echo "$response" | grep -q '"FunctionError"'; then
|
|
849
|
+
rm -f "$output_file"
|
|
850
|
+
exit 1
|
|
851
|
+
fi
|
|
852
|
+
rm -f "$output_file"
|
|
853
|
+
EOT
|
|
854
|
+
environment = {
|
|
855
|
+
AWS_REGION = data.aws_region.current.region
|
|
856
|
+
FUNCTION_NAME = self.triggers.function_name
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
depends_on = [
|
|
861
|
+
aws_lambda_function.migration_handler,
|
|
862
|
+
module.aurora,
|
|
863
|
+
null_resource.create_db_user_trigger,
|
|
864
|
+
aws_iam_role_policy.proxy_db_user_connect
|
|
865
|
+
]
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
output "security_group_id" {
|
|
869
|
+
description = "Security group ID to allow inbound connections to the database (proxy SG if RDS Proxy is enabled, otherwise DB SG)."
|
|
870
|
+
value = module.aurora.security_group_id
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
output "database_security_group_id" {
|
|
874
|
+
description = "Security group ID of the Aurora cluster directly, used for direct DB access rules (e.g. when RDS Proxy is disabled)."
|
|
875
|
+
value = module.aurora.database_security_group_id
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
output "cluster_resource_id" {
|
|
879
|
+
description = "Resource ID of the Aurora cluster, used for IAM rds-db:connect policies."
|
|
880
|
+
value = module.aurora.cluster_resource_id
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
output "proxy_resource_id" {
|
|
884
|
+
description = "Resource identifier of the RDS Proxy (prx-XXXX), used for IAM rds-db:connect policies when connecting through the proxy. Null if RDS Proxy is disabled."
|
|
885
|
+
value = module.aurora.proxy_resource_id
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
output "connect_resource_id" {
|
|
889
|
+
description = "Resource ID to use in IAM rds-db:connect policies for the application database user. Resolves to the RDS Proxy resource ID when the proxy is enabled (the default), or the Aurora cluster resource ID when it is disabled — connecting through the proxy and connecting directly to the cluster are different IAM permission boundaries."
|
|
890
|
+
value = module.aurora.connect_resource_id
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
output "kms_key_arn" {
|
|
894
|
+
description = "ARN of the KMS key protecting Aurora and the admin credentials secret, used to grant decrypt access alongside secret_arn."
|
|
895
|
+
value = module.aurora.kms_key_arn
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
output "cluster_arn" {
|
|
899
|
+
description = "ARN of the Aurora cluster."
|
|
900
|
+
value = module.aurora.cluster_arn
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
output "cluster_endpoint" {
|
|
904
|
+
description = "Writer endpoint of the Aurora cluster."
|
|
905
|
+
value = module.aurora.cluster_endpoint
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
output "reader_endpoint" {
|
|
909
|
+
description = "Reader endpoint of the Aurora cluster."
|
|
910
|
+
value = module.aurora.reader_endpoint
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
output "cluster_port" {
|
|
914
|
+
description = "Port exposed by the Aurora cluster."
|
|
915
|
+
value = module.aurora.cluster_port
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
output "secret_arn" {
|
|
919
|
+
description = "ARN of the generated admin credentials secret."
|
|
920
|
+
value = module.aurora.secret_arn
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
output "database_runtime_user" {
|
|
924
|
+
description = "Application database user created for IAM-authenticated access."
|
|
925
|
+
value = local.database_runtime_user
|
|
926
|
+
}
|
|
927
|
+
"
|
|
928
|
+
`;
|
|
929
|
+
|
|
930
|
+
exports[`py#rdb generator > should generate a PostgreSQL SQLModel project with Alembic > packages/db/migrations/env.py 1`] = `
|
|
931
|
+
"import asyncio
|
|
932
|
+
import json
|
|
933
|
+
import os
|
|
934
|
+
from logging.config import fileConfig
|
|
935
|
+
|
|
936
|
+
from alembic import context
|
|
937
|
+
from sqlalchemy import URL
|
|
938
|
+
from sqlalchemy.ext.asyncio import create_async_engine
|
|
939
|
+
from sqlmodel import SQLModel
|
|
940
|
+
|
|
941
|
+
# Import all models to register them in SQLModel.metadata
|
|
942
|
+
from proj_db.models import * # noqa: F401, F403
|
|
943
|
+
|
|
944
|
+
config = context.config
|
|
945
|
+
|
|
946
|
+
if config.config_file_name is not None:
|
|
947
|
+
fileConfig(config.config_file_name)
|
|
948
|
+
|
|
949
|
+
target_metadata = SQLModel.metadata
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
def _get_local_url():
|
|
953
|
+
if os.environ.get("LOCAL_DEV") == "true":
|
|
954
|
+
config_path = os.path.join(os.path.dirname(__file__), "..", "config.json")
|
|
955
|
+
with open(config_path) as f:
|
|
956
|
+
cfg = json.load(f)["localDev"]
|
|
957
|
+
engine = cfg["dbEngine"]
|
|
958
|
+
driver = "mysql+aiomysql" if engine == "mysql" else "postgresql+asyncpg"
|
|
959
|
+
return URL.create(
|
|
960
|
+
driver,
|
|
961
|
+
username=cfg["dbUser"],
|
|
962
|
+
password=cfg["dbPassword"],
|
|
963
|
+
host=cfg["host"],
|
|
964
|
+
port=cfg["port"],
|
|
965
|
+
database=cfg["dbName"],
|
|
966
|
+
)
|
|
967
|
+
|
|
968
|
+
raise RuntimeError("Run alembic via nx run <project>:alembic")
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
# Generates SQL script without a live DB connection (alembic upgrade head --sql)
|
|
972
|
+
def run_migrations_offline() -> None:
|
|
973
|
+
context.configure(
|
|
974
|
+
url=_get_local_url(),
|
|
975
|
+
target_metadata=target_metadata,
|
|
976
|
+
literal_binds=True,
|
|
977
|
+
dialect_opts={"paramstyle": "named"},
|
|
978
|
+
)
|
|
979
|
+
with context.begin_transaction():
|
|
980
|
+
context.run_migrations()
|
|
981
|
+
|
|
982
|
+
|
|
983
|
+
def _run_migrations_sync(sync_conn) -> None:
|
|
984
|
+
context.configure(connection=sync_conn, target_metadata=target_metadata)
|
|
985
|
+
with context.begin_transaction():
|
|
986
|
+
context.run_migrations()
|
|
987
|
+
|
|
988
|
+
|
|
989
|
+
# Runs migrations against a live DB connection
|
|
990
|
+
def run_migrations_online() -> None:
|
|
991
|
+
supplied_connection = config.attributes.get("connection")
|
|
992
|
+
# Connection injected by migration_handler.py (Lambda)
|
|
993
|
+
if supplied_connection is not None:
|
|
994
|
+
_run_migrations_sync(supplied_connection)
|
|
995
|
+
return
|
|
996
|
+
|
|
997
|
+
# Local alembic commands run via nx run <project>:alembic
|
|
998
|
+
async def _run_async() -> None:
|
|
999
|
+
engine = create_async_engine(_get_local_url())
|
|
1000
|
+
async with engine.begin() as conn:
|
|
1001
|
+
await conn.run_sync(_run_migrations_sync)
|
|
1002
|
+
await engine.dispose()
|
|
1003
|
+
|
|
1004
|
+
asyncio.run(_run_async())
|
|
1005
|
+
|
|
1006
|
+
|
|
1007
|
+
if context.is_offline_mode():
|
|
1008
|
+
run_migrations_offline()
|
|
1009
|
+
else:
|
|
1010
|
+
run_migrations_online()
|
|
1011
|
+
"
|
|
1012
|
+
`;
|
|
1013
|
+
|
|
1014
|
+
exports[`py#rdb generator > should generate a PostgreSQL SQLModel project with Alembic > packages/db/migrations/script.py.mako 1`] = `
|
|
1015
|
+
""""\${message}
|
|
1016
|
+
|
|
1017
|
+
Revision ID: \${up_revision}
|
|
1018
|
+
Revises: \${down_revision | comma,n}
|
|
1019
|
+
Create Date: \${create_date}
|
|
1020
|
+
|
|
1021
|
+
"""
|
|
1022
|
+
from typing import Sequence, Union
|
|
1023
|
+
|
|
1024
|
+
from alembic import op
|
|
1025
|
+
import sqlalchemy as sa
|
|
1026
|
+
\${imports if imports else ""}
|
|
1027
|
+
|
|
1028
|
+
# revision identifiers, used by Alembic.
|
|
1029
|
+
revision: str = \${repr(up_revision)}
|
|
1030
|
+
down_revision: Union[str, Sequence[str], None] = \${repr(down_revision)}
|
|
1031
|
+
branch_labels: Union[str, Sequence[str], None] = \${repr(branch_labels)}
|
|
1032
|
+
depends_on: Union[str, Sequence[str], None] = \${repr(depends_on)}
|
|
1033
|
+
|
|
1034
|
+
|
|
1035
|
+
def upgrade() -> None:
|
|
1036
|
+
"""Upgrade schema."""
|
|
1037
|
+
\${upgrades if upgrades else "pass"}
|
|
1038
|
+
|
|
1039
|
+
|
|
1040
|
+
def downgrade() -> None:
|
|
1041
|
+
"""Downgrade schema."""
|
|
1042
|
+
\${downgrades if downgrades else "pass"}
|
|
1043
|
+
"
|
|
1044
|
+
`;
|
|
1045
|
+
|
|
1046
|
+
exports[`py#rdb generator > should generate a PostgreSQL SQLModel project with Alembic > packages/db/migrations/versions/.gitkeep 1`] = `""`;
|
|
1047
|
+
|
|
1048
|
+
exports[`py#rdb generator > should generate a PostgreSQL SQLModel project with Alembic > packages/db/proj_db/__init__.py 1`] = `
|
|
1049
|
+
"from .connection import get_engine, is_local_dev, session_context
|
|
1050
|
+
|
|
1051
|
+
__all__ = ["get_engine", "is_local_dev", "session_context"]
|
|
1052
|
+
"
|
|
1053
|
+
`;
|
|
1054
|
+
|
|
1055
|
+
exports[`py#rdb generator > should generate a PostgreSQL SQLModel project with Alembic > packages/db/proj_db/connection.py 1`] = `
|
|
1056
|
+
"import ssl
|
|
1057
|
+
from collections.abc import AsyncGenerator
|
|
1058
|
+
from contextlib import asynccontextmanager
|
|
1059
|
+
|
|
1060
|
+
import boto3
|
|
1061
|
+
from sqlalchemy import event
|
|
1062
|
+
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
|
|
1063
|
+
|
|
1064
|
+
from .utils import build_database_url, get_database_config, get_local_dev_config, is_local_dev
|
|
1065
|
+
|
|
1066
|
+
# Generated: must match runtimeConfigKey in config.json
|
|
1067
|
+
_runtime_config_key = "Db"
|
|
1068
|
+
|
|
1069
|
+
_engine = None
|
|
1070
|
+
|
|
1071
|
+
|
|
1072
|
+
def get_engine():
|
|
1073
|
+
global _engine
|
|
1074
|
+
if _engine is not None:
|
|
1075
|
+
return _engine
|
|
1076
|
+
if is_local_dev():
|
|
1077
|
+
cfg = get_local_dev_config()
|
|
1078
|
+
url = build_database_url(cfg["dbUser"], cfg["host"], cfg["port"], cfg["dbName"])
|
|
1079
|
+
ssl_args: dict = {}
|
|
1080
|
+
else:
|
|
1081
|
+
config = get_database_config(_runtime_config_key)
|
|
1082
|
+
url = build_database_url(
|
|
1083
|
+
config["dbUser"],
|
|
1084
|
+
config["hostname"],
|
|
1085
|
+
config["port"],
|
|
1086
|
+
config["database"],
|
|
1087
|
+
)
|
|
1088
|
+
ssl_args = {"ssl": ssl.create_default_context()}
|
|
1089
|
+
_engine = create_async_engine(url, connect_args=ssl_args)
|
|
1090
|
+
|
|
1091
|
+
@event.listens_for(_engine.sync_engine, "do_connect")
|
|
1092
|
+
def provide_password(_dialect, _connection_record, _cargs, connection_params):
|
|
1093
|
+
if is_local_dev():
|
|
1094
|
+
connection_params["password"] = get_local_dev_config()["dbPassword"]
|
|
1095
|
+
else:
|
|
1096
|
+
config = get_database_config(_runtime_config_key)
|
|
1097
|
+
connection_params["password"] = boto3.client(
|
|
1098
|
+
"rds",
|
|
1099
|
+
region_name=config["region"],
|
|
1100
|
+
).generate_db_auth_token(
|
|
1101
|
+
DBHostname=config["hostname"],
|
|
1102
|
+
Port=config["port"],
|
|
1103
|
+
DBUsername=config["dbUser"],
|
|
1104
|
+
)
|
|
1105
|
+
|
|
1106
|
+
return _engine
|
|
1107
|
+
|
|
1108
|
+
|
|
1109
|
+
@asynccontextmanager
|
|
1110
|
+
async def session_context() -> AsyncGenerator[AsyncSession]:
|
|
1111
|
+
async with AsyncSession(get_engine()) as session:
|
|
1112
|
+
yield session
|
|
1113
|
+
"
|
|
1114
|
+
`;
|
|
1115
|
+
|
|
1116
|
+
exports[`py#rdb generator > should generate a PostgreSQL SQLModel project with Alembic > packages/db/proj_db/create_db_user_handler.py 1`] = `
|
|
1117
|
+
"import asyncio
|
|
1118
|
+
import secrets
|
|
1119
|
+
import ssl
|
|
1120
|
+
from typing import Any
|
|
1121
|
+
|
|
1122
|
+
import asyncpg
|
|
1123
|
+
|
|
1124
|
+
from .utils import get_database_secret, with_connection_retry
|
|
1125
|
+
|
|
1126
|
+
|
|
1127
|
+
async def _ensure_database_user(db_user: str) -> None:
|
|
1128
|
+
secret = get_database_secret()
|
|
1129
|
+
conn = await asyncpg.connect(
|
|
1130
|
+
host=secret["host"],
|
|
1131
|
+
port=int(secret["port"]),
|
|
1132
|
+
database=secret["dbname"],
|
|
1133
|
+
user=secret["username"],
|
|
1134
|
+
password=secret["password"],
|
|
1135
|
+
ssl=ssl.create_default_context(),
|
|
1136
|
+
)
|
|
1137
|
+
try:
|
|
1138
|
+
quoted = await conn.fetchrow(
|
|
1139
|
+
"SELECT quote_ident($1) AS role_q, quote_ident($2) AS db_q",
|
|
1140
|
+
db_user,
|
|
1141
|
+
secret["dbname"],
|
|
1142
|
+
)
|
|
1143
|
+
role_q, db_q = quoted["role_q"], quoted["db_q"]
|
|
1144
|
+
row = await conn.fetchrow("SELECT 1 FROM pg_roles WHERE rolname = $1", db_user)
|
|
1145
|
+
if row is None:
|
|
1146
|
+
await conn.execute(f"CREATE ROLE {role_q} WITH LOGIN")
|
|
1147
|
+
await conn.execute(f"""
|
|
1148
|
+
ALTER ROLE {role_q} WITH LOGIN;
|
|
1149
|
+
GRANT CONNECT ON DATABASE {db_q} TO {role_q};
|
|
1150
|
+
GRANT USAGE ON SCHEMA public TO {role_q};
|
|
1151
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO {role_q};
|
|
1152
|
+
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO {role_q};
|
|
1153
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
|
1154
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO {role_q};
|
|
1155
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
|
1156
|
+
GRANT USAGE, SELECT ON SEQUENCES TO {role_q};
|
|
1157
|
+
GRANT rds_iam TO {role_q};
|
|
1158
|
+
""")
|
|
1159
|
+
finally:
|
|
1160
|
+
await conn.close()
|
|
1161
|
+
|
|
1162
|
+
|
|
1163
|
+
_PHYSICAL_RESOURCE_ID_PREFIX = "db-user:"
|
|
1164
|
+
|
|
1165
|
+
|
|
1166
|
+
def _resolve_db_user(physical_resource_id: str | None) -> str:
|
|
1167
|
+
if physical_resource_id and physical_resource_id.startswith(_PHYSICAL_RESOURCE_ID_PREFIX):
|
|
1168
|
+
return physical_resource_id[len(_PHYSICAL_RESOURCE_ID_PREFIX) :]
|
|
1169
|
+
return f"db_{secrets.token_hex(8)}"
|
|
1170
|
+
|
|
1171
|
+
|
|
1172
|
+
def handler(event: dict[str, Any], _context: Any) -> dict[str, Any]:
|
|
1173
|
+
db_user = _resolve_db_user(event.get("PhysicalResourceId"))
|
|
1174
|
+
|
|
1175
|
+
if event.get("RequestType") != "Delete":
|
|
1176
|
+
with_connection_retry(lambda: asyncio.run(_ensure_database_user(db_user)))
|
|
1177
|
+
|
|
1178
|
+
return {
|
|
1179
|
+
"PhysicalResourceId": f"{_PHYSICAL_RESOURCE_ID_PREFIX}{db_user}",
|
|
1180
|
+
"Data": {"dbUser": db_user},
|
|
1181
|
+
}
|
|
1182
|
+
"
|
|
1183
|
+
`;
|
|
1184
|
+
|
|
1185
|
+
exports[`py#rdb generator > should generate a PostgreSQL SQLModel project with Alembic > packages/db/proj_db/migration_handler.py 1`] = `
|
|
1186
|
+
"import asyncio
|
|
1187
|
+
import ssl
|
|
1188
|
+
|
|
1189
|
+
from alembic import command
|
|
1190
|
+
from alembic.config import Config
|
|
1191
|
+
from sqlalchemy.ext.asyncio import create_async_engine
|
|
1192
|
+
from sqlalchemy.pool import NullPool
|
|
1193
|
+
|
|
1194
|
+
from .utils import build_database_url, get_database_secret, with_connection_retry
|
|
1195
|
+
|
|
1196
|
+
|
|
1197
|
+
def _apply_migrations(sync_conn, alembic_cfg: Config) -> None:
|
|
1198
|
+
alembic_cfg.attributes["connection"] = sync_conn
|
|
1199
|
+
command.upgrade(alembic_cfg, "head")
|
|
1200
|
+
|
|
1201
|
+
|
|
1202
|
+
async def _run_migrations() -> None:
|
|
1203
|
+
secret = get_database_secret()
|
|
1204
|
+
database_url = build_database_url(
|
|
1205
|
+
secret["username"],
|
|
1206
|
+
secret["host"],
|
|
1207
|
+
secret["port"],
|
|
1208
|
+
secret["dbname"],
|
|
1209
|
+
password=secret["password"],
|
|
1210
|
+
)
|
|
1211
|
+
alembic_cfg = Config("alembic.ini")
|
|
1212
|
+
engine = create_async_engine(
|
|
1213
|
+
database_url,
|
|
1214
|
+
poolclass=NullPool,
|
|
1215
|
+
connect_args={"ssl": ssl.create_default_context()},
|
|
1216
|
+
)
|
|
1217
|
+
try:
|
|
1218
|
+
async with engine.begin() as conn:
|
|
1219
|
+
await conn.run_sync(lambda c: _apply_migrations(c, alembic_cfg))
|
|
1220
|
+
finally:
|
|
1221
|
+
await engine.dispose()
|
|
1222
|
+
|
|
1223
|
+
|
|
1224
|
+
def handler(_event, _context):
|
|
1225
|
+
with_connection_retry(lambda: asyncio.run(_run_migrations()))
|
|
1226
|
+
"
|
|
1227
|
+
`;
|
|
1228
|
+
|
|
1229
|
+
exports[`py#rdb generator > should generate a PostgreSQL SQLModel project with Alembic > packages/db/proj_db/models/__init__.py 1`] = `
|
|
1230
|
+
"from .example import ExampleModel
|
|
1231
|
+
|
|
1232
|
+
__all__ = ["ExampleModel"]
|
|
1233
|
+
"
|
|
1234
|
+
`;
|
|
1235
|
+
|
|
1236
|
+
exports[`py#rdb generator > should generate a PostgreSQL SQLModel project with Alembic > packages/db/proj_db/models/example.py 1`] = `
|
|
1237
|
+
"from sqlalchemy import Column, String
|
|
1238
|
+
from sqlmodel import Field, SQLModel
|
|
1239
|
+
|
|
1240
|
+
|
|
1241
|
+
class ExampleModel(SQLModel, table=True):
|
|
1242
|
+
id: int | None = Field(default=None, primary_key=True)
|
|
1243
|
+
name: str = Field(sa_column=Column(String(255), nullable=False))
|
|
1244
|
+
description: str | None = Field(default=None, sa_column=Column(String(255), nullable=True))
|
|
1245
|
+
"
|
|
1246
|
+
`;
|
|
1247
|
+
|
|
1248
|
+
exports[`py#rdb generator > should generate a PostgreSQL SQLModel project with Alembic > packages/db/proj_db/utils.py 1`] = `
|
|
1249
|
+
"import json
|
|
1250
|
+
import os
|
|
1251
|
+
import time
|
|
1252
|
+
from collections.abc import Callable
|
|
1253
|
+
from typing import Any
|
|
1254
|
+
|
|
1255
|
+
import boto3
|
|
1256
|
+
from aws_lambda_powertools.utilities.parameters import AppConfigProvider
|
|
1257
|
+
from sqlalchemy import URL
|
|
1258
|
+
|
|
1259
|
+
DatabaseConfig = dict[str, Any]
|
|
1260
|
+
DatabaseSecret = dict[str, Any]
|
|
1261
|
+
|
|
1262
|
+
|
|
1263
|
+
def build_database_url(
|
|
1264
|
+
username: str,
|
|
1265
|
+
host: str,
|
|
1266
|
+
port: int,
|
|
1267
|
+
database: str,
|
|
1268
|
+
password: str | None = None,
|
|
1269
|
+
) -> URL:
|
|
1270
|
+
return URL.create(
|
|
1271
|
+
drivername="postgresql+asyncpg",
|
|
1272
|
+
username=username,
|
|
1273
|
+
password=password,
|
|
1274
|
+
host=host,
|
|
1275
|
+
port=port,
|
|
1276
|
+
database=database,
|
|
1277
|
+
)
|
|
1278
|
+
|
|
1279
|
+
|
|
1280
|
+
def is_local_dev() -> bool:
|
|
1281
|
+
return os.environ.get("LOCAL_DEV") == "true"
|
|
1282
|
+
|
|
1283
|
+
|
|
1284
|
+
def get_local_dev_config() -> dict:
|
|
1285
|
+
config_path = os.path.join(os.path.dirname(__file__), "..", "config.json")
|
|
1286
|
+
with open(config_path) as f:
|
|
1287
|
+
return json.load(f)["localDev"]
|
|
1288
|
+
|
|
1289
|
+
|
|
1290
|
+
def get_database_secret() -> DatabaseSecret:
|
|
1291
|
+
secret_arn = os.environ.get("DATABASE_SECRET_ARN")
|
|
1292
|
+
if not secret_arn:
|
|
1293
|
+
raise ValueError("Missing required environment variable DATABASE_SECRET_ARN.")
|
|
1294
|
+
client = boto3.client("secretsmanager")
|
|
1295
|
+
response = client.get_secret_value(SecretId=secret_arn)
|
|
1296
|
+
return json.loads(response["SecretString"])
|
|
1297
|
+
|
|
1298
|
+
|
|
1299
|
+
_database_config: dict[str, DatabaseConfig] = {}
|
|
1300
|
+
|
|
1301
|
+
|
|
1302
|
+
def get_database_config(runtime_config_key: str) -> DatabaseConfig:
|
|
1303
|
+
if runtime_config_key not in _database_config:
|
|
1304
|
+
app_id = os.environ.get("RUNTIME_CONFIG_APP_ID")
|
|
1305
|
+
if not app_id:
|
|
1306
|
+
raise ValueError("Missing required environment variable RUNTIME_CONFIG_APP_ID.")
|
|
1307
|
+
provider = AppConfigProvider(application=app_id, environment="default")
|
|
1308
|
+
config = provider.get("database", transform="json")
|
|
1309
|
+
if not isinstance(config, dict):
|
|
1310
|
+
raise ValueError("Unexpected RuntimeConfig format: expected JSON object.")
|
|
1311
|
+
db_config = config.get(runtime_config_key)
|
|
1312
|
+
if not db_config:
|
|
1313
|
+
raise ValueError(f"RuntimeConfig is missing database.{runtime_config_key}.")
|
|
1314
|
+
_database_config[runtime_config_key] = db_config
|
|
1315
|
+
return _database_config[runtime_config_key]
|
|
1316
|
+
|
|
1317
|
+
|
|
1318
|
+
_TRANSIENT_ERROR_PATTERNS = [
|
|
1319
|
+
"timeout",
|
|
1320
|
+
"connection refused",
|
|
1321
|
+
"could not connect",
|
|
1322
|
+
"connection reset",
|
|
1323
|
+
"connection timed out",
|
|
1324
|
+
"operationalerror",
|
|
1325
|
+
"password authentication failed",
|
|
1326
|
+
"access denied",
|
|
1327
|
+
"temporary failure",
|
|
1328
|
+
]
|
|
1329
|
+
|
|
1330
|
+
|
|
1331
|
+
def is_transient_connection_error(error: Exception) -> bool:
|
|
1332
|
+
error_str = str(error).lower()
|
|
1333
|
+
return any(p in error_str for p in _TRANSIENT_ERROR_PATTERNS)
|
|
1334
|
+
|
|
1335
|
+
|
|
1336
|
+
def with_connection_retry[T](
|
|
1337
|
+
fn: Callable[[], T],
|
|
1338
|
+
max_attempts: int = 6,
|
|
1339
|
+
delay_seconds: float = 10.0,
|
|
1340
|
+
) -> T:
|
|
1341
|
+
for attempt in range(1, max_attempts + 1):
|
|
1342
|
+
try:
|
|
1343
|
+
return fn()
|
|
1344
|
+
except Exception as e:
|
|
1345
|
+
if attempt == max_attempts or not is_transient_connection_error(e):
|
|
1346
|
+
raise
|
|
1347
|
+
wait = delay_seconds * attempt
|
|
1348
|
+
print(f"Transient connection error (attempt {attempt}/{max_attempts}), retrying in {wait:.0f}s: {e}")
|
|
1349
|
+
time.sleep(wait)
|
|
1350
|
+
raise RuntimeError("unreachable")
|
|
1351
|
+
"
|
|
1352
|
+
`;
|
|
1353
|
+
|
|
1354
|
+
exports[`py#rdb generator > should generate a PostgreSQL SQLModel project with Alembic 1`] = `
|
|
1355
|
+
"[alembic]
|
|
1356
|
+
script_location = migrations
|
|
1357
|
+
file_template = %%(year)d%%(month).2d%%(day).2d_%%(hour).2d%%(minute).2d_%%(rev)s_%%(slug)s
|
|
1358
|
+
prepend_sys_path = .
|
|
1359
|
+
|
|
1360
|
+
[loggers]
|
|
1361
|
+
keys = root,sqlalchemy,alembic
|
|
1362
|
+
|
|
1363
|
+
[handlers]
|
|
1364
|
+
keys = console
|
|
1365
|
+
|
|
1366
|
+
[formatters]
|
|
1367
|
+
keys = generic
|
|
1368
|
+
|
|
1369
|
+
[logger_root]
|
|
1370
|
+
level = WARN
|
|
1371
|
+
handlers = console
|
|
1372
|
+
qualname =
|
|
1373
|
+
|
|
1374
|
+
[logger_sqlalchemy]
|
|
1375
|
+
level = WARN
|
|
1376
|
+
handlers =
|
|
1377
|
+
qualname = sqlalchemy.engine
|
|
1378
|
+
|
|
1379
|
+
[logger_alembic]
|
|
1380
|
+
level = INFO
|
|
1381
|
+
handlers =
|
|
1382
|
+
qualname = alembic
|
|
1383
|
+
|
|
1384
|
+
[handler_console]
|
|
1385
|
+
class = StreamHandler
|
|
1386
|
+
args = (sys.stderr,)
|
|
1387
|
+
level = NOTSET
|
|
1388
|
+
formatter = generic
|
|
1389
|
+
|
|
1390
|
+
[formatter_generic]
|
|
1391
|
+
format = %(levelname)-5.5s [%(name)s] %(message)s
|
|
1392
|
+
datefmt = %H:%M:%S
|
|
1393
|
+
"
|
|
1394
|
+
`;
|
|
1395
|
+
|
|
1396
|
+
exports[`py#rdb generator > should generate a PostgreSQL SQLModel project with Alembic 2`] = `
|
|
1397
|
+
"FROM public.ecr.aws/lambda/python:3.14
|
|
1398
|
+
|
|
1399
|
+
WORKDIR \${LAMBDA_TASK_ROOT}
|
|
1400
|
+
|
|
1401
|
+
COPY . .
|
|
1402
|
+
|
|
1403
|
+
ADD https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem /etc/pki/ca-trust/source/anchors/global-bundle.pem
|
|
1404
|
+
RUN update-ca-trust
|
|
1405
|
+
|
|
1406
|
+
CMD ["proj_db.migration_handler.handler"]
|
|
1407
|
+
"
|
|
1408
|
+
`;
|
|
1409
|
+
|
|
1410
|
+
exports[`py#rdb generator > should generate a PostgreSQL SQLModel project with Alembic 3`] = `
|
|
1411
|
+
"FROM public.ecr.aws/lambda/python:3.14
|
|
1412
|
+
|
|
1413
|
+
WORKDIR \${LAMBDA_TASK_ROOT}
|
|
1414
|
+
|
|
1415
|
+
COPY . .
|
|
1416
|
+
|
|
1417
|
+
ADD https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem /etc/pki/ca-trust/source/anchors/global-bundle.pem
|
|
1418
|
+
RUN update-ca-trust
|
|
1419
|
+
|
|
1420
|
+
CMD ["proj_db.create_db_user_handler.handler"]
|
|
1421
|
+
"
|
|
1422
|
+
`;
|
|
1423
|
+
|
|
1424
|
+
exports[`py#rdb generator > should generate a PostgreSQL SQLModel project with Alembic 4`] = `
|
|
1425
|
+
"{
|
|
1426
|
+
"runtimeConfigKey": "Db",
|
|
1427
|
+
"localDev": {
|
|
1428
|
+
"containerEngine": "docker",
|
|
1429
|
+
"containerName": "proj-database_name",
|
|
1430
|
+
"image": "public.ecr.aws/docker/library/postgres:17.7",
|
|
1431
|
+
"port": 5432,
|
|
1432
|
+
"host": "localhost",
|
|
1433
|
+
"dbName": "database_name",
|
|
1434
|
+
"dbUser": "dbadmin",
|
|
1435
|
+
"dbPassword": "password",
|
|
1436
|
+
"dbEngine": "postgres"
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
"
|
|
1440
|
+
`;
|
|
1441
|
+
|
|
1442
|
+
exports[`py#rdb generator > should generate a PostgreSQL SQLModel project with Alembic 5`] = `
|
|
1443
|
+
"[tool.coverage.run]
|
|
1444
|
+
branch = true
|
|
1445
|
+
source = [ "proj_db" ]
|
|
1446
|
+
|
|
1447
|
+
[tool.coverage.report]
|
|
1448
|
+
exclude_lines = [ "if TYPE_CHECKING:" ]
|
|
1449
|
+
show_missing = true
|
|
1450
|
+
|
|
1451
|
+
[tool.pytest.ini_options]
|
|
1452
|
+
addopts = """
|
|
1453
|
+
--cov
|
|
1454
|
+
--cov-report html:'../../coverage/packages/db/html'
|
|
1455
|
+
--cov-report xml:'../../coverage/packages/db/coverage.xml'
|
|
1456
|
+
--html='../../reports/packages/db/unittests/html/index.html'
|
|
1457
|
+
--junitxml='../../reports/packages/db/unittests/junit.xml'
|
|
1458
|
+
"""
|
|
1459
|
+
|
|
1460
|
+
[tool.hatch.build.targets.wheel]
|
|
1461
|
+
packages = [ "proj_db" ]
|
|
1462
|
+
|
|
1463
|
+
[tool.hatch.metadata]
|
|
1464
|
+
allow-direct-references = true
|
|
1465
|
+
|
|
1466
|
+
[tool.ruff]
|
|
1467
|
+
exclude = [ ".ruff_cache", ".svn", ".tox", ".venv", "dist" ]
|
|
1468
|
+
line-length = 120
|
|
1469
|
+
indent-width = 4
|
|
1470
|
+
|
|
1471
|
+
[tool.ruff.lint]
|
|
1472
|
+
select = [ "E", "F", "UP", "B", "SIM", "I" ]
|
|
1473
|
+
ignore = [ ]
|
|
1474
|
+
fixable = [ "ALL" ]
|
|
1475
|
+
unfixable = [ ]
|
|
1476
|
+
|
|
1477
|
+
[project]
|
|
1478
|
+
name = "proj-db"
|
|
1479
|
+
version = "1.0.0"
|
|
1480
|
+
description = "Automatically generated by Nx."
|
|
1481
|
+
requires-python = ">=3.14"
|
|
1482
|
+
readme = "README.md"
|
|
1483
|
+
dependencies = [
|
|
1484
|
+
"sqlmodel==0.0.38",
|
|
1485
|
+
"alembic==1.18.4",
|
|
1486
|
+
"asyncpg==0.31.0",
|
|
1487
|
+
"boto3==1.43.46",
|
|
1488
|
+
"aws-lambda-powertools==3.31.0"
|
|
1489
|
+
]
|
|
1490
|
+
|
|
1491
|
+
[build-system]
|
|
1492
|
+
requires = [ "hatchling" ]
|
|
1493
|
+
build-backend = "hatchling.build"
|
|
1494
|
+
"
|
|
1495
|
+
`;
|
|
1496
|
+
|
|
1497
|
+
exports[`py#rdb generator > should generate a PostgreSQL SQLModel project with Alembic 6`] = `
|
|
1498
|
+
"import * as path from 'path';
|
|
1499
|
+
import * as url from 'url';
|
|
1500
|
+
import { readFileSync } from 'fs';
|
|
1501
|
+
import { Construct } from 'constructs';
|
|
1502
|
+
import { Platform } from 'aws-cdk-lib/aws-ecr-assets';
|
|
1503
|
+
import {
|
|
1504
|
+
DockerImageCode,
|
|
1505
|
+
DockerImageFunction,
|
|
1506
|
+
Function,
|
|
1507
|
+
FunctionOptions,
|
|
1508
|
+
} from 'aws-cdk-lib/aws-lambda';
|
|
1509
|
+
import {
|
|
1510
|
+
AuroraDatabase,
|
|
1511
|
+
AuroraDatabaseEngines,
|
|
1512
|
+
AuroraDatabaseProps,
|
|
1513
|
+
} from '../../core/rdb/aurora.js';
|
|
1514
|
+
import { findWorkspaceRoot } from '../../core/workspace.js';
|
|
1515
|
+
|
|
1516
|
+
const { runtimeConfigKey } = JSON.parse(
|
|
1517
|
+
readFileSync(
|
|
1518
|
+
path.join(
|
|
1519
|
+
findWorkspaceRoot(url.fileURLToPath(new URL(import.meta.url))),
|
|
1520
|
+
'packages/db/config.json',
|
|
1521
|
+
),
|
|
1522
|
+
'utf-8',
|
|
1523
|
+
),
|
|
1524
|
+
) as { runtimeConfigKey: string };
|
|
1525
|
+
|
|
1526
|
+
const migrationBundleDir = path.join(
|
|
1527
|
+
findWorkspaceRoot(url.fileURLToPath(new URL(import.meta.url))),
|
|
1528
|
+
'dist/packages/db/docker/migration',
|
|
1529
|
+
);
|
|
1530
|
+
|
|
1531
|
+
const createDbUserBundleDir = path.join(
|
|
1532
|
+
findWorkspaceRoot(url.fileURLToPath(new URL(import.meta.url))),
|
|
1533
|
+
'dist/packages/db/docker/create-db-user',
|
|
1534
|
+
);
|
|
1535
|
+
|
|
1536
|
+
export type DbProps = Omit<
|
|
1537
|
+
AuroraDatabaseProps,
|
|
1538
|
+
'databaseName' | 'adminUser' | 'runtimeConfigKey' | 'engine'
|
|
1539
|
+
>;
|
|
1540
|
+
|
|
1541
|
+
/**
|
|
1542
|
+
* CDK construct that provisions an Aurora Serverless v2 cluster.
|
|
1543
|
+
*/
|
|
1544
|
+
export class Db extends AuroraDatabase {
|
|
1545
|
+
constructor(scope: Construct, id: string, props: DbProps) {
|
|
1546
|
+
super(scope, id, {
|
|
1547
|
+
...props,
|
|
1548
|
+
databaseName: 'database_name',
|
|
1549
|
+
adminUser: 'databaseUser',
|
|
1550
|
+
runtimeConfigKey,
|
|
1551
|
+
engine: AuroraDatabaseEngines.postgres({}),
|
|
1552
|
+
});
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1555
|
+
protected override createDbUserHandler(baseProps: FunctionOptions): Function {
|
|
1556
|
+
return new DockerImageFunction(this, 'CreateDbUserHandler', {
|
|
1557
|
+
...baseProps,
|
|
1558
|
+
code: DockerImageCode.fromImageAsset(createDbUserBundleDir, {
|
|
1559
|
+
platform: Platform.LINUX_ARM64,
|
|
1560
|
+
}),
|
|
1561
|
+
});
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1564
|
+
protected override createMigrationHandler(
|
|
1565
|
+
baseProps: FunctionOptions,
|
|
1566
|
+
): Function {
|
|
1567
|
+
return new DockerImageFunction(this, 'MigrationHandler', {
|
|
1568
|
+
...baseProps,
|
|
1569
|
+
code: DockerImageCode.fromImageAsset(migrationBundleDir, {
|
|
1570
|
+
platform: Platform.LINUX_ARM64,
|
|
1571
|
+
}),
|
|
1572
|
+
});
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
"
|
|
1576
|
+
`;
|
|
1577
|
+
|
|
1578
|
+
exports[`py#rdb generator > should generate a PostgreSQL SQLModel project with Alembic 7`] = `
|
|
1579
|
+
"import asyncio
|
|
1580
|
+
import secrets
|
|
1581
|
+
import ssl
|
|
1582
|
+
from typing import Any
|
|
1583
|
+
|
|
1584
|
+
import asyncpg
|
|
1585
|
+
|
|
1586
|
+
from .utils import get_database_secret, with_connection_retry
|
|
1587
|
+
|
|
1588
|
+
|
|
1589
|
+
async def _ensure_database_user(db_user: str) -> None:
|
|
1590
|
+
secret = get_database_secret()
|
|
1591
|
+
conn = await asyncpg.connect(
|
|
1592
|
+
host=secret["host"],
|
|
1593
|
+
port=int(secret["port"]),
|
|
1594
|
+
database=secret["dbname"],
|
|
1595
|
+
user=secret["username"],
|
|
1596
|
+
password=secret["password"],
|
|
1597
|
+
ssl=ssl.create_default_context(),
|
|
1598
|
+
)
|
|
1599
|
+
try:
|
|
1600
|
+
quoted = await conn.fetchrow(
|
|
1601
|
+
"SELECT quote_ident($1) AS role_q, quote_ident($2) AS db_q",
|
|
1602
|
+
db_user,
|
|
1603
|
+
secret["dbname"],
|
|
1604
|
+
)
|
|
1605
|
+
role_q, db_q = quoted["role_q"], quoted["db_q"]
|
|
1606
|
+
row = await conn.fetchrow("SELECT 1 FROM pg_roles WHERE rolname = $1", db_user)
|
|
1607
|
+
if row is None:
|
|
1608
|
+
await conn.execute(f"CREATE ROLE {role_q} WITH LOGIN")
|
|
1609
|
+
await conn.execute(f"""
|
|
1610
|
+
ALTER ROLE {role_q} WITH LOGIN;
|
|
1611
|
+
GRANT CONNECT ON DATABASE {db_q} TO {role_q};
|
|
1612
|
+
GRANT USAGE ON SCHEMA public TO {role_q};
|
|
1613
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO {role_q};
|
|
1614
|
+
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO {role_q};
|
|
1615
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
|
1616
|
+
GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO {role_q};
|
|
1617
|
+
ALTER DEFAULT PRIVILEGES IN SCHEMA public
|
|
1618
|
+
GRANT USAGE, SELECT ON SEQUENCES TO {role_q};
|
|
1619
|
+
GRANT rds_iam TO {role_q};
|
|
1620
|
+
""")
|
|
1621
|
+
finally:
|
|
1622
|
+
await conn.close()
|
|
1623
|
+
|
|
1624
|
+
|
|
1625
|
+
_PHYSICAL_RESOURCE_ID_PREFIX = "db-user:"
|
|
1626
|
+
|
|
1627
|
+
|
|
1628
|
+
def _resolve_db_user(physical_resource_id: str | None) -> str:
|
|
1629
|
+
if physical_resource_id and physical_resource_id.startswith(_PHYSICAL_RESOURCE_ID_PREFIX):
|
|
1630
|
+
return physical_resource_id[len(_PHYSICAL_RESOURCE_ID_PREFIX) :]
|
|
1631
|
+
return f"db_{secrets.token_hex(8)}"
|
|
1632
|
+
|
|
1633
|
+
|
|
1634
|
+
def handler(event: dict[str, Any], _context: Any) -> dict[str, Any]:
|
|
1635
|
+
db_user = _resolve_db_user(event.get("PhysicalResourceId"))
|
|
1636
|
+
|
|
1637
|
+
if event.get("RequestType") != "Delete":
|
|
1638
|
+
with_connection_retry(lambda: asyncio.run(_ensure_database_user(db_user)))
|
|
1639
|
+
|
|
1640
|
+
return {
|
|
1641
|
+
"PhysicalResourceId": f"{_PHYSICAL_RESOURCE_ID_PREFIX}{db_user}",
|
|
1642
|
+
"Data": {"dbUser": db_user},
|
|
1643
|
+
}
|
|
1644
|
+
"
|
|
1645
|
+
`;
|
|
1646
|
+
|
|
1647
|
+
exports[`py#rdb generator > should generate a PostgreSQL SQLModel project with Alembic 8`] = `
|
|
1648
|
+
"import { CfnOutput, Duration, RemovalPolicy, Stack } from 'aws-cdk-lib';
|
|
1649
|
+
import { CustomResource } from 'aws-cdk-lib';
|
|
1650
|
+
import { IConnectable, IVpc, Port, SubnetType } from 'aws-cdk-lib/aws-ec2';
|
|
1651
|
+
import { IGrantable, Role, ServicePrincipal } from 'aws-cdk-lib/aws-iam';
|
|
1652
|
+
import { Key } from 'aws-cdk-lib/aws-kms';
|
|
1653
|
+
import {
|
|
1654
|
+
Architecture,
|
|
1655
|
+
Function,
|
|
1656
|
+
FunctionOptions,
|
|
1657
|
+
Tracing,
|
|
1658
|
+
} from 'aws-cdk-lib/aws-lambda';
|
|
1659
|
+
import {
|
|
1660
|
+
AuroraMysqlEngineVersion,
|
|
1661
|
+
AuroraPostgresEngineVersion,
|
|
1662
|
+
ClusterInstance,
|
|
1663
|
+
Credentials,
|
|
1664
|
+
DatabaseCluster,
|
|
1665
|
+
DatabaseClusterEngine,
|
|
1666
|
+
DatabaseClusterProps,
|
|
1667
|
+
DatabaseProxy,
|
|
1668
|
+
DefaultAuthScheme,
|
|
1669
|
+
IClusterEngine,
|
|
1670
|
+
} from 'aws-cdk-lib/aws-rds';
|
|
1671
|
+
import { Provider } from 'aws-cdk-lib/custom-resources';
|
|
1672
|
+
import { Trigger } from 'aws-cdk-lib/triggers';
|
|
1673
|
+
import { Construct } from 'constructs';
|
|
1674
|
+
import { RuntimeConfig } from '../runtime-config.js';
|
|
1675
|
+
|
|
1676
|
+
export type AuroraDatabaseEngineVersion =
|
|
1677
|
+
| AuroraMysqlEngineVersion
|
|
1678
|
+
| AuroraPostgresEngineVersion;
|
|
1679
|
+
|
|
1680
|
+
export interface AuroraDatabaseEngine {
|
|
1681
|
+
/**
|
|
1682
|
+
* Discriminant identifying the engine type.
|
|
1683
|
+
*/
|
|
1684
|
+
readonly type: 'mysql' | 'postgres';
|
|
1685
|
+
|
|
1686
|
+
/**
|
|
1687
|
+
* Default Aurora engine version used when one is not explicitly provided.
|
|
1688
|
+
*/
|
|
1689
|
+
readonly defaultVersion: AuroraDatabaseEngineVersion;
|
|
1690
|
+
|
|
1691
|
+
/**
|
|
1692
|
+
* Builds the CDK cluster engine for the provided engine version.
|
|
1693
|
+
*/
|
|
1694
|
+
clusterEngine(version: AuroraDatabaseEngineVersion): IClusterEngine;
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
export class AuroraDatabaseEngines {
|
|
1698
|
+
public static mysql({
|
|
1699
|
+
defaultVersion = AuroraMysqlEngineVersion.VER_3_12_0,
|
|
1700
|
+
}: {
|
|
1701
|
+
defaultVersion?: AuroraMysqlEngineVersion;
|
|
1702
|
+
}): AuroraDatabaseEngine {
|
|
1703
|
+
return {
|
|
1704
|
+
type: 'mysql',
|
|
1705
|
+
defaultVersion,
|
|
1706
|
+
clusterEngine: (version) =>
|
|
1707
|
+
DatabaseClusterEngine.auroraMysql({
|
|
1708
|
+
version: version as AuroraMysqlEngineVersion,
|
|
1709
|
+
}),
|
|
1710
|
+
};
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
public static postgres({
|
|
1714
|
+
defaultVersion = AuroraPostgresEngineVersion.VER_17_7,
|
|
1715
|
+
}: {
|
|
1716
|
+
defaultVersion?: AuroraPostgresEngineVersion;
|
|
1717
|
+
}): AuroraDatabaseEngine {
|
|
1718
|
+
return {
|
|
1719
|
+
type: 'postgres',
|
|
1720
|
+
defaultVersion,
|
|
1721
|
+
clusterEngine: (version) =>
|
|
1722
|
+
DatabaseClusterEngine.auroraPostgres({
|
|
1723
|
+
version: version as AuroraPostgresEngineVersion,
|
|
1724
|
+
}),
|
|
1725
|
+
};
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
type _AuroraDatabaseProps = Omit<
|
|
1730
|
+
DatabaseClusterProps,
|
|
1731
|
+
| 'credentials'
|
|
1732
|
+
| 'defaultDatabaseName'
|
|
1733
|
+
| 'engine'
|
|
1734
|
+
| 'iamAuthentication'
|
|
1735
|
+
| 'instanceProps'
|
|
1736
|
+
| 'writer'
|
|
1737
|
+
>;
|
|
1738
|
+
|
|
1739
|
+
export interface AuroraDatabaseProps extends _AuroraDatabaseProps {
|
|
1740
|
+
/**
|
|
1741
|
+
* VPC where the Aurora cluster will be deployed.
|
|
1742
|
+
*/
|
|
1743
|
+
readonly vpc: IVpc;
|
|
1744
|
+
|
|
1745
|
+
/**
|
|
1746
|
+
* Aurora engine preset used to build the cluster.
|
|
1747
|
+
*/
|
|
1748
|
+
readonly engine: AuroraDatabaseEngine;
|
|
1749
|
+
|
|
1750
|
+
/**
|
|
1751
|
+
* The engine version to deploy.
|
|
1752
|
+
*
|
|
1753
|
+
* @default - engine.defaultVersion
|
|
1754
|
+
*/
|
|
1755
|
+
readonly engineVersion?: AuroraDatabaseEngineVersion;
|
|
1756
|
+
|
|
1757
|
+
/**
|
|
1758
|
+
* Admin username used when generating credentials.
|
|
1759
|
+
*/
|
|
1760
|
+
readonly adminUser: string;
|
|
1761
|
+
|
|
1762
|
+
/**
|
|
1763
|
+
* The initial database created in the cluster.
|
|
1764
|
+
*/
|
|
1765
|
+
readonly databaseName: string;
|
|
1766
|
+
|
|
1767
|
+
/**
|
|
1768
|
+
* RuntimeConfig key used under the \`database\` namespace.
|
|
1769
|
+
*/
|
|
1770
|
+
readonly runtimeConfigKey: string;
|
|
1771
|
+
|
|
1772
|
+
/**
|
|
1773
|
+
* Writer instance for the Aurora cluster.
|
|
1774
|
+
*/
|
|
1775
|
+
readonly writer?: DatabaseClusterProps['writer'];
|
|
1776
|
+
|
|
1777
|
+
/**
|
|
1778
|
+
* Whether to provision an RDS Proxy in front of the Aurora cluster.
|
|
1779
|
+
*
|
|
1780
|
+
* @default true
|
|
1781
|
+
*/
|
|
1782
|
+
readonly enableRdsProxy?: boolean;
|
|
1783
|
+
|
|
1784
|
+
/**
|
|
1785
|
+
* Whether to enable automatic credential rotation for the admin secret.
|
|
1786
|
+
*
|
|
1787
|
+
* @default true
|
|
1788
|
+
*/
|
|
1789
|
+
readonly enableCredentialRotation?: boolean;
|
|
1790
|
+
|
|
1791
|
+
/**
|
|
1792
|
+
* Whether to enable deletion protection on the Aurora cluster.
|
|
1793
|
+
*
|
|
1794
|
+
* @default true
|
|
1795
|
+
*/
|
|
1796
|
+
readonly deletionProtection?: boolean;
|
|
1797
|
+
|
|
1798
|
+
/**
|
|
1799
|
+
* Removal policy applied to the Aurora cluster.
|
|
1800
|
+
*
|
|
1801
|
+
* @default RemovalPolicy.RETAIN
|
|
1802
|
+
*/
|
|
1803
|
+
readonly removalPolicy?: RemovalPolicy;
|
|
1804
|
+
|
|
1805
|
+
/**
|
|
1806
|
+
* Whether to enable automatic key rotation on the KMS key used to encrypt the Aurora cluster and its credentials secret.
|
|
1807
|
+
*
|
|
1808
|
+
* @default true
|
|
1809
|
+
*/
|
|
1810
|
+
readonly enableKeyRotation?: boolean;
|
|
1811
|
+
|
|
1812
|
+
/**
|
|
1813
|
+
* Whether to export Aurora engine logs to CloudWatch Logs.
|
|
1814
|
+
* See https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/USER_LogAccess.html
|
|
1815
|
+
*
|
|
1816
|
+
* @default false
|
|
1817
|
+
*/
|
|
1818
|
+
readonly enableCloudwatchLogs?: boolean;
|
|
1819
|
+
|
|
1820
|
+
/**
|
|
1821
|
+
* Whether to enable Performance Insights on the Aurora writer instance.
|
|
1822
|
+
*
|
|
1823
|
+
* @default true
|
|
1824
|
+
*/
|
|
1825
|
+
readonly enablePerformanceInsights?: boolean;
|
|
1826
|
+
}
|
|
1827
|
+
|
|
1828
|
+
/**
|
|
1829
|
+
* Reusable Aurora database construct that supports different Aurora engines
|
|
1830
|
+
* through typed engine presets.
|
|
1831
|
+
*/
|
|
1832
|
+
export abstract class AuroraDatabase extends Construct {
|
|
1833
|
+
public readonly cluster: DatabaseCluster;
|
|
1834
|
+
public readonly proxy?: DatabaseProxy;
|
|
1835
|
+
private readonly adminUser: string;
|
|
1836
|
+
private readonly dbUser: string;
|
|
1837
|
+
|
|
1838
|
+
constructor(
|
|
1839
|
+
scope: Construct,
|
|
1840
|
+
id: string,
|
|
1841
|
+
{
|
|
1842
|
+
vpc,
|
|
1843
|
+
adminUser,
|
|
1844
|
+
databaseName,
|
|
1845
|
+
runtimeConfigKey,
|
|
1846
|
+
vpcSubnets,
|
|
1847
|
+
writer,
|
|
1848
|
+
enableRdsProxy = true,
|
|
1849
|
+
enableCredentialRotation = true,
|
|
1850
|
+
deletionProtection = true,
|
|
1851
|
+
removalPolicy = RemovalPolicy.RETAIN,
|
|
1852
|
+
enableKeyRotation = true,
|
|
1853
|
+
enableCloudwatchLogs = false,
|
|
1854
|
+
enablePerformanceInsights = true,
|
|
1855
|
+
engine,
|
|
1856
|
+
engineVersion,
|
|
1857
|
+
...clusterProps
|
|
1858
|
+
}: AuroraDatabaseProps,
|
|
1859
|
+
) {
|
|
1860
|
+
super(scope, id);
|
|
1861
|
+
|
|
1862
|
+
this.adminUser = adminUser;
|
|
1863
|
+
|
|
1864
|
+
const key = new Key(this, 'EncryptionKey', { enableKeyRotation });
|
|
1865
|
+
this.cluster = new DatabaseCluster(this, 'DatabaseCluster', {
|
|
1866
|
+
...clusterProps,
|
|
1867
|
+
vpc,
|
|
1868
|
+
vpcSubnets,
|
|
1869
|
+
engine: engine.clusterEngine(engineVersion ?? engine.defaultVersion),
|
|
1870
|
+
writer:
|
|
1871
|
+
writer ??
|
|
1872
|
+
ClusterInstance.serverlessV2('writer', {
|
|
1873
|
+
enablePerformanceInsights,
|
|
1874
|
+
performanceInsightEncryptionKey: enablePerformanceInsights
|
|
1875
|
+
? key
|
|
1876
|
+
: undefined,
|
|
1877
|
+
}),
|
|
1878
|
+
credentials: Credentials.fromGeneratedSecret(adminUser, {
|
|
1879
|
+
encryptionKey: key,
|
|
1880
|
+
}),
|
|
1881
|
+
iamAuthentication: true,
|
|
1882
|
+
monitoringInterval: Duration.seconds(5),
|
|
1883
|
+
cloudwatchLogsExports: enableCloudwatchLogs
|
|
1884
|
+
? engine.type === 'mysql'
|
|
1885
|
+
? ['audit', 'error', 'general', 'slowquery']
|
|
1886
|
+
: ['postgresql']
|
|
1887
|
+
: undefined,
|
|
1888
|
+
defaultDatabaseName: databaseName,
|
|
1889
|
+
storageEncrypted: true,
|
|
1890
|
+
storageEncryptionKey: key,
|
|
1891
|
+
deletionProtection,
|
|
1892
|
+
removalPolicy,
|
|
1893
|
+
});
|
|
1894
|
+
|
|
1895
|
+
if (enableCredentialRotation) {
|
|
1896
|
+
this.cluster.addRotationSingleUser({
|
|
1897
|
+
automaticallyAfter: Duration.days(30),
|
|
1898
|
+
vpcSubnets: {
|
|
1899
|
+
subnetType: SubnetType.PRIVATE_WITH_EGRESS,
|
|
1900
|
+
},
|
|
1901
|
+
});
|
|
1902
|
+
}
|
|
1903
|
+
|
|
1904
|
+
const proxyRole = enableRdsProxy
|
|
1905
|
+
? new Role(this, 'DatabaseProxyRole', {
|
|
1906
|
+
assumedBy: new ServicePrincipal('rds.amazonaws.com'),
|
|
1907
|
+
})
|
|
1908
|
+
: undefined;
|
|
1909
|
+
|
|
1910
|
+
if (enableRdsProxy) {
|
|
1911
|
+
this.proxy = this.cluster.addProxy('DatabaseProxy', {
|
|
1912
|
+
vpc,
|
|
1913
|
+
vpcSubnets,
|
|
1914
|
+
defaultAuthScheme: DefaultAuthScheme.IAM_AUTH,
|
|
1915
|
+
role: proxyRole,
|
|
1916
|
+
});
|
|
1917
|
+
}
|
|
1918
|
+
|
|
1919
|
+
const databaseHostname =
|
|
1920
|
+
this.proxy?.endpoint ?? this.cluster.clusterEndpoint.hostname;
|
|
1921
|
+
const databasePort = this.cluster.clusterEndpoint.port;
|
|
1922
|
+
|
|
1923
|
+
const commonProps: FunctionOptions = {
|
|
1924
|
+
vpc,
|
|
1925
|
+
timeout: Duration.minutes(5),
|
|
1926
|
+
tracing: Tracing.ACTIVE,
|
|
1927
|
+
architecture: Architecture.ARM_64,
|
|
1928
|
+
};
|
|
1929
|
+
|
|
1930
|
+
const createDbUserHandler = this.createDbUserHandler({
|
|
1931
|
+
...commonProps,
|
|
1932
|
+
vpcSubnets: {
|
|
1933
|
+
subnetType: SubnetType.PRIVATE_WITH_EGRESS,
|
|
1934
|
+
},
|
|
1935
|
+
});
|
|
1936
|
+
createDbUserHandler.addEnvironment(
|
|
1937
|
+
'DATABASE_SECRET_ARN',
|
|
1938
|
+
this.cluster.secret!.secretArn,
|
|
1939
|
+
);
|
|
1940
|
+
this.cluster.connections.allowDefaultPortFrom(
|
|
1941
|
+
createDbUserHandler,
|
|
1942
|
+
'Allow the create-db-user handler to connect to the database',
|
|
1943
|
+
);
|
|
1944
|
+
this.grantSecretRead(createDbUserHandler);
|
|
1945
|
+
|
|
1946
|
+
const createDbUserProvider = new Provider(this, 'CreateDbUserProvider', {
|
|
1947
|
+
onEventHandler: createDbUserHandler,
|
|
1948
|
+
});
|
|
1949
|
+
|
|
1950
|
+
const createDbUserResource = new CustomResource(
|
|
1951
|
+
this,
|
|
1952
|
+
'CreateDbUserResource',
|
|
1953
|
+
{
|
|
1954
|
+
serviceToken: createDbUserProvider.serviceToken,
|
|
1955
|
+
properties: {
|
|
1956
|
+
clusterIdentifier: this.cluster.clusterIdentifier,
|
|
1957
|
+
},
|
|
1958
|
+
},
|
|
1959
|
+
);
|
|
1960
|
+
createDbUserResource.node.addDependency(this.cluster);
|
|
1961
|
+
this.dbUser = createDbUserResource.getAttString('dbUser');
|
|
1962
|
+
if (this.proxy && proxyRole) {
|
|
1963
|
+
this.cluster.grantConnect(proxyRole, this.dbUser);
|
|
1964
|
+
}
|
|
1965
|
+
|
|
1966
|
+
const rc = RuntimeConfig.ensure(this);
|
|
1967
|
+
rc.set('database', runtimeConfigKey, {
|
|
1968
|
+
hostname: databaseHostname,
|
|
1969
|
+
port: databasePort,
|
|
1970
|
+
database: databaseName,
|
|
1971
|
+
adminUser: this.adminUser,
|
|
1972
|
+
dbUser: this.dbUser,
|
|
1973
|
+
region: Stack.of(this).region,
|
|
1974
|
+
});
|
|
1975
|
+
|
|
1976
|
+
const migrationHandler = this.createMigrationHandler({
|
|
1977
|
+
...commonProps,
|
|
1978
|
+
memorySize: 1024,
|
|
1979
|
+
});
|
|
1980
|
+
migrationHandler.addEnvironment(
|
|
1981
|
+
'DATABASE_SECRET_ARN',
|
|
1982
|
+
this.cluster.secret!.secretArn,
|
|
1983
|
+
);
|
|
1984
|
+
this.cluster.connections.allowDefaultPortFrom(migrationHandler);
|
|
1985
|
+
this.grantSecretRead(migrationHandler);
|
|
1986
|
+
|
|
1987
|
+
const migrationTrigger = new Trigger(this, 'MigrationTrigger', {
|
|
1988
|
+
handler: migrationHandler,
|
|
1989
|
+
});
|
|
1990
|
+
migrationTrigger.node.addDependency(createDbUserResource);
|
|
1991
|
+
|
|
1992
|
+
new CfnOutput(this, 'ClusterEndpoint', {
|
|
1993
|
+
value: this.cluster.clusterEndpoint.hostname,
|
|
1994
|
+
});
|
|
1995
|
+
|
|
1996
|
+
if (this.proxy?.endpoint) {
|
|
1997
|
+
new CfnOutput(this, 'ProxyEndpoint', {
|
|
1998
|
+
value: this.proxy?.endpoint,
|
|
1999
|
+
});
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
|
|
2003
|
+
/**
|
|
2004
|
+
* Creates the Lambda handler used to create or reconcile the application database user.
|
|
2005
|
+
*/
|
|
2006
|
+
protected abstract createDbUserHandler(baseProps: FunctionOptions): Function;
|
|
2007
|
+
|
|
2008
|
+
/**
|
|
2009
|
+
* Creates the Lambda handler used to run database migrations.
|
|
2010
|
+
*/
|
|
2011
|
+
protected abstract createMigrationHandler(
|
|
2012
|
+
baseProps: FunctionOptions,
|
|
2013
|
+
): Function;
|
|
2014
|
+
|
|
2015
|
+
public allowDefaultPortFrom(other: IConnectable, description?: string): void {
|
|
2016
|
+
if (this.proxy) {
|
|
2017
|
+
this.proxy.connections.allowFrom(
|
|
2018
|
+
other,
|
|
2019
|
+
Port.tcp(this.cluster.clusterEndpoint.port),
|
|
2020
|
+
description,
|
|
2021
|
+
);
|
|
2022
|
+
} else {
|
|
2023
|
+
this.cluster.connections.allowDefaultPortFrom(other, description);
|
|
2024
|
+
}
|
|
2025
|
+
}
|
|
2026
|
+
|
|
2027
|
+
public grantSecretRead(grantee: IGrantable) {
|
|
2028
|
+
return this.cluster.secret!.grantRead(grantee);
|
|
2029
|
+
}
|
|
2030
|
+
|
|
2031
|
+
public grantConnect(grantee: IGrantable) {
|
|
2032
|
+
return this.proxy
|
|
2033
|
+
? this.proxy.grantConnect(grantee, this.dbUser)
|
|
2034
|
+
: this.cluster.grantConnect(grantee, this.dbUser);
|
|
2035
|
+
}
|
|
2036
|
+
}
|
|
2037
|
+
"
|
|
2038
|
+
`;
|