@fjall/components-infrastructure 27.0.0 → 27.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/patterns/aws/database.js +8 -1
- package/dist/lib/patterns/aws/interfaces/database.d.ts +6 -3
- package/dist/lib/resources/aws/database/rdsAurora.d.ts +8 -0
- package/dist/lib/resources/aws/database/rdsAurora.js +13 -1
- package/dist/lib/resources/aws/database/rdsAuroraGlobal.d.ts +7 -0
- package/dist/lib/resources/aws/database/rdsAuroraGlobal.js +15 -0
- package/dist/lib/resources/aws/database/rdsInstance.d.ts +8 -0
- package/dist/lib/resources/aws/database/rdsInstance.js +16 -2
- package/package.json +3 -3
|
@@ -12,7 +12,7 @@ import { Port } from "aws-cdk-lib/aws-ec2";
|
|
|
12
12
|
import { Effect, PolicyStatement } from "aws-cdk-lib/aws-iam";
|
|
13
13
|
import { MIGRATION_SNAPSHOT_NAME_PREFIX } from "./interfaces/database.js";
|
|
14
14
|
import { pickLatestPrismaMigration } from "../../utils/migrationVersionResolvers.js";
|
|
15
|
-
import { SCHEMA_GATE_DB_PASSWORD_ENV, SCHEMA_GATE_DB_URL_BASE_ENV, SCHEMA_GATE_DB_USER_ENV } from "@fjall/util/migration";
|
|
15
|
+
import { MIGRATION_SNAPSHOT_RETENTION_DAYS_ENV, SCHEMA_GATE_DB_PASSWORD_ENV, SCHEMA_GATE_DB_URL_BASE_ENV, SCHEMA_GATE_DB_USER_ENV } from "@fjall/util/migration";
|
|
16
16
|
import { DatabaseClusterEngine, DatabaseInstanceEngine, AuroraPostgresEngineVersion, AuroraMysqlEngineVersion, PostgresEngineVersion, MysqlEngineVersion } from "aws-cdk-lib/aws-rds";
|
|
17
17
|
import { Duration } from "aws-cdk-lib";
|
|
18
18
|
export { isAwsManagedKey, isCMKRequested, AWS_MANAGED, USE_CMK } from "../../utils/databaseTypes.js";
|
|
@@ -296,11 +296,13 @@ const SNAPSHOT_ACTION_TABLE = {
|
|
|
296
296
|
instance: {
|
|
297
297
|
createAction: "rds:CreateDBSnapshot",
|
|
298
298
|
describeAction: "rds:DescribeDBSnapshots",
|
|
299
|
+
deleteAction: "rds:DeleteDBSnapshot",
|
|
299
300
|
resourceArnSegment: "snapshot"
|
|
300
301
|
},
|
|
301
302
|
cluster: {
|
|
302
303
|
createAction: "rds:CreateDBClusterSnapshot",
|
|
303
304
|
describeAction: "rds:DescribeDBClusterSnapshots",
|
|
305
|
+
deleteAction: "rds:DeleteDBClusterSnapshot",
|
|
304
306
|
resourceArnSegment: "cluster-snapshot"
|
|
305
307
|
}
|
|
306
308
|
};
|
|
@@ -540,6 +542,10 @@ export class RelationalDatabase extends Construct {
|
|
|
540
542
|
actions: [
|
|
541
543
|
triple.createAction,
|
|
542
544
|
triple.describeAction,
|
|
545
|
+
// Delete is confined to fjall-premigrate-* by IAM: a Delete request's
|
|
546
|
+
// resource is always a snapshot ARN, which only the prefix glob below
|
|
547
|
+
// can match — never the instance/cluster ARN.
|
|
548
|
+
triple.deleteAction,
|
|
543
549
|
"rds:AddTagsToResource"
|
|
544
550
|
],
|
|
545
551
|
resources: [
|
|
@@ -605,6 +611,7 @@ export class RelationalDatabase extends Construct {
|
|
|
605
611
|
const target = this.getSnapshotTarget();
|
|
606
612
|
environment.SNAPSHOT_TARGET_KIND = target.kind;
|
|
607
613
|
environment.SNAPSHOT_TARGET_ARN = target.arn;
|
|
614
|
+
environment[MIGRATION_SNAPSHOT_RETENTION_DAYS_ENV] = String(this.database.getBackupRetentionDays());
|
|
608
615
|
}
|
|
609
616
|
const credentials = this.getCredentials();
|
|
610
617
|
const secretsImport = {
|
|
@@ -127,9 +127,12 @@ export interface IRelationalDatabaseBase extends IDatabase, IConnectable, IMigra
|
|
|
127
127
|
getSnapshotTarget(): SnapshotTarget;
|
|
128
128
|
/**
|
|
129
129
|
* Returns the IAM PolicyStatement granting the migration runner the rights
|
|
130
|
-
* needed to take and
|
|
131
|
-
*
|
|
132
|
-
* Snapshot name glob is bound to
|
|
130
|
+
* needed to take, tag, describe, and prune pre-migration snapshots of this
|
|
131
|
+
* database. Actions and resource ARN segment derive from
|
|
132
|
+
* `this.getSnapshotTarget().kind`. Snapshot name glob is bound to
|
|
133
|
+
* `MIGRATION_SNAPSHOT_NAME_PREFIX`; the delete action can only ever match
|
|
134
|
+
* that glob (a Delete request's resource is a snapshot ARN, never the
|
|
135
|
+
* database ARN), confining pruning to premigrate snapshots.
|
|
133
136
|
*/
|
|
134
137
|
getMigrationSnapshotPolicy(): PolicyStatement;
|
|
135
138
|
/**
|
|
@@ -97,6 +97,7 @@ export declare class RdsAurora extends Construct implements IConnectable {
|
|
|
97
97
|
private databaseCredentials;
|
|
98
98
|
private cfnCluster?;
|
|
99
99
|
private databaseNameValue;
|
|
100
|
+
private backupRetentionDaysValue;
|
|
100
101
|
constructor(scope: Construct, id: string, props: RdsProps);
|
|
101
102
|
private buildReaders;
|
|
102
103
|
private addProxy;
|
|
@@ -108,6 +109,13 @@ export declare class RdsAurora extends Construct implements IConnectable {
|
|
|
108
109
|
getSnapshotTarget(): Extract<SnapshotTarget, {
|
|
109
110
|
kind: "cluster";
|
|
110
111
|
}>;
|
|
112
|
+
/**
|
|
113
|
+
* Effective automated-backup retention in whole days (the applied
|
|
114
|
+
* `backupRetention`, defaulted). Feeds `MIGRATION_SNAPSHOT_RETENTION_DAYS`
|
|
115
|
+
* so the migration runner prunes pre-migration snapshots against the same
|
|
116
|
+
* window the cluster's PITR actually covers.
|
|
117
|
+
*/
|
|
118
|
+
getBackupRetentionDays(): number;
|
|
111
119
|
getDatabaseName(): string;
|
|
112
120
|
getConnectionString(): string;
|
|
113
121
|
getCfnCluster(): CfnDBCluster | undefined;
|
|
@@ -62,6 +62,7 @@ export class RdsAurora extends Construct {
|
|
|
62
62
|
databaseCredentials;
|
|
63
63
|
cfnCluster;
|
|
64
64
|
databaseNameValue;
|
|
65
|
+
backupRetentionDaysValue;
|
|
65
66
|
constructor(scope, id, props) {
|
|
66
67
|
super(scope, id);
|
|
67
68
|
validateServerlessV2DevKnobs(props);
|
|
@@ -163,6 +164,8 @@ export class RdsAurora extends Construct {
|
|
|
163
164
|
const vpcSubnets = props.publiclyAccessible
|
|
164
165
|
? { subnetType: SubnetType.PUBLIC }
|
|
165
166
|
: { subnetType: SubnetType.PRIVATE_WITH_EGRESS };
|
|
167
|
+
this.backupRetentionDaysValue =
|
|
168
|
+
props.backupRetention ?? RDS_DEFAULTS.BACKUP_RETENTION_DEFAULT_DAYS;
|
|
166
169
|
// Common props shared across all cluster creation paths
|
|
167
170
|
const baseClusterProps = {
|
|
168
171
|
vpc: props.vpc,
|
|
@@ -171,7 +174,7 @@ export class RdsAurora extends Construct {
|
|
|
171
174
|
engine,
|
|
172
175
|
parameterGroup,
|
|
173
176
|
backup: {
|
|
174
|
-
retention: Duration.days(
|
|
177
|
+
retention: Duration.days(this.backupRetentionDaysValue)
|
|
175
178
|
},
|
|
176
179
|
storageEncrypted: true,
|
|
177
180
|
...(storageEncryptionKey && { storageEncryptionKey }),
|
|
@@ -361,6 +364,15 @@ export class RdsAurora extends Construct {
|
|
|
361
364
|
getSnapshotTarget() {
|
|
362
365
|
return { kind: "cluster", arn: this.databaseCluster.clusterArn };
|
|
363
366
|
}
|
|
367
|
+
/**
|
|
368
|
+
* Effective automated-backup retention in whole days (the applied
|
|
369
|
+
* `backupRetention`, defaulted). Feeds `MIGRATION_SNAPSHOT_RETENTION_DAYS`
|
|
370
|
+
* so the migration runner prunes pre-migration snapshots against the same
|
|
371
|
+
* window the cluster's PITR actually covers.
|
|
372
|
+
*/
|
|
373
|
+
getBackupRetentionDays() {
|
|
374
|
+
return this.backupRetentionDaysValue;
|
|
375
|
+
}
|
|
364
376
|
getDatabaseName() {
|
|
365
377
|
return this.databaseNameValue;
|
|
366
378
|
}
|
|
@@ -81,6 +81,13 @@ export declare class RdsAuroraGlobal extends Construct implements IConnectable {
|
|
|
81
81
|
kind: "cluster";
|
|
82
82
|
}>;
|
|
83
83
|
getDatabaseName(): string;
|
|
84
|
+
/**
|
|
85
|
+
* Effective automated-backup retention in whole days, delegated to the
|
|
86
|
+
* regional cluster that actually applies the default. Feeds
|
|
87
|
+
* `MIGRATION_SNAPSHOT_RETENTION_DAYS` so the migration runner prunes
|
|
88
|
+
* pre-migration snapshots against the same window PITR actually covers.
|
|
89
|
+
*/
|
|
90
|
+
getBackupRetentionDays(): number;
|
|
84
91
|
getConnectionString(): string;
|
|
85
92
|
}
|
|
86
93
|
export {};
|
|
@@ -182,6 +182,21 @@ export class RdsAuroraGlobal extends Construct {
|
|
|
182
182
|
return this.regionalCluster.getDatabaseName();
|
|
183
183
|
throw new Error("No Aurora cluster available to return database name from");
|
|
184
184
|
}
|
|
185
|
+
/**
|
|
186
|
+
* Effective automated-backup retention in whole days, delegated to the
|
|
187
|
+
* regional cluster that actually applies the default. Feeds
|
|
188
|
+
* `MIGRATION_SNAPSHOT_RETENTION_DAYS` so the migration runner prunes
|
|
189
|
+
* pre-migration snapshots against the same window PITR actually covers.
|
|
190
|
+
*/
|
|
191
|
+
getBackupRetentionDays() {
|
|
192
|
+
if (this.primaryCluster) {
|
|
193
|
+
return this.primaryCluster.getBackupRetentionDays();
|
|
194
|
+
}
|
|
195
|
+
if (this.regionalCluster) {
|
|
196
|
+
return this.regionalCluster.getBackupRetentionDays();
|
|
197
|
+
}
|
|
198
|
+
throw new Error("No Aurora cluster available to return backup retention from");
|
|
199
|
+
}
|
|
185
200
|
getConnectionString() {
|
|
186
201
|
if (this.primaryCluster)
|
|
187
202
|
return this.primaryCluster.getConnectionString();
|
|
@@ -71,6 +71,7 @@ export declare class RdsInstance extends Construct implements IConnectable {
|
|
|
71
71
|
private databaseProxySecurityGroup?;
|
|
72
72
|
private readReplicaSecurityGroup?;
|
|
73
73
|
private databaseNameValue;
|
|
74
|
+
private backupRetentionDaysValue;
|
|
74
75
|
private readonly constructId;
|
|
75
76
|
constructor(scope: Construct, id: string, props: RdsProps);
|
|
76
77
|
private addDatabase;
|
|
@@ -84,6 +85,13 @@ export declare class RdsInstance extends Construct implements IConnectable {
|
|
|
84
85
|
getSnapshotTarget(): Extract<SnapshotTarget, {
|
|
85
86
|
kind: "instance";
|
|
86
87
|
}>;
|
|
88
|
+
/**
|
|
89
|
+
* Effective automated-backup retention in whole days (the applied
|
|
90
|
+
* `backupRetention`, defaulted). Feeds `MIGRATION_SNAPSHOT_RETENTION_DAYS`
|
|
91
|
+
* so the migration runner prunes pre-migration snapshots against the same
|
|
92
|
+
* window the instance's PITR actually covers.
|
|
93
|
+
*/
|
|
94
|
+
getBackupRetentionDays(): number;
|
|
87
95
|
getDatabaseName(): string;
|
|
88
96
|
getConnectionString(): string;
|
|
89
97
|
/**
|
|
@@ -29,6 +29,7 @@ export class RdsInstance extends Construct {
|
|
|
29
29
|
databaseProxySecurityGroup;
|
|
30
30
|
readReplicaSecurityGroup;
|
|
31
31
|
databaseNameValue;
|
|
32
|
+
backupRetentionDaysValue;
|
|
32
33
|
constructId;
|
|
33
34
|
constructor(scope, id, props) {
|
|
34
35
|
super(scope, id);
|
|
@@ -121,6 +122,11 @@ export class RdsInstance extends Construct {
|
|
|
121
122
|
const subnetType = props.publiclyAccessible
|
|
122
123
|
? SubnetType.PUBLIC
|
|
123
124
|
: SubnetType.PRIVATE_WITH_EGRESS;
|
|
125
|
+
const backupRetention = props.backupRetention ??
|
|
126
|
+
Duration.days(RDS_DEFAULTS.BACKUP_RETENTION_DEFAULT_DAYS);
|
|
127
|
+
// toDays() throws on a fractional Duration — same whole-days contract the
|
|
128
|
+
// L2 DatabaseInstance enforces, surfaced at synth either way.
|
|
129
|
+
this.backupRetentionDaysValue = backupRetention.toDays();
|
|
124
130
|
const commonInstanceProps = {
|
|
125
131
|
vpc: this.vpc,
|
|
126
132
|
vpcSubnets: {
|
|
@@ -130,8 +136,7 @@ export class RdsInstance extends Construct {
|
|
|
130
136
|
engine,
|
|
131
137
|
parameterGroup,
|
|
132
138
|
allocatedStorage: props.allocatedStorage,
|
|
133
|
-
backupRetention
|
|
134
|
-
Duration.days(RDS_DEFAULTS.BACKUP_RETENTION_DEFAULT_DAYS),
|
|
139
|
+
backupRetention,
|
|
135
140
|
preferredBackupWindow: props.preferredBackupWindow ?? "02:00-03:00",
|
|
136
141
|
storageEncrypted: true,
|
|
137
142
|
storageEncryptionKey,
|
|
@@ -357,6 +362,15 @@ exports.handler = async (event) => {
|
|
|
357
362
|
getSnapshotTarget() {
|
|
358
363
|
return { kind: "instance", arn: this.database.instanceArn };
|
|
359
364
|
}
|
|
365
|
+
/**
|
|
366
|
+
* Effective automated-backup retention in whole days (the applied
|
|
367
|
+
* `backupRetention`, defaulted). Feeds `MIGRATION_SNAPSHOT_RETENTION_DAYS`
|
|
368
|
+
* so the migration runner prunes pre-migration snapshots against the same
|
|
369
|
+
* window the instance's PITR actually covers.
|
|
370
|
+
*/
|
|
371
|
+
getBackupRetentionDays() {
|
|
372
|
+
return this.backupRetentionDaysValue;
|
|
373
|
+
}
|
|
360
374
|
getDatabaseName() {
|
|
361
375
|
return this.databaseNameValue;
|
|
362
376
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fjall/components-infrastructure",
|
|
3
|
-
"version": "27.
|
|
3
|
+
"version": "27.1.0",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/fjall-tech/fjall.git",
|
|
@@ -78,8 +78,8 @@
|
|
|
78
78
|
},
|
|
79
79
|
"dependencies": {
|
|
80
80
|
"@aws-sdk/client-organizations": "^3.1098.0",
|
|
81
|
-
"@fjall/generator": "^27.
|
|
82
|
-
"@fjall/util": "^27.
|
|
81
|
+
"@fjall/generator": "^27.1.0",
|
|
82
|
+
"@fjall/util": "^27.1.0",
|
|
83
83
|
"constructs": "^10.7.2",
|
|
84
84
|
"zod": "^4.4.3"
|
|
85
85
|
},
|