@aws/nx-plugin 1.0.0-rc.85 → 1.0.0-rc.87
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/migrations.json +11 -1
- package/package.json +1 -1
- package/src/infra/app/__snapshots__/generator.spec.ts.snap +34 -8
- package/src/infra/app/files/app/README.md.template +14 -0
- package/src/infra/app/generator.js +15 -2
- package/src/infra/app/generator.js.map +1 -1
- package/src/mcp-server/tools/general-guidance.js +1 -1
- package/src/mcp-server/tools/general-guidance.js.map +1 -1
- package/src/migrations/latest/add-destroy-sandbox-target/metadata.json +3 -0
- package/src/migrations/latest/add-destroy-sandbox-target/migration.d.ts +6 -0
- package/src/migrations/latest/add-destroy-sandbox-target/migration.js +150 -0
- package/src/migrations/latest/add-destroy-sandbox-target/migration.js.map +1 -0
- package/src/migrations/latest/terraform-rdb-proxy-iam-connect-grant/__snapshots__/migration.spec.ts.snap +23 -0
- package/src/migrations/latest/terraform-rdb-proxy-iam-connect-grant/metadata.json +3 -0
- package/src/migrations/latest/terraform-rdb-proxy-iam-connect-grant/migration.d.ts +6 -0
- package/src/migrations/latest/terraform-rdb-proxy-iam-connect-grant/migration.js +88 -0
- package/src/migrations/latest/terraform-rdb-proxy-iam-connect-grant/migration.js.map +1 -0
- package/src/open-api/ts-client/generator.js.map +1 -1
- package/src/open-api/ts-hooks/generator.spec.tsx +1 -1
- package/src/py/project/generator.js +5 -5
- package/src/py/project/generator.js.map +1 -1
- package/src/py/rdb/__snapshots__/generator.spec.ts.snap +21 -9
- package/src/py/rdb/files/__name__/utils.py.template +17 -1
- package/src/smithy/ts/api/__snapshots__/generator.spec.ts.snap +8 -8
- package/src/trpc/backend/__snapshots__/generator.spec.ts.snap +16 -16
- package/src/ts/dcr-proxy/__snapshots__/generator.spec.ts.snap +3 -3
- package/src/ts/lambda-function/__snapshots__/generator.spec.ts.snap +3 -3
- package/src/ts/rdb/__snapshots__/generator.spec.ts.snap +132 -261
- package/src/ts/rdb/files/src/utils.ts.template +28 -1
- package/src/ts/react-website/cognito-auth/generator.js +1 -1
- package/src/ts/react-website/cognito-auth/generator.js.map +1 -1
- package/src/ts/react-website/runtime-config/generator.js +1 -1
- package/src/ts/react-website/runtime-config/generator.js.map +1 -1
- package/src/utils/agent-core-constructs/agent-core-constructs.js +3 -2
- package/src/utils/agent-core-constructs/agent-core-constructs.js.map +1 -1
- package/src/utils/agent-core-constructs/files/cdk/core/agentcore-gateway/agentcore-gateway.ts.template +1 -1
- package/src/utils/api-constructs/api-constructs.js +7 -4
- package/src/utils/api-constructs/api-constructs.js.map +1 -1
- package/src/utils/api-constructs/files/cdk/app/apis/http/__apiNameKebabCase__.ts.template +4 -4
- package/src/utils/api-constructs/files/cdk/app/apis/rest/__apiNameKebabCase__.ts.template +4 -4
- package/src/utils/api-constructs/files/cdk/core/api/rest/api-gateway-account.ts.template +1 -1
- package/src/utils/api-constructs/files/terraform/app/apis/http/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +4 -4
- package/src/utils/api-constructs/files/terraform/app/apis/rest/__apiNameKebabCase__/__apiNameKebabCase__.tf.template +4 -4
- package/src/utils/ast.d.ts +13 -0
- package/src/utils/ast.js +36 -0
- package/src/utils/ast.js.map +1 -1
- package/src/utils/bundle/bundle.js +5 -2
- package/src/utils/bundle/bundle.js.map +1 -1
- package/src/utils/dcr-proxy-constructs/dcr-proxy-constructs.js +5 -3
- package/src/utils/dcr-proxy-constructs/dcr-proxy-constructs.js.map +1 -1
- package/src/utils/dcr-proxy-constructs/files/cdk/app/dcr-proxies/__nameKebabCase__/__nameKebabCase__.ts.template +1 -1
- package/src/utils/dcr-proxy-constructs/files/terraform/app/dcr-proxies/__nameKebabCase__/__nameKebabCase__.tf.template +2 -2
- package/src/utils/files/common/scripts/src/infra/stage-credentials/cdk-command.ts.template +7 -3
- package/src/utils/function-constructs/function-constructs.js +3 -3
- package/src/utils/function-constructs/function-constructs.js.map +1 -1
- package/src/utils/lambda-runtime-resolution.d.ts +74 -0
- package/src/utils/lambda-runtime-resolution.js +97 -0
- package/src/utils/lambda-runtime-resolution.js.map +1 -0
- package/src/utils/rdb-constructs/files/cdk/app/dbs/__nameKebabCase__.ts.template +3 -3
- package/src/utils/rdb-constructs/files/terraform/app/dbs/__nameKebabCase__/__nameKebabCase__.tf.template +10 -29
- package/src/utils/rdb-constructs/files/terraform/core/rdb/aurora/aurora.tf.template +28 -116
- package/src/utils/rdb-constructs/rdb-constructs.js +5 -3
- package/src/utils/rdb-constructs/rdb-constructs.js.map +1 -1
- package/src/utils/version-upgrade-migration/sync-lambda-runtimes.d.ts +28 -0
- package/src/utils/version-upgrade-migration/sync-lambda-runtimes.js +148 -0
- package/src/utils/version-upgrade-migration/sync-lambda-runtimes.js.map +1 -0
- package/src/utils/version-upgrade-migration/sync-python-language-version.d.ts +31 -0
- package/src/utils/version-upgrade-migration/sync-python-language-version.js +110 -0
- package/src/utils/version-upgrade-migration/sync-python-language-version.js.map +1 -0
- package/src/utils/version-upgrade-migration/sync-vended-versions.js +36 -7
- package/src/utils/version-upgrade-migration/sync-vended-versions.js.map +1 -1
- package/src/utils/versions.d.ts +60 -0
- package/src/utils/versions.js +51 -0
- package/src/utils/versions.js.map +1 -1
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/ import { LAMBDA_RUNTIME_VERSIONS } from "./versions.js";
|
|
5
|
+
/**
|
|
6
|
+
* Resolution of the Lambda runtimes and the CPython patch the version update
|
|
7
|
+
* pins.
|
|
8
|
+
*
|
|
9
|
+
* Lives here rather than beside the script so it is covered by the plugin's test
|
|
10
|
+
* suite; the script supplies the runtime list and the uv output.
|
|
11
|
+
*/ /** Compare two dotted numeric versions (`24`, `3.14`) ascending. */ export const compareRuntimeVersions = (a, b)=>{
|
|
12
|
+
const left = a.split('.').map(Number);
|
|
13
|
+
const right = b.split('.').map(Number);
|
|
14
|
+
for(let i = 0; i < Math.max(left.length, right.length); i++){
|
|
15
|
+
const diff = (left[i] ?? 0) - (right[i] ?? 0);
|
|
16
|
+
if (diff !== 0) {
|
|
17
|
+
return diff;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return 0;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* The version a managed runtime identifier names, or undefined for one that isn't
|
|
24
|
+
* a versioned `nodejs`/`python` runtime.
|
|
25
|
+
*
|
|
26
|
+
* `nodejs24.x` -> `24`, `python3.14` -> `3.14`. The bare `nodejs` and
|
|
27
|
+
* `nodejs4.3-edge` style identifiers carry no comparable version and are skipped.
|
|
28
|
+
*/ export const runtimeIdentifierVersion = (identifier)=>{
|
|
29
|
+
const node = /^nodejs(\d+)\.x$/.exec(identifier);
|
|
30
|
+
if (node) {
|
|
31
|
+
return {
|
|
32
|
+
language: 'node',
|
|
33
|
+
version: node[1]
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
const python = /^python(\d+\.\d+)$/.exec(identifier);
|
|
37
|
+
return python ? {
|
|
38
|
+
language: 'python',
|
|
39
|
+
version: python[1]
|
|
40
|
+
} : undefined;
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* The latest managed runtime for each language in {@link LAMBDA_RUNTIME_VERSIONS},
|
|
44
|
+
* from the runtime identifiers `aws-cdk-lib` publishes.
|
|
45
|
+
*
|
|
46
|
+
* `Runtime.ALL` is a curated list of the runtimes CDK supports, so a runtime still
|
|
47
|
+
* in public preview does not appear — which is what makes it a usable source for a
|
|
48
|
+
* generally-available runtime. Never moves a runtime backwards: a pin ahead of
|
|
49
|
+
* what CDK offers stays.
|
|
50
|
+
*
|
|
51
|
+
* A language the list says nothing about keeps its current pin and is reported
|
|
52
|
+
* through `unresolved`, so a failure costs this bump alone rather than the whole
|
|
53
|
+
* version update.
|
|
54
|
+
*/ export const resolveLambdaRuntimes = (identifiers)=>{
|
|
55
|
+
const unresolved = [];
|
|
56
|
+
const versions = Object.fromEntries(Object.keys(LAMBDA_RUNTIME_VERSIONS).map((language)=>{
|
|
57
|
+
const current = LAMBDA_RUNTIME_VERSIONS[language];
|
|
58
|
+
const available = identifiers.map(runtimeIdentifierVersion).filter((parsed)=>parsed?.language === language).map((parsed)=>parsed.version);
|
|
59
|
+
if (available.length === 0) {
|
|
60
|
+
unresolved.push({
|
|
61
|
+
language,
|
|
62
|
+
kept: current,
|
|
63
|
+
reason: 'no-runtimes-listed'
|
|
64
|
+
});
|
|
65
|
+
return [
|
|
66
|
+
language,
|
|
67
|
+
current
|
|
68
|
+
];
|
|
69
|
+
}
|
|
70
|
+
const latest = available.reduce((best, version)=>compareRuntimeVersions(version, best) > 0 ? version : best);
|
|
71
|
+
return [
|
|
72
|
+
language,
|
|
73
|
+
compareRuntimeVersions(latest, current) > 0 ? latest : current
|
|
74
|
+
];
|
|
75
|
+
}));
|
|
76
|
+
return {
|
|
77
|
+
versions,
|
|
78
|
+
unresolved
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
/** The warning a language's unresolved runtime reports. */ export const unresolvedRuntimeWarning = (entry)=>`Found no ${entry.language} runtime in the aws-cdk-lib runtime list, so it keeps its pinned runtime (${entry.kept})`;
|
|
82
|
+
/**
|
|
83
|
+
* The latest CPython patch uv can install for a `major.minor`, or undefined when
|
|
84
|
+
* it lists none.
|
|
85
|
+
*
|
|
86
|
+
* Lambda names only `major.minor` and patches the interpreter itself, but uv pins
|
|
87
|
+
* an exact `major.minor.patch`, so the patch is resolved from what uv can actually
|
|
88
|
+
* install for the runtime's minor. Pre-releases and the free-threaded variant are
|
|
89
|
+
* excluded: a generated project needs the default build of a final release.
|
|
90
|
+
*/ export const resolveLatestPythonPatch = (entries, minor = LAMBDA_RUNTIME_VERSIONS.python)=>{
|
|
91
|
+
const [major, wanted] = minor.split('.').map(Number);
|
|
92
|
+
const patches = entries.filter((entry)=>entry.implementation === 'cpython' && entry.variant !== 'freethreaded' && entry.version_parts.major === major && entry.version_parts.minor === wanted && // A final release only; `3.15.0rc1` carries a suffix.
|
|
93
|
+
/^\d+\.\d+\.\d+$/.test(entry.version)).map((entry)=>entry.version_parts.patch);
|
|
94
|
+
return patches.length > 0 ? String(Math.max(...patches)) : undefined;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
//# sourceMappingURL=lambda-runtime-resolution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../packages/nx-plugin/src/utils/lambda-runtime-resolution.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport { type ILambdaRuntime, LAMBDA_RUNTIME_VERSIONS } from './versions.js';\n\n/**\n * Resolution of the Lambda runtimes and the CPython patch the version update\n * pins.\n *\n * Lives here rather than beside the script so it is covered by the plugin's test\n * suite; the script supplies the runtime list and the uv output.\n */\n\n/** Compare two dotted numeric versions (`24`, `3.14`) ascending. */\nexport const compareRuntimeVersions = (a: string, b: string): number => {\n const left = a.split('.').map(Number);\n const right = b.split('.').map(Number);\n for (let i = 0; i < Math.max(left.length, right.length); i++) {\n const diff = (left[i] ?? 0) - (right[i] ?? 0);\n if (diff !== 0) {\n return diff;\n }\n }\n return 0;\n};\n\n/**\n * The version a managed runtime identifier names, or undefined for one that isn't\n * a versioned `nodejs`/`python` runtime.\n *\n * `nodejs24.x` -> `24`, `python3.14` -> `3.14`. The bare `nodejs` and\n * `nodejs4.3-edge` style identifiers carry no comparable version and are skipped.\n */\nexport const runtimeIdentifierVersion = (\n identifier: string,\n): { language: ILambdaRuntime; version: string } | undefined => {\n const node = /^nodejs(\\d+)\\.x$/.exec(identifier);\n if (node) {\n return { language: 'node', version: node[1] };\n }\n const python = /^python(\\d+\\.\\d+)$/.exec(identifier);\n return python ? { language: 'python', version: python[1] } : undefined;\n};\n\n/** Why a language's runtime could not be resolved. */\nexport type UnresolvedReason = 'no-runtimes-listed';\n\nexport interface RuntimeResolution {\n /** Runtime version per language, holding the current pin where unresolved. */\n readonly versions: Record<string, string>;\n /** Languages left on their current pin, and why. */\n readonly unresolved: {\n readonly language: string;\n readonly kept: string;\n readonly reason: UnresolvedReason;\n }[];\n}\n\n/**\n * The latest managed runtime for each language in {@link LAMBDA_RUNTIME_VERSIONS},\n * from the runtime identifiers `aws-cdk-lib` publishes.\n *\n * `Runtime.ALL` is a curated list of the runtimes CDK supports, so a runtime still\n * in public preview does not appear — which is what makes it a usable source for a\n * generally-available runtime. Never moves a runtime backwards: a pin ahead of\n * what CDK offers stays.\n *\n * A language the list says nothing about keeps its current pin and is reported\n * through `unresolved`, so a failure costs this bump alone rather than the whole\n * version update.\n */\nexport const resolveLambdaRuntimes = (\n identifiers: readonly string[],\n): RuntimeResolution => {\n const unresolved: RuntimeResolution['unresolved'][number][] = [];\n\n const versions = Object.fromEntries(\n (Object.keys(LAMBDA_RUNTIME_VERSIONS) as ILambdaRuntime[]).map(\n (language) => {\n const current = LAMBDA_RUNTIME_VERSIONS[language];\n const available = identifiers\n .map(runtimeIdentifierVersion)\n .filter((parsed) => parsed?.language === language)\n .map((parsed) => parsed!.version);\n\n if (available.length === 0) {\n unresolved.push({\n language,\n kept: current,\n reason: 'no-runtimes-listed',\n });\n return [language, current];\n }\n\n const latest = available.reduce((best, version) =>\n compareRuntimeVersions(version, best) > 0 ? version : best,\n );\n\n return [\n language,\n compareRuntimeVersions(latest, current) > 0 ? latest : current,\n ];\n },\n ),\n );\n\n return { versions, unresolved };\n};\n\n/** The warning a language's unresolved runtime reports. */\nexport const unresolvedRuntimeWarning = (\n entry: RuntimeResolution['unresolved'][number],\n): string =>\n `Found no ${entry.language} runtime in the aws-cdk-lib runtime list, so it keeps its pinned runtime (${entry.kept})`;\n\n/** A CPython build as `uv python list --output-format json` reports it. */\nexport interface UvPythonEntry {\n readonly version: string;\n readonly version_parts: {\n readonly major: number;\n readonly minor: number;\n readonly patch: number;\n };\n readonly implementation: string;\n readonly variant?: string;\n}\n\n/**\n * The latest CPython patch uv can install for a `major.minor`, or undefined when\n * it lists none.\n *\n * Lambda names only `major.minor` and patches the interpreter itself, but uv pins\n * an exact `major.minor.patch`, so the patch is resolved from what uv can actually\n * install for the runtime's minor. Pre-releases and the free-threaded variant are\n * excluded: a generated project needs the default build of a final release.\n */\nexport const resolveLatestPythonPatch = (\n entries: readonly UvPythonEntry[],\n minor: string = LAMBDA_RUNTIME_VERSIONS.python,\n): string | undefined => {\n const [major, wanted] = minor.split('.').map(Number);\n const patches = entries\n .filter(\n (entry) =>\n entry.implementation === 'cpython' &&\n entry.variant !== 'freethreaded' &&\n entry.version_parts.major === major &&\n entry.version_parts.minor === wanted &&\n // A final release only; `3.15.0rc1` carries a suffix.\n /^\\d+\\.\\d+\\.\\d+$/.test(entry.version),\n )\n .map((entry) => entry.version_parts.patch);\n\n return patches.length > 0 ? String(Math.max(...patches)) : undefined;\n};\n"],"names":["LAMBDA_RUNTIME_VERSIONS","compareRuntimeVersions","a","b","left","split","map","Number","right","i","Math","max","length","diff","runtimeIdentifierVersion","identifier","node","exec","language","version","python","undefined","resolveLambdaRuntimes","identifiers","unresolved","versions","Object","fromEntries","keys","current","available","filter","parsed","push","kept","reason","latest","reduce","best","unresolvedRuntimeWarning","entry","resolveLatestPythonPatch","entries","minor","major","wanted","patches","implementation","variant","version_parts","test","patch","String"],"mappings":"AAAA;;;CAGC,GACD,SAA8BA,uBAAuB,QAAQ,gBAAgB;AAE7E;;;;;;CAMC,GAED,kEAAkE,GAClE,OAAO,MAAMC,yBAAyB,CAACC,GAAWC;IAChD,MAAMC,OAAOF,EAAEG,KAAK,CAAC,KAAKC,GAAG,CAACC;IAC9B,MAAMC,QAAQL,EAAEE,KAAK,CAAC,KAAKC,GAAG,CAACC;IAC/B,IAAK,IAAIE,IAAI,GAAGA,IAAIC,KAAKC,GAAG,CAACP,KAAKQ,MAAM,EAAEJ,MAAMI,MAAM,GAAGH,IAAK;QAC5D,MAAMI,OAAO,AAACT,CAAAA,IAAI,CAACK,EAAE,IAAI,CAAA,IAAMD,CAAAA,KAAK,CAACC,EAAE,IAAI,CAAA;QAC3C,IAAII,SAAS,GAAG;YACd,OAAOA;QACT;IACF;IACA,OAAO;AACT,EAAE;AAEF;;;;;;CAMC,GACD,OAAO,MAAMC,2BAA2B,CACtCC;IAEA,MAAMC,OAAO,mBAAmBC,IAAI,CAACF;IACrC,IAAIC,MAAM;QACR,OAAO;YAAEE,UAAU;YAAQC,SAASH,IAAI,CAAC,EAAE;QAAC;IAC9C;IACA,MAAMI,SAAS,qBAAqBH,IAAI,CAACF;IACzC,OAAOK,SAAS;QAAEF,UAAU;QAAUC,SAASC,MAAM,CAAC,EAAE;IAAC,IAAIC;AAC/D,EAAE;AAgBF;;;;;;;;;;;;CAYC,GACD,OAAO,MAAMC,wBAAwB,CACnCC;IAEA,MAAMC,aAAwD,EAAE;IAEhE,MAAMC,WAAWC,OAAOC,WAAW,CACjC,AAACD,OAAOE,IAAI,CAAC5B,yBAA8CM,GAAG,CAC5D,CAACY;QACC,MAAMW,UAAU7B,uBAAuB,CAACkB,SAAS;QACjD,MAAMY,YAAYP,YACfjB,GAAG,CAACQ,0BACJiB,MAAM,CAAC,CAACC,SAAWA,QAAQd,aAAaA,UACxCZ,GAAG,CAAC,CAAC0B,SAAWA,OAAQb,OAAO;QAElC,IAAIW,UAAUlB,MAAM,KAAK,GAAG;YAC1BY,WAAWS,IAAI,CAAC;gBACdf;gBACAgB,MAAML;gBACNM,QAAQ;YACV;YACA,OAAO;gBAACjB;gBAAUW;aAAQ;QAC5B;QAEA,MAAMO,SAASN,UAAUO,MAAM,CAAC,CAACC,MAAMnB,UACrClB,uBAAuBkB,SAASmB,QAAQ,IAAInB,UAAUmB;QAGxD,OAAO;YACLpB;YACAjB,uBAAuBmC,QAAQP,WAAW,IAAIO,SAASP;SACxD;IACH;IAIJ,OAAO;QAAEJ;QAAUD;IAAW;AAChC,EAAE;AAEF,yDAAyD,GACzD,OAAO,MAAMe,2BAA2B,CACtCC,QAEA,CAAC,SAAS,EAAEA,MAAMtB,QAAQ,CAAC,0EAA0E,EAAEsB,MAAMN,IAAI,CAAC,CAAC,CAAC,CAAC;AAcvH;;;;;;;;CAQC,GACD,OAAO,MAAMO,2BAA2B,CACtCC,SACAC,QAAgB3C,wBAAwBoB,MAAM;IAE9C,MAAM,CAACwB,OAAOC,OAAO,GAAGF,MAAMtC,KAAK,CAAC,KAAKC,GAAG,CAACC;IAC7C,MAAMuC,UAAUJ,QACbX,MAAM,CACL,CAACS,QACCA,MAAMO,cAAc,KAAK,aACzBP,MAAMQ,OAAO,KAAK,kBAClBR,MAAMS,aAAa,CAACL,KAAK,KAAKA,SAC9BJ,MAAMS,aAAa,CAACN,KAAK,KAAKE,UAC9B,sDAAsD;QACtD,kBAAkBK,IAAI,CAACV,MAAMrB,OAAO,GAEvCb,GAAG,CAAC,CAACkC,QAAUA,MAAMS,aAAa,CAACE,KAAK;IAE3C,OAAOL,QAAQlC,MAAM,GAAG,IAAIwC,OAAO1C,KAAKC,GAAG,IAAImC,YAAYzB;AAC7D,EAAE"}
|
|
@@ -4,14 +4,14 @@ import { readFileSync } from 'fs';
|
|
|
4
4
|
import { Construct } from 'constructs';
|
|
5
5
|
import { Platform } from 'aws-cdk-lib/aws-ecr-assets';
|
|
6
6
|
import {
|
|
7
|
-
<%_ if (framework
|
|
7
|
+
<%_ if (framework === 'prisma') { _%>
|
|
8
8
|
Code,
|
|
9
9
|
<%_ } _%>
|
|
10
10
|
DockerImageCode,
|
|
11
11
|
DockerImageFunction,
|
|
12
12
|
Function,
|
|
13
13
|
FunctionOptions,
|
|
14
|
-
<%_ if (framework
|
|
14
|
+
<%_ if (framework === 'prisma') { _%>
|
|
15
15
|
Runtime,
|
|
16
16
|
<%_ } _%>
|
|
17
17
|
} from 'aws-cdk-lib/aws-lambda';
|
|
@@ -76,7 +76,7 @@ export class <%= nameClassName %> extends AuroraDatabase {
|
|
|
76
76
|
...baseProps,
|
|
77
77
|
code: Code.fromAsset(createDbUserBundleDir),
|
|
78
78
|
handler: 'index.handler',
|
|
79
|
-
runtime:
|
|
79
|
+
runtime: <%- nodeRuntime %>,
|
|
80
80
|
environment: {
|
|
81
81
|
NODE_EXTRA_CA_CERTS: '/var/runtime/ca-cert.pem',
|
|
82
82
|
},
|
|
@@ -88,12 +88,6 @@ variable "enable_rds_proxy" {
|
|
|
88
88
|
default = true
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
variable "enable_credential_rotation" {
|
|
92
|
-
description = "Whether to enable automatic credential rotation for the admin secret."
|
|
93
|
-
type = bool
|
|
94
|
-
default = true
|
|
95
|
-
}
|
|
96
|
-
|
|
97
91
|
variable "enable_cloudwatch_logs" {
|
|
98
92
|
description = "Whether to export Aurora engine logs to CloudWatch. PostgreSQL logs DDL statements only (log_statement=ddl); MySQL enables Advanced Auditing scoped to connections and DDL (server_audit_events=CONNECT,QUERY_DDL). Neither logs statement parameter values, to avoid leaking PII into log data."
|
|
99
93
|
type = bool
|
|
@@ -144,7 +138,7 @@ variable "create_db_user_docker_image_tag" {
|
|
|
144
138
|
}
|
|
145
139
|
<%_ } _%>
|
|
146
140
|
|
|
147
|
-
<%_ if (framework
|
|
141
|
+
<%_ if (framework === 'prisma') { _%>
|
|
148
142
|
variable "asset_bucket_name" {
|
|
149
143
|
description = "Name of the shared asset S3 bucket used to stage the Lambda deployment zip. Instantiate the `core/asset-bucket` module once per deployment and pass its `bucket_name` output here."
|
|
150
144
|
type = string
|
|
@@ -163,7 +157,7 @@ resource "random_string" "suffix" {
|
|
|
163
157
|
locals {
|
|
164
158
|
config = jsondecode(file("${path.module}/../../../../../../../<%= projectRoot %>/config.json"))
|
|
165
159
|
runtime_config_key = local.config.runtimeConfigKey
|
|
166
|
-
<%_ if (framework
|
|
160
|
+
<%_ if (framework === 'prisma') { _%>
|
|
167
161
|
create_db_user_bundle_path = "${path.module}/../../../../../../../<%- createDbUserBundleDir %>"
|
|
168
162
|
<%_ } _%>
|
|
169
163
|
migration_function_name = "<%= nameKebabCase %>-migration-${random_string.suffix.result}"
|
|
@@ -177,7 +171,6 @@ module "aurora" {
|
|
|
177
171
|
name = "<%= nameKebabCase %>"
|
|
178
172
|
vpc_id = var.vpc_id
|
|
179
173
|
subnet_ids = var.database_subnet_ids
|
|
180
|
-
lambda_subnet_ids = var.lambda_subnet_ids
|
|
181
174
|
engine = "<%= engine === 'mysql' ? 'aurora-mysql' : 'aurora-postgresql' %>"
|
|
182
175
|
engine_version = var.engine_version
|
|
183
176
|
database_name = "<%= databaseName %>"
|
|
@@ -189,7 +182,6 @@ module "aurora" {
|
|
|
189
182
|
deletion_protection = var.deletion_protection
|
|
190
183
|
skip_final_snapshot = var.skip_final_snapshot
|
|
191
184
|
enable_rds_proxy = var.enable_rds_proxy
|
|
192
|
-
enable_credential_rotation = var.enable_credential_rotation
|
|
193
185
|
enable_cloudwatch_logs = var.enable_cloudwatch_logs
|
|
194
186
|
enable_performance_insights = var.enable_performance_insights
|
|
195
187
|
performance_insights_retention_period = var.performance_insights_retention_period
|
|
@@ -206,22 +198,6 @@ resource "aws_iam_role_policy" "proxy_db_user_connect" {
|
|
|
206
198
|
policy = jsonencode({
|
|
207
199
|
Version = "2012-10-17"
|
|
208
200
|
Statement = [
|
|
209
|
-
<%_ if (engine === 'mysql' && framework !== 'sqlmodel') { _%>
|
|
210
|
-
{
|
|
211
|
-
Effect = "Allow"
|
|
212
|
-
Action = [
|
|
213
|
-
"secretsmanager:GetSecretValue"
|
|
214
|
-
]
|
|
215
|
-
Resource = [module.aurora.secret_arn]
|
|
216
|
-
},
|
|
217
|
-
{
|
|
218
|
-
Effect = "Allow"
|
|
219
|
-
Action = [
|
|
220
|
-
"kms:Decrypt"
|
|
221
|
-
]
|
|
222
|
-
Resource = [module.aurora.kms_key_arn]
|
|
223
|
-
}
|
|
224
|
-
<%_ } else { _%>
|
|
225
201
|
{
|
|
226
202
|
Effect = "Allow"
|
|
227
203
|
Action = ["rds-db:connect"]
|
|
@@ -229,12 +205,11 @@ resource "aws_iam_role_policy" "proxy_db_user_connect" {
|
|
|
229
205
|
"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}"
|
|
230
206
|
]
|
|
231
207
|
}
|
|
232
|
-
<%_ } _%>
|
|
233
208
|
]
|
|
234
209
|
})
|
|
235
210
|
}
|
|
236
211
|
|
|
237
|
-
<%_ if (framework
|
|
212
|
+
<%_ if (framework === 'prisma') { _%>
|
|
238
213
|
data "archive_file" "create_db_user_zip" {
|
|
239
214
|
type = "zip"
|
|
240
215
|
source_dir = local.create_db_user_bundle_path
|
|
@@ -595,7 +570,7 @@ resource "aws_lambda_function" "create_db_user" {
|
|
|
595
570
|
role = aws_iam_role.create_db_user.arn
|
|
596
571
|
handler = "index.handler"
|
|
597
572
|
source_code_hash = data.archive_file.create_db_user_zip.output_base64sha256
|
|
598
|
-
runtime = "
|
|
573
|
+
runtime = "<%- nodeRuntime %>"
|
|
599
574
|
timeout = 300
|
|
600
575
|
architectures = ["arm64"]
|
|
601
576
|
<%_ } _%>
|
|
@@ -612,6 +587,9 @@ resource "aws_lambda_function" "create_db_user" {
|
|
|
612
587
|
environment {
|
|
613
588
|
variables = {
|
|
614
589
|
DATABASE_SECRET_ARN = module.aurora.secret_arn
|
|
590
|
+
DATABASE_HOST = module.aurora.writer_endpoint
|
|
591
|
+
DATABASE_PORT = module.aurora.cluster_port
|
|
592
|
+
DATABASE_NAME = module.aurora.database_name
|
|
615
593
|
<%_ if (framework === 'prisma') { _%>
|
|
616
594
|
NODE_EXTRA_CA_CERTS = "/var/runtime/ca-cert.pem"
|
|
617
595
|
<%_ } _%>
|
|
@@ -699,6 +677,9 @@ resource "aws_lambda_function" "migration_handler" {
|
|
|
699
677
|
environment {
|
|
700
678
|
variables = {
|
|
701
679
|
DATABASE_SECRET_ARN = module.aurora.secret_arn
|
|
680
|
+
DATABASE_HOST = module.aurora.writer_endpoint
|
|
681
|
+
DATABASE_PORT = module.aurora.cluster_port
|
|
682
|
+
DATABASE_NAME = module.aurora.database_name
|
|
702
683
|
}
|
|
703
684
|
}
|
|
704
685
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# Core Aurora module
|
|
2
|
-
# This module creates an Aurora cluster
|
|
2
|
+
# This module creates an Aurora cluster whose admin credentials are generated
|
|
3
|
+
# and rotated by RDS in Secrets Manager.
|
|
3
4
|
|
|
4
5
|
terraform {
|
|
5
6
|
required_version = ">= 1.0"
|
|
@@ -43,11 +44,6 @@ variable "subnet_ids" {
|
|
|
43
44
|
type = list(string)
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
variable "lambda_subnet_ids" {
|
|
47
|
-
description = "Subnet IDs for the credential-rotation Lambda. Must have outbound egress to AWS service endpoints (e.g. Secrets Manager) — use private subnets with a NAT gateway."
|
|
48
|
-
type = list(string)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
47
|
variable "engine" {
|
|
52
48
|
description = "Aurora engine to use."
|
|
53
49
|
type = string
|
|
@@ -117,12 +113,6 @@ variable "enable_rds_proxy" {
|
|
|
117
113
|
default = true
|
|
118
114
|
}
|
|
119
115
|
|
|
120
|
-
variable "enable_credential_rotation" {
|
|
121
|
-
description = "Whether to enable automatic credential rotation for the admin secret."
|
|
122
|
-
type = bool
|
|
123
|
-
default = true
|
|
124
|
-
}
|
|
125
|
-
|
|
126
116
|
variable "enable_cloudwatch_logs" {
|
|
127
117
|
description = "Whether to export Aurora engine logs to CloudWatch. PostgreSQL logs DDL statements only (log_statement=ddl); MySQL enables Advanced Auditing scoped to connections and DDL (server_audit_events=CONNECT,QUERY_DDL). Neither logs statement parameter values, to avoid leaking PII into log data."
|
|
128
118
|
type = bool
|
|
@@ -244,6 +234,20 @@ resource "aws_kms_key" "database" {
|
|
|
244
234
|
"kms:CreateGrant"
|
|
245
235
|
]
|
|
246
236
|
Resource = "*"
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
Sid = "AllowSecretsManagerService"
|
|
240
|
+
Effect = "Allow"
|
|
241
|
+
Principal = {
|
|
242
|
+
Service = "secretsmanager.amazonaws.com"
|
|
243
|
+
}
|
|
244
|
+
Action = [
|
|
245
|
+
"kms:Encrypt",
|
|
246
|
+
"kms:Decrypt",
|
|
247
|
+
"kms:GenerateDataKey*",
|
|
248
|
+
"kms:DescribeKey"
|
|
249
|
+
]
|
|
250
|
+
Resource = "*"
|
|
247
251
|
}
|
|
248
252
|
]
|
|
249
253
|
})
|
|
@@ -298,35 +302,6 @@ resource "aws_db_subnet_group" "database" {
|
|
|
298
302
|
})
|
|
299
303
|
}
|
|
300
304
|
|
|
301
|
-
resource "random_password" "master_password" {
|
|
302
|
-
length = 32
|
|
303
|
-
special = true
|
|
304
|
-
override_special = "!#$%&*()-_=+[]{}<>:?"
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
resource "aws_secretsmanager_secret" "credentials" {
|
|
308
|
-
#checkov:skip=CKV2_AWS_57:Rotation is configured via aws_cloudformation_stack.credentials_rotation using the AWS::SecretsManager-2024-09-16 transform; Checkov cannot resolve rotation schedules created by CloudFormation transforms
|
|
309
|
-
name_prefix = "${var.name}-aurora-credentials-"
|
|
310
|
-
kms_key_id = aws_kms_key.database.arn
|
|
311
|
-
|
|
312
|
-
tags = merge(var.tags, {
|
|
313
|
-
Name = "${var.name}-aurora-credentials"
|
|
314
|
-
})
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
resource "aws_secretsmanager_secret_version" "credentials" {
|
|
318
|
-
secret_id = aws_secretsmanager_secret.credentials.id
|
|
319
|
-
secret_string = jsonencode({
|
|
320
|
-
engine = var.engine == "aurora-mysql" ? "mysql" : "postgres"
|
|
321
|
-
username = var.admin_user
|
|
322
|
-
password = random_password.master_password.result
|
|
323
|
-
host = aws_rds_cluster.database.endpoint
|
|
324
|
-
port = aws_rds_cluster.database.port
|
|
325
|
-
dbname = var.database_name
|
|
326
|
-
dbClusterIdentifier = aws_rds_cluster.database.cluster_identifier
|
|
327
|
-
})
|
|
328
|
-
}
|
|
329
|
-
|
|
330
305
|
resource "aws_rds_cluster" "database" {
|
|
331
306
|
#checkov:skip=CKV2_AWS_27:Query logging is enabled by default via enable_cloudwatch_logs; checkov cannot resolve the conditional count expression on aws_rds_cluster_parameter_group.database
|
|
332
307
|
#checkov:skip=CKV_AWS_139:Deletion protection is enabled but checkov is unable to detect it correctly
|
|
@@ -335,7 +310,8 @@ resource "aws_rds_cluster" "database" {
|
|
|
335
310
|
engine_version = coalesce(var.engine_version, local.default_engine_version)
|
|
336
311
|
database_name = var.database_name
|
|
337
312
|
master_username = var.admin_user
|
|
338
|
-
|
|
313
|
+
manage_master_user_password = true
|
|
314
|
+
master_user_secret_kms_key_id = aws_kms_key.database.arn
|
|
339
315
|
db_subnet_group_name = aws_db_subnet_group.database.name
|
|
340
316
|
db_cluster_parameter_group_name = var.enable_cloudwatch_logs ? aws_rds_cluster_parameter_group.database[0].name : null
|
|
341
317
|
vpc_security_group_ids = [aws_security_group.database.id]
|
|
@@ -387,75 +363,6 @@ resource "aws_rds_cluster_instance" "database" {
|
|
|
387
363
|
})
|
|
388
364
|
}
|
|
389
365
|
|
|
390
|
-
resource "aws_security_group" "rotation" {
|
|
391
|
-
#checkov:skip=CKV2_AWS_5:Security group is attached to the hosted rotation Lambda created by AWS::SecretsManager::RotationSchedule; Checkov cannot resolve resources created by the CloudFormation transform
|
|
392
|
-
count = var.enable_credential_rotation ? 1 : 0
|
|
393
|
-
name_prefix = "${var.name}-aurora-rotation-"
|
|
394
|
-
description = "Security group for Aurora secret rotation ${var.name}"
|
|
395
|
-
vpc_id = var.vpc_id
|
|
396
|
-
|
|
397
|
-
tags = merge(var.tags, {
|
|
398
|
-
Name = "${var.name}-aurora-rotation"
|
|
399
|
-
})
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
resource "aws_vpc_security_group_egress_rule" "rotation_to_database" {
|
|
403
|
-
count = var.enable_credential_rotation ? 1 : 0
|
|
404
|
-
security_group_id = aws_security_group.rotation[0].id
|
|
405
|
-
referenced_security_group_id = aws_security_group.database.id
|
|
406
|
-
from_port = coalesce(var.port, local.default_port)
|
|
407
|
-
to_port = coalesce(var.port, local.default_port)
|
|
408
|
-
ip_protocol = "tcp"
|
|
409
|
-
description = "Allow outbound database traffic from secret rotation Lambda"
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
resource "aws_vpc_security_group_ingress_rule" "rotation_to_database" {
|
|
413
|
-
count = var.enable_credential_rotation ? 1 : 0
|
|
414
|
-
security_group_id = aws_security_group.database.id
|
|
415
|
-
referenced_security_group_id = aws_security_group.rotation[0].id
|
|
416
|
-
from_port = coalesce(var.port, local.default_port)
|
|
417
|
-
to_port = coalesce(var.port, local.default_port)
|
|
418
|
-
ip_protocol = "tcp"
|
|
419
|
-
description = "Allow inbound database traffic from secret rotation Lambda"
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
resource "aws_cloudformation_stack" "credentials_rotation" {
|
|
423
|
-
#checkov:skip=CKV_AWS_124:SNS event notifications are not required for the credentials rotation stack
|
|
424
|
-
count = var.enable_credential_rotation ? 1 : 0
|
|
425
|
-
name = "${local.cluster_name}-credentials-rotation"
|
|
426
|
-
|
|
427
|
-
capabilities = ["CAPABILITY_IAM", "CAPABILITY_AUTO_EXPAND"]
|
|
428
|
-
|
|
429
|
-
template_body = jsonencode({
|
|
430
|
-
AWSTemplateFormatVersion = "2010-09-09"
|
|
431
|
-
Transform = "AWS::SecretsManager-2024-09-16"
|
|
432
|
-
Resources = {
|
|
433
|
-
CredentialsRotationSchedule = {
|
|
434
|
-
Type = "AWS::SecretsManager::RotationSchedule"
|
|
435
|
-
Properties = {
|
|
436
|
-
SecretId = aws_secretsmanager_secret.credentials.arn
|
|
437
|
-
HostedRotationLambda = {
|
|
438
|
-
RotationType = var.engine == "aurora-mysql" ? "MySQLSingleUser" : "PostgreSQLSingleUser"
|
|
439
|
-
RotationLambdaName = "${local.cluster_name}-credentials-rotation"
|
|
440
|
-
VpcSecurityGroupIds = aws_security_group.rotation[0].id
|
|
441
|
-
VpcSubnetIds = join(",", var.lambda_subnet_ids)
|
|
442
|
-
}
|
|
443
|
-
RotationRules = {
|
|
444
|
-
AutomaticallyAfterDays = 30
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
})
|
|
450
|
-
|
|
451
|
-
depends_on = [
|
|
452
|
-
aws_secretsmanager_secret_version.credentials,
|
|
453
|
-
aws_rds_cluster_instance.database,
|
|
454
|
-
aws_vpc_security_group_egress_rule.rotation_to_database,
|
|
455
|
-
aws_vpc_security_group_ingress_rule.rotation_to_database,
|
|
456
|
-
]
|
|
457
|
-
}
|
|
458
|
-
|
|
459
366
|
resource "aws_iam_role" "proxy" {
|
|
460
367
|
count = var.enable_rds_proxy ? 1 : 0
|
|
461
368
|
|
|
@@ -694,6 +601,11 @@ output "cluster_endpoint" {
|
|
|
694
601
|
value = var.enable_rds_proxy ? aws_db_proxy.aurora[0].endpoint : aws_rds_cluster.database.endpoint
|
|
695
602
|
}
|
|
696
603
|
|
|
604
|
+
output "writer_endpoint" {
|
|
605
|
+
description = "Writer endpoint of the Aurora cluster itself, bypassing the RDS Proxy. Used by the admin-credentialled handlers, which connect directly to the cluster."
|
|
606
|
+
value = aws_rds_cluster.database.endpoint
|
|
607
|
+
}
|
|
608
|
+
|
|
697
609
|
output "reader_endpoint" {
|
|
698
610
|
description = "Reader endpoint of the Aurora cluster."
|
|
699
611
|
value = aws_rds_cluster.database.reader_endpoint
|
|
@@ -720,12 +632,12 @@ output "proxy_role_name" {
|
|
|
720
632
|
}
|
|
721
633
|
|
|
722
634
|
output "secret_arn" {
|
|
723
|
-
description = "ARN of the
|
|
724
|
-
value =
|
|
635
|
+
description = "ARN of the RDS-managed admin credentials secret. Its value is a JSON object with username and password only — connection details come from this module's other outputs."
|
|
636
|
+
value = one(aws_rds_cluster.database.master_user_secret[*].secret_arn)
|
|
725
637
|
}
|
|
726
638
|
|
|
727
639
|
output "kms_key_arn" {
|
|
728
|
-
description = "ARN of the KMS key protecting Aurora and
|
|
640
|
+
description = "ARN of the KMS key protecting Aurora and its admin credentials secret."
|
|
729
641
|
value = aws_kms_key.database.arn
|
|
730
642
|
}
|
|
731
643
|
|
|
@@ -750,6 +662,6 @@ output "database_name" {
|
|
|
750
662
|
}
|
|
751
663
|
|
|
752
664
|
output "admin_user" {
|
|
753
|
-
description = "Admin username stored in the
|
|
754
|
-
value =
|
|
665
|
+
description = "Admin username stored in the RDS-managed credentials secret."
|
|
666
|
+
value = aws_rds_cluster.database.master_username
|
|
755
667
|
}
|
|
@@ -6,7 +6,7 @@ import { addStarExport } from "../ast.js";
|
|
|
6
6
|
import { esmVars } from "../module-format.js";
|
|
7
7
|
import { addDependencyToTargetIfNotPresent } from "../nx.js";
|
|
8
8
|
import { PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, SHARED_TERRAFORM_DIR } from "../shared-constructs-constants.js";
|
|
9
|
-
import { terraformProviderVersions } from "../versions.js";
|
|
9
|
+
import { cdkLambdaRuntimeVars, terraformLambdaRuntimeVars, terraformProviderVersions } from "../versions.js";
|
|
10
10
|
/**
|
|
11
11
|
* Aurora Serverless v2 scaling bounds, in ACUs, that both IaC providers derive
|
|
12
12
|
* from so the same generator options vend the same ceiling regardless of `--iac`.
|
|
@@ -48,7 +48,8 @@ export const addRdbCdkConstructs = async (tree, options)=>{
|
|
|
48
48
|
});
|
|
49
49
|
generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'cdk', 'app', 'dbs'), joinPathFragments(PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, 'src', 'app', 'dbs'), {
|
|
50
50
|
...options,
|
|
51
|
-
...esmVars(tree)
|
|
51
|
+
...esmVars(tree),
|
|
52
|
+
...cdkLambdaRuntimeVars()
|
|
52
53
|
}, {
|
|
53
54
|
overwriteStrategy: OverwriteStrategy.KeepExisting
|
|
54
55
|
});
|
|
@@ -66,7 +67,8 @@ export const addRdbTerraformModules = (tree, options)=>{
|
|
|
66
67
|
generateFiles(tree, joinPathFragments(import.meta.dirname, 'files', 'terraform', 'app', 'dbs'), joinPathFragments(PACKAGES_DIR, SHARED_TERRAFORM_DIR, 'src', 'app', 'dbs'), {
|
|
67
68
|
...options,
|
|
68
69
|
...terraformProviderVersions(),
|
|
69
|
-
...auroraServerlessV2Capacity()
|
|
70
|
+
...auroraServerlessV2Capacity(),
|
|
71
|
+
...terraformLambdaRuntimeVars()
|
|
70
72
|
}, {
|
|
71
73
|
overwriteStrategy: OverwriteStrategy.KeepExisting
|
|
72
74
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/utils/rdb-constructs/rdb-constructs.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type ProjectConfiguration,\n type Tree,\n updateJson,\n} from '@nx/devkit';\nimport { addStarExport } from '../ast.js';\nimport type { Containers } from '../containers.js';\nimport type { Iac } from '../iac.js';\nimport { esmVars } from '../module-format.js';\nimport { addDependencyToTargetIfNotPresent } from '../nx.js';\nimport {\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n SHARED_TERRAFORM_DIR,\n} from '../shared-constructs-constants.js';\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../../../../packages/nx-plugin/src/utils/rdb-constructs/rdb-constructs.ts"],"sourcesContent":["/**\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\nimport {\n generateFiles,\n joinPathFragments,\n OverwriteStrategy,\n type ProjectConfiguration,\n type Tree,\n updateJson,\n} from '@nx/devkit';\nimport { addStarExport } from '../ast.js';\nimport type { Containers } from '../containers.js';\nimport type { Iac } from '../iac.js';\nimport { esmVars } from '../module-format.js';\nimport { addDependencyToTargetIfNotPresent } from '../nx.js';\nimport {\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n SHARED_TERRAFORM_DIR,\n} from '../shared-constructs-constants.js';\nimport {\n cdkLambdaRuntimeVars,\n terraformLambdaRuntimeVars,\n terraformProviderVersions,\n} from '../versions.js';\n\n/**\n * Aurora Serverless v2 scaling bounds, in ACUs, that both IaC providers derive\n * from so the same generator options vend the same ceiling regardless of `--iac`.\n *\n * Set explicitly on CDK rather than inheriting `DatabaseClusterProps`, whose\n * default moves with `aws-cdk-lib`. Serverless v2 bills on ACUs consumed, not on\n * the ceiling, so the maximum is headroom rather than a cost commitment.\n */\nexport const AURORA_SERVERLESS_V2_CAPACITY = {\n min: 0.5,\n max: 4,\n} as const;\n\n/**\n * Substitution variables exposing the Aurora Serverless v2 scaling bounds to\n * generated CDK and Terraform templates.\n */\nconst auroraServerlessV2Capacity = () => ({\n serverlessMinCapacity: AURORA_SERVERLESS_V2_CAPACITY.min,\n serverlessMaxCapacity: AURORA_SERVERLESS_V2_CAPACITY.max,\n});\n\nexport interface AddRdbConstructOptions {\n projectName: string;\n projectRoot: string;\n nameClassName: string;\n nameKebabCase: string;\n databasePackageAlias: string;\n databaseName: string;\n adminUser: string;\n engine: 'postgres' | 'mysql';\n migrationBundleDir: string;\n /**\n * Node.js zip bundle directory for the create-db-user Lambda (ts#rdb).\n * When absent the migration Docker image is reused with the\n * `create_db_user_handler.handler` command (py#rdb).\n */\n createDbUserBundleDir: string;\n /** ORM framework used by the create-db-user Lambda. */\n framework: 'prisma' | 'sqlmodel';\n /** Local Docker tag for the Python create-db-user Lambda image. */\n createDbUserDockerImageTag?: string;\n /** Local Docker tag for the migration Lambda image. */\n migrationDockerImageTag: string;\n containerEngine: Containers;\n}\n\nexport const addRdbInfra = async (\n tree: Tree,\n options: AddRdbConstructOptions & { iac: Iac },\n) => {\n if (options.iac === 'cdk') {\n await addRdbCdkConstructs(tree, options);\n } else if (options.iac === 'terraform') {\n addRdbTerraformModules(tree, options);\n } else {\n throw new Error(`Unsupported iac ${options.iac}`);\n }\n\n updateJson(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n options.iac === 'cdk' ? SHARED_CONSTRUCTS_DIR : SHARED_TERRAFORM_DIR,\n 'project.json',\n ),\n (config: ProjectConfiguration) => {\n addDependencyToTargetIfNotPresent(\n config,\n 'build',\n `${options.projectName}:build`,\n );\n return config;\n },\n );\n};\n\nexport const addRdbCdkConstructs = async (\n tree: Tree,\n options: AddRdbConstructOptions,\n) => {\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'cdk', 'core', 'rdb'),\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'core',\n 'rdb',\n ),\n { ...options, ...esmVars(tree), ...auroraServerlessV2Capacity() },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'cdk', 'app', 'dbs'),\n joinPathFragments(PACKAGES_DIR, SHARED_CONSTRUCTS_DIR, 'src', 'app', 'dbs'),\n { ...options, ...esmVars(tree), ...cdkLambdaRuntimeVars() },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'core',\n 'index.ts',\n ),\n './rdb/aurora.js',\n );\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'dbs',\n 'index.ts',\n ),\n `./${options.nameKebabCase}.js`,\n );\n await addStarExport(\n tree,\n joinPathFragments(\n PACKAGES_DIR,\n SHARED_CONSTRUCTS_DIR,\n 'src',\n 'app',\n 'index.ts',\n ),\n './dbs/index.js',\n );\n};\n\nexport const addRdbTerraformModules = (\n tree: Tree,\n options: AddRdbConstructOptions,\n) => {\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'terraform', 'core', 'rdb'),\n joinPathFragments(PACKAGES_DIR, SHARED_TERRAFORM_DIR, 'src', 'core', 'rdb'),\n { ...terraformProviderVersions(), ...auroraServerlessV2Capacity() },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n\n generateFiles(\n tree,\n joinPathFragments(import.meta.dirname, 'files', 'terraform', 'app', 'dbs'),\n joinPathFragments(PACKAGES_DIR, SHARED_TERRAFORM_DIR, 'src', 'app', 'dbs'),\n {\n ...options,\n ...terraformProviderVersions(),\n ...auroraServerlessV2Capacity(),\n ...terraformLambdaRuntimeVars(),\n },\n {\n overwriteStrategy: OverwriteStrategy.KeepExisting,\n },\n );\n};\n"],"names":["generateFiles","joinPathFragments","OverwriteStrategy","updateJson","addStarExport","esmVars","addDependencyToTargetIfNotPresent","PACKAGES_DIR","SHARED_CONSTRUCTS_DIR","SHARED_TERRAFORM_DIR","cdkLambdaRuntimeVars","terraformLambdaRuntimeVars","terraformProviderVersions","AURORA_SERVERLESS_V2_CAPACITY","min","max","auroraServerlessV2Capacity","serverlessMinCapacity","serverlessMaxCapacity","addRdbInfra","tree","options","iac","addRdbCdkConstructs","addRdbTerraformModules","Error","config","projectName","dirname","overwriteStrategy","KeepExisting","nameKebabCase"],"mappings":"AAAA;;;CAGC,GACD,SACEA,aAAa,EACbC,iBAAiB,EACjBC,iBAAiB,EAGjBC,UAAU,QACL,aAAa;AACpB,SAASC,aAAa,QAAQ,YAAY;AAG1C,SAASC,OAAO,QAAQ,sBAAsB;AAC9C,SAASC,iCAAiC,QAAQ,WAAW;AAC7D,SACEC,YAAY,EACZC,qBAAqB,EACrBC,oBAAoB,QACf,oCAAoC;AAC3C,SACEC,oBAAoB,EACpBC,0BAA0B,EAC1BC,yBAAyB,QACpB,iBAAiB;AAExB;;;;;;;CAOC,GACD,OAAO,MAAMC,gCAAgC;IAC3CC,KAAK;IACLC,KAAK;AACP,EAAW;AAEX;;;CAGC,GACD,MAAMC,6BAA6B,IAAO,CAAA;QACxCC,uBAAuBJ,8BAA8BC,GAAG;QACxDI,uBAAuBL,8BAA8BE,GAAG;IAC1D,CAAA;AA2BA,OAAO,MAAMI,cAAc,OACzBC,MACAC;IAEA,IAAIA,QAAQC,GAAG,KAAK,OAAO;QACzB,MAAMC,oBAAoBH,MAAMC;IAClC,OAAO,IAAIA,QAAQC,GAAG,KAAK,aAAa;QACtCE,uBAAuBJ,MAAMC;IAC/B,OAAO;QACL,MAAM,IAAII,MAAM,CAAC,gBAAgB,EAAEJ,QAAQC,GAAG,EAAE;IAClD;IAEAnB,WACEiB,MACAnB,kBACEM,cACAc,QAAQC,GAAG,KAAK,QAAQd,wBAAwBC,sBAChD,iBAEF,CAACiB;QACCpB,kCACEoB,QACA,SACA,GAAGL,QAAQM,WAAW,CAAC,MAAM,CAAC;QAEhC,OAAOD;IACT;AAEJ,EAAE;AAEF,OAAO,MAAMH,sBAAsB,OACjCH,MACAC;IAEArB,cACEoB,MACAnB,kBAAkB,YAAY2B,OAAO,EAAE,SAAS,OAAO,QAAQ,QAC/D3B,kBACEM,cACAC,uBACA,OACA,QACA,QAEF;QAAE,GAAGa,OAAO;QAAE,GAAGhB,QAAQe,KAAK;QAAE,GAAGJ,4BAA4B;IAAC,GAChE;QACEa,mBAAmB3B,kBAAkB4B,YAAY;IACnD;IAGF9B,cACEoB,MACAnB,kBAAkB,YAAY2B,OAAO,EAAE,SAAS,OAAO,OAAO,QAC9D3B,kBAAkBM,cAAcC,uBAAuB,OAAO,OAAO,QACrE;QAAE,GAAGa,OAAO;QAAE,GAAGhB,QAAQe,KAAK;QAAE,GAAGV,sBAAsB;IAAC,GAC1D;QACEmB,mBAAmB3B,kBAAkB4B,YAAY;IACnD;IAGF,MAAM1B,cACJgB,MACAnB,kBACEM,cACAC,uBACA,OACA,QACA,aAEF;IAEF,MAAMJ,cACJgB,MACAnB,kBACEM,cACAC,uBACA,OACA,OACA,OACA,aAEF,CAAC,EAAE,EAAEa,QAAQU,aAAa,CAAC,GAAG,CAAC;IAEjC,MAAM3B,cACJgB,MACAnB,kBACEM,cACAC,uBACA,OACA,OACA,aAEF;AAEJ,EAAE;AAEF,OAAO,MAAMgB,yBAAyB,CACpCJ,MACAC;IAEArB,cACEoB,MACAnB,kBAAkB,YAAY2B,OAAO,EAAE,SAAS,aAAa,QAAQ,QACrE3B,kBAAkBM,cAAcE,sBAAsB,OAAO,QAAQ,QACrE;QAAE,GAAGG,2BAA2B;QAAE,GAAGI,4BAA4B;IAAC,GAClE;QACEa,mBAAmB3B,kBAAkB4B,YAAY;IACnD;IAGF9B,cACEoB,MACAnB,kBAAkB,YAAY2B,OAAO,EAAE,SAAS,aAAa,OAAO,QACpE3B,kBAAkBM,cAAcE,sBAAsB,OAAO,OAAO,QACpE;QACE,GAAGY,OAAO;QACV,GAAGT,2BAA2B;QAC9B,GAAGI,4BAA4B;QAC/B,GAAGL,4BAA4B;IACjC,GACA;QACEkB,mBAAmB3B,kBAAkB4B,YAAY;IACnD;AAEJ,EAAE"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*/
|
|
5
|
+
import { type Tree } from '@nx/devkit';
|
|
6
|
+
/**
|
|
7
|
+
* Sync the Lambda runtimes vended into the projects this plugin owns.
|
|
8
|
+
*
|
|
9
|
+
* The runtimes present are read from each file rather than compared against a
|
|
10
|
+
* list of what past releases vended, which would need maintaining by hand for the
|
|
11
|
+
* same reason the pin itself does.
|
|
12
|
+
*/
|
|
13
|
+
/** The IaC provider a vended file belongs to, decided by the directory it sits in. */
|
|
14
|
+
export type VendedIac = 'cdk' | 'terraform';
|
|
15
|
+
/**
|
|
16
|
+
* Sync the Lambda runtimes in the directories this plugin owns.
|
|
17
|
+
*
|
|
18
|
+
* A runtime below the pin is ours to move, as is a `_LATEST` alias — its value is
|
|
19
|
+
* decided by `aws-cdk-lib`, which is the drift this closes. A runtime at or ahead
|
|
20
|
+
* of the pin is the user's and is left, as is any Lambda outside these
|
|
21
|
+
* directories. One the rewrite cannot reach is reported instead.
|
|
22
|
+
*
|
|
23
|
+
* @returns the files changed, and the owned files still holding an older runtime
|
|
24
|
+
*/
|
|
25
|
+
export declare const syncLambdaRuntimes: (tree: Tree, dirs: Readonly<Record<VendedIac, string>>) => Promise<{
|
|
26
|
+
updated: string[];
|
|
27
|
+
diverged: string[];
|
|
28
|
+
}>;
|