From f83b176eb57f05aa60dacd58280f0d299bff4d82 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Tue, 16 Dec 2025 21:57:57 +0100 Subject: [PATCH 1/3] Add snapshot db integration tests --- tests/database/index.test.ts | 2 ++ tests/database/infrastructure/index.ts | 22 +++++++++++- tests/database/snapshot-db.test.ts | 41 +++++++++++++++++++++++ tests/database/utils/cleanup-snapshots.ts | 6 +++- 4 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 tests/database/snapshot-db.test.ts diff --git a/tests/database/index.test.ts b/tests/database/index.test.ts index f86fd7d..8339910 100644 --- a/tests/database/index.test.ts +++ b/tests/database/index.test.ts @@ -11,6 +11,7 @@ import { RDSClient } from '@aws-sdk/client-rds'; import { requireEnv } from '../util'; import { testCustomDb } from './custom-db.test'; import { testDefaultDb } from './default-db.test'; +import { testSnapshotDb } from './snapshot-db.test'; const programArgs: InlineProgramArgs = { stackName: 'dev', @@ -39,5 +40,6 @@ describe('Database component deployment', () => { describe('Default database', () => testDefaultDb(ctx)); describe('Custom database', () => testCustomDb(ctx)); + describe('Snapshot database', () => testSnapshotDb(ctx)); after(() => cleanupSnapshots(ctx)); }); diff --git a/tests/database/infrastructure/index.ts b/tests/database/infrastructure/index.ts index ada577b..c7c628c 100644 --- a/tests/database/infrastructure/index.ts +++ b/tests/database/infrastructure/index.ts @@ -55,4 +55,24 @@ const customDb = new DatabaseBuilder(`${config.appName}-custom`) .withTags(config.tags) .build(); -export { vpc, defaultDb, kms, paramGroup, customDb }; +const snapshot = defaultDb.instance.dbInstanceIdentifier.apply( + dbInstanceIdentifier => { + if (!dbInstanceIdentifier) return; + return new aws.rds.Snapshot(`${config.appName}-snapshot`, { + dbInstanceIdentifier: dbInstanceIdentifier, + dbSnapshotIdentifier: `${config.appName}-snap-db`, + tags: config.tags, + }); + }, +); + +const snapshotDb = snapshot.apply(snapshot => { + if (!snapshot) return; + return new DatabaseBuilder(`${config.appName}-snapshot`) + .withVpc(vpc.vpc) + .withTags(config.tags) + .withSnapshot(snapshot.id) + .build(); +}); + +export { vpc, defaultDb, kms, paramGroup, customDb, snapshot, snapshotDb }; diff --git a/tests/database/snapshot-db.test.ts b/tests/database/snapshot-db.test.ts new file mode 100644 index 0000000..cb2695e --- /dev/null +++ b/tests/database/snapshot-db.test.ts @@ -0,0 +1,41 @@ +import * as assert from 'node:assert'; +import { DatabaseTestContext } from './test-context'; +import { it } from 'node:test'; + +export function testSnapshotDb(ctx: DatabaseTestContext) { + it('should create and properly configure encrypted snapshot copy', () => { + const snapshotDb = ctx.outputs.snapshotDb.value; + const snapshot = ctx.outputs.snapshot.value; + + assert.ok( + snapshotDb.encryptedSnapshotCopy, + 'Encrtyped snapshot copy should exist', + ); + + assert.strictEqual( + snapshotDb.encryptedSnapshotCopy.sourceDbSnapshotIdentifier, + snapshot.dbSnapshotArn, + 'Encrtyped snapshot copy should have correct source db snapshot identifier', + ); + assert.strictEqual( + snapshotDb.encryptedSnapshotCopy.targetDbSnapshotIdentifier, + `${snapshot.id}-encrypted-copy`, + 'Encrtyped snapshot copy should have the correct target db snapshot identifier', + ); + assert.strictEqual( + snapshotDb.encryptedSnapshotCopy.kmsKeyId, + snapshotDb.kmsKeyId, + 'Encrtyped snapshot copy should have the correct ksm key id', + ); + }); + + it('should properly configure instance', () => { + const snapshotDb = ctx.outputs.snapshotDb.value; + + assert.strictEqual( + snapshotDb.instance.dbSnapshotIdentifier, + snapshotDb.encryptedSnapshotCopy.targetDbSnapshotIdentifier, + 'Db snapshot identifier should be set correctly', + ); + }); +} diff --git a/tests/database/utils/cleanup-snapshots.ts b/tests/database/utils/cleanup-snapshots.ts index c43d036..e895270 100644 --- a/tests/database/utils/cleanup-snapshots.ts +++ b/tests/database/utils/cleanup-snapshots.ts @@ -8,7 +8,11 @@ import { DatabaseTestContext } from '../test-context'; export async function cleanupSnapshots(ctx: DatabaseTestContext) { const spinner = createSpinner('Deleting snapshots...').start(); - const dbs = [ctx.outputs.defaultDb.value, ctx.outputs.customDb.value]; + const dbs = [ + ctx.outputs.defaultDb.value, + ctx.outputs.customDb.value, + ctx.outputs.snapshotDb.value, + ]; await Promise.all( dbs.map(db => deleteSnapshot(ctx, db.instance.dbInstanceIdentifier)), ); From 7c0ff49673a1af46e0492180814834a8bd9cb850 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 17 Dec 2025 11:30:13 +0100 Subject: [PATCH 2/3] Fix issues when destroying stack --- tests/database/infrastructure/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/database/infrastructure/index.ts b/tests/database/infrastructure/index.ts index c7c628c..d247e29 100644 --- a/tests/database/infrastructure/index.ts +++ b/tests/database/infrastructure/index.ts @@ -69,6 +69,9 @@ const snapshot = defaultDb.instance.dbInstanceIdentifier.apply( const snapshotDb = snapshot.apply(snapshot => { if (!snapshot) return; return new DatabaseBuilder(`${config.appName}-snapshot`) + .withInstance({ + applyImmediately: true, + }) .withVpc(vpc.vpc) .withTags(config.tags) .withSnapshot(snapshot.id) From e27313619da7f853bbfaf702f031933c50947dbb Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 17 Dec 2025 15:16:57 +0100 Subject: [PATCH 3/3] Renaming --- tests/database/default-db.test.ts | 2 +- tests/database/infrastructure/index.ts | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/database/default-db.test.ts b/tests/database/default-db.test.ts index eaac25f..4e3a4e0 100644 --- a/tests/database/default-db.test.ts +++ b/tests/database/default-db.test.ts @@ -18,7 +18,7 @@ export function testDefaultDb(ctx: DatabaseTestContext) { assert.ok(database, 'Database should be defined'); assert.strictEqual( database.name, - `${ctx.config.appName}-default`, + `${ctx.config.appName}-default-db`, 'Database should have correct name', ); diff --git a/tests/database/infrastructure/index.ts b/tests/database/infrastructure/index.ts index d247e29..85d15bb 100644 --- a/tests/database/infrastructure/index.ts +++ b/tests/database/infrastructure/index.ts @@ -5,7 +5,7 @@ import * as config from './config'; const vpc = new studion.Vpc(`${config.appName}-vpc`, {}); -const defaultDb = new DatabaseBuilder(`${config.appName}-default`) +const defaultDb = new DatabaseBuilder(`${config.appName}-default-db`) .withInstance({ dbName: config.dbName, }) @@ -15,7 +15,7 @@ const defaultDb = new DatabaseBuilder(`${config.appName}-default`) .withVpc(vpc.vpc) .build(); -const kms = new aws.kms.Key(`${config.appName}-kms`, { +const kms = new aws.kms.Key(`${config.appName}-kms-key`, { description: `${config.appName} RDS encryption key`, customerMasterKeySpec: 'SYMMETRIC_DEFAULT', isEnabled: true, @@ -33,7 +33,7 @@ const paramGroup = new aws.rds.ParameterGroup( }, ); -const customDb = new DatabaseBuilder(`${config.appName}-custom`) +const customDb = new DatabaseBuilder(`${config.appName}-custom-db`) .withInstance({ dbName: config.dbName, applyImmediately: config.applyImmediately, @@ -60,7 +60,7 @@ const snapshot = defaultDb.instance.dbInstanceIdentifier.apply( if (!dbInstanceIdentifier) return; return new aws.rds.Snapshot(`${config.appName}-snapshot`, { dbInstanceIdentifier: dbInstanceIdentifier, - dbSnapshotIdentifier: `${config.appName}-snap-db`, + dbSnapshotIdentifier: `${config.appName}-snapshot-id`, tags: config.tags, }); }, @@ -68,7 +68,7 @@ const snapshot = defaultDb.instance.dbInstanceIdentifier.apply( const snapshotDb = snapshot.apply(snapshot => { if (!snapshot) return; - return new DatabaseBuilder(`${config.appName}-snapshot`) + return new DatabaseBuilder(`${config.appName}-snapshot-db`) .withInstance({ applyImmediately: true, })