From 96b0f18b50d9e420e032eb91e9742f7462eb03f5 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 1 Apr 2026 17:17:39 +0200 Subject: [PATCH 1/8] refactor: switch aws rds provider --- src/components/database/index.ts | 43 ++++++++++++++++---------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/components/database/index.ts b/src/components/database/index.ts index b539d1fc..61d1b95d 100644 --- a/src/components/database/index.ts +++ b/src/components/database/index.ts @@ -1,5 +1,4 @@ import * as aws from '@pulumi/aws'; -import * as awsNative from '@pulumi/aws-native'; import * as awsx from '@pulumi/awsx'; import * as pulumi from '@pulumi/pulumi'; import { commonTags } from '../../shared/common-tags'; @@ -17,6 +16,7 @@ export namespace Database { allowMajorVersionUpgrade?: pulumi.Input; autoMinorVersionUpgrade?: pulumi.Input; applyImmediately?: pulumi.Input; + skipFinalSnapshot?: pulumi.Input; }; export type Credentials = { @@ -66,6 +66,7 @@ export namespace Database { const defaults = { multiAz: false, applyImmediately: false, + skipFinalSnapshot: false, allocatedStorage: 20, maxAllocatedStorage: 100, instanceClass: 'db.t4g.micro', @@ -77,7 +78,7 @@ const defaults = { export class Database extends pulumi.ComponentResource { name: string; - instance: awsNative.rds.DbInstance; + instance: aws.rds.Instance; vpc: pulumi.Output; dbSubnetGroup: aws.rds.SubnetGroup; dbSecurityGroup: aws.ec2.SecurityGroup; @@ -285,29 +286,31 @@ export class Database extends pulumi.ComponentResource { } private createDatabaseInstance(args: Database.Args) { + const stack = pulumi.getStack(); + const monitoringOptions = args.enableMonitoring && this.monitoringRole ? { monitoringInterval: 60, monitoringRoleArn: this.monitoringRole.arn, - enablePerformanceInsights: true, + performanceInsightsEnabled: true, performanceInsightsRetentionPeriod: 7, } : {}; - const instance = new awsNative.rds.DbInstance( + const instance = new aws.rds.Instance( `${this.name}-rds`, { - dbInstanceIdentifier: `${this.name}-db-instance`, + identifierPrefix: `${this.name}-`, engine: 'postgres', engineVersion: args.engineVersion, - dbInstanceClass: args.instanceClass, + instanceClass: args.instanceClass!, dbName: args.dbName, - masterUsername: args.username, - masterUserPassword: this.password.value, + username: args.username, + password: this.password.value, dbSubnetGroupName: this.dbSubnetGroup.name, - vpcSecurityGroups: [this.dbSecurityGroup.id], - allocatedStorage: args.allocatedStorage?.toString(), + vpcSecurityGroupIds: [this.dbSecurityGroup.id], + allocatedStorage: args.allocatedStorage, maxAllocatedStorage: args.maxAllocatedStorage, multiAz: args.multiAz, applyImmediately: args.applyImmediately, @@ -316,21 +319,17 @@ export class Database extends pulumi.ComponentResource { kmsKeyId: this.kmsKeyId, storageEncrypted: true, publiclyAccessible: false, - preferredMaintenanceWindow: 'Mon:07:00-Mon:07:30', - preferredBackupWindow: '06:00-06:30', + skipFinalSnapshot: args.skipFinalSnapshot, + maintenanceWindow: 'Mon:07:00-Mon:07:30', + finalSnapshotIdentifier: `${this.name}-final-snapshot-${stack}`, + backupWindow: '06:00-06:30', backupRetentionPeriod: 14, - caCertificateIdentifier: 'rds-ca-rsa2048-g1', - dbParameterGroupName: args.parameterGroupName, - dbSnapshotIdentifier: + caCertIdentifier: 'rds-ca-rsa2048-g1', + parameterGroupName: args.parameterGroupName, + snapshotIdentifier: this.encryptedSnapshotCopy?.targetDbSnapshotIdentifier, ...monitoringOptions, - tags: pulumi - .output(args.tags) - .apply(tags => [ - ...Object.entries({ ...commonTags, ...tags }).map( - ([key, value]) => ({ key, value }), - ), - ]), + tags: { ...commonTags, ...args.tags }, }, { parent: this, dependsOn: [this.password] }, ); From 043a353a3fbfc067c5347685c50ac410dba3270f Mon Sep 17 00:00:00 2001 From: mandryllo Date: Wed, 1 Apr 2026 17:19:31 +0200 Subject: [PATCH 2/8] test: update defaultDb and configurableDb tests --- tests/database/configurable-db.test.ts | 21 +++++++++++++-------- tests/database/index.test.ts | 12 ++++++------ tests/database/infrastructure/config.ts | 1 + tests/database/infrastructure/index.ts | 2 ++ tests/database/test-context.ts | 1 + 5 files changed, 23 insertions(+), 14 deletions(-) diff --git a/tests/database/configurable-db.test.ts b/tests/database/configurable-db.test.ts index b21bd3e6..32cd774b 100644 --- a/tests/database/configurable-db.test.ts +++ b/tests/database/configurable-db.test.ts @@ -23,7 +23,7 @@ export function testConfigurableDb(ctx: DatabaseTestContext) { assert.ok(configurableDb.instance, 'Database instance should be defined'); const command = new DescribeDBInstancesCommand({ - DBInstanceIdentifier: configurableDb.instance.dbInstanceIdentifier, + DBInstanceIdentifier: configurableDb.instance.identifier, }); const { DBInstances } = await ctx.clients.rds.send(command); @@ -34,7 +34,7 @@ export function testConfigurableDb(ctx: DatabaseTestContext) { const [DBInstance] = DBInstances; assert.strictEqual( DBInstance.DBInstanceIdentifier, - configurableDb.instance.dbInstanceIdentifier, + configurableDb.instance.identifier, 'Database instance identifier should match', ); }); @@ -57,6 +57,11 @@ export function testConfigurableDb(ctx: DatabaseTestContext) { ctx.config.autoMinorVersionUpgrade, 'Auto minor version upgrade argument should be set correctly', ); + assert.strictEqual( + configurableDb.instance.skipFinalSnapshot, + ctx.config.skipFinalSnapshot, + 'Skip final snapshot argument should be set correctly', + ); }); it('should properly configure password', () => { @@ -64,9 +69,9 @@ export function testConfigurableDb(ctx: DatabaseTestContext) { assert.ok(configurableDb.password, 'Password should exist'); assert.strictEqual( - configurableDb.instance.masterUserPassword, + configurableDb.instance.password, ctx.config.dbPassword, - 'Master user password should be set correctly', + 'Password should be set correctly', ); }); @@ -75,7 +80,7 @@ export function testConfigurableDb(ctx: DatabaseTestContext) { assert.strictEqual( configurableDb.instance.allocatedStorage, - ctx.config.allocatedStorage.toString(), + ctx.config.allocatedStorage, 'Allocated storage argument should be set correctly', ); assert.strictEqual( @@ -89,7 +94,7 @@ export function testConfigurableDb(ctx: DatabaseTestContext) { const configurableDb = ctx.outputs.configurableDb.value; assert.strictEqual( - configurableDb.instance.enablePerformanceInsights, + configurableDb.instance.performanceInsightsEnabled, true, 'Performance insights should be enabled', ); @@ -152,7 +157,7 @@ export function testConfigurableDb(ctx: DatabaseTestContext) { const paramGroup = ctx.outputs.paramGroup.value; assert.strictEqual( - configurableDb.instance.dbParameterGroupName, + configurableDb.instance.parameterGroupName, paramGroup.name, 'Parameter group name should be set correctly', ); @@ -162,7 +167,7 @@ export function testConfigurableDb(ctx: DatabaseTestContext) { const configurableDb = ctx.outputs.configurableDb.value; const command = new ListTagsForResourceCommand({ - ResourceName: configurableDb.instance.dbInstanceArn, + ResourceName: configurableDb.instance.arn, }); const { TagList } = await ctx.clients.rds.send(command); assert.ok(TagList && TagList.length > 0, 'Tags should exist'); diff --git a/tests/database/index.test.ts b/tests/database/index.test.ts index f688ac0e..af9d9b26 100644 --- a/tests/database/index.test.ts +++ b/tests/database/index.test.ts @@ -72,7 +72,7 @@ describe('Database component deployment', () => { assert.ok(database.instance, 'Database instance should be defined'); const command = new DescribeDBInstancesCommand({ - DBInstanceIdentifier: database.instance.dbInstanceIdentifier, + DBInstanceIdentifier: database.instance.identifier, }); const { DBInstances } = await ctx.clients.rds.send(command); @@ -83,7 +83,7 @@ describe('Database component deployment', () => { const [DBInstance] = DBInstances; assert.strictEqual( DBInstance.DBInstanceIdentifier, - database.instance.dbInstanceIdentifier, + database.instance.identifier, 'Database instance identifier should match', ); }); @@ -104,13 +104,13 @@ describe('Database component deployment', () => { instance, { dbName: ctx.config.dbName, - masterUsername: ctx.config.dbUsername, + username: ctx.config.dbUsername, multiAz: false, applyImmediately: false, - allocatedStorage: '20', + allocatedStorage: 20, maxAllocatedStorage: 100, - dbInstanceClass: 'db.t4g.micro', - enablePerformanceInsights: false, + instanceClass: 'db.t4g.micro', + performanceInsightsEnabled: false, allowMajorVersionUpgrade: false, autoMinorVersionUpgrade: true, engineVersion: '17.2', diff --git a/tests/database/infrastructure/config.ts b/tests/database/infrastructure/config.ts index d43d12ba..78f7324e 100644 --- a/tests/database/infrastructure/config.ts +++ b/tests/database/infrastructure/config.ts @@ -12,5 +12,6 @@ export const dbPassword = 'dbpassword'; export const applyImmediately = true; export const allowMajorVersionUpgrade = true; export const autoMinorVersionUpgrade = false; +export const skipFinalSnapshot = true; export const allocatedStorage = 10; export const maxAllocatedStorage = 50; diff --git a/tests/database/infrastructure/index.ts b/tests/database/infrastructure/index.ts index 87d7ca49..d32881bb 100644 --- a/tests/database/infrastructure/index.ts +++ b/tests/database/infrastructure/index.ts @@ -14,6 +14,7 @@ const vpc = util.getCommonVpc(); const defaultDb = new studion.DatabaseBuilder(`${config.appName}-default-db`) .withInstance({ dbName: config.dbName, + skipFinalSnapshot: true, }) .withCredentials({ username: config.dbUsername, @@ -52,6 +53,7 @@ const configurableDb = new studion.DatabaseBuilder( applyImmediately: config.applyImmediately, allowMajorVersionUpgrade: config.allowMajorVersionUpgrade, autoMinorVersionUpgrade: config.autoMinorVersionUpgrade, + skipFinalSnapshot: config.skipFinalSnapshot, }) .withCredentials({ username: config.dbUsername, diff --git a/tests/database/test-context.ts b/tests/database/test-context.ts index f86866c5..543f8f63 100644 --- a/tests/database/test-context.ts +++ b/tests/database/test-context.ts @@ -22,6 +22,7 @@ interface DatabaseTestConfig { applyImmediately: boolean; allowMajorVersionUpgrade: boolean; autoMinorVersionUpgrade: boolean; + skipFinalSnapshot: boolean; allocatedStorage: number; maxAllocatedStorage: number; } From 99cb75b66f5c712076818eab1ea328977c51b277 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Thu, 2 Apr 2026 13:47:49 +0200 Subject: [PATCH 3/8] test: update snapshotdb tests --- tests/database/infrastructure/index.ts | 26 ++++++++++++-------------- tests/database/snapshot-db.test.ts | 8 ++++---- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/tests/database/infrastructure/index.ts b/tests/database/infrastructure/index.ts index d32881bb..edd23897 100644 --- a/tests/database/infrastructure/index.ts +++ b/tests/database/infrastructure/index.ts @@ -70,24 +70,22 @@ const configurableDb = new studion.DatabaseBuilder( .withTags(config.tags) .build({ parent }); -const snapshot = defaultDb.instance.dbInstanceIdentifier.apply( - dbInstanceIdentifier => { - return new aws.rds.Snapshot( - `${config.appName}-snapshot`, - { - dbInstanceIdentifier: dbInstanceIdentifier!, - dbSnapshotIdentifier: `${config.appName}-snapshot-id`, - tags: config.tags, - }, - { parent }, - ); - }, -); +const snapshot = defaultDb.instance.identifier.apply(identifier => { + return new aws.rds.Snapshot( + `${config.appName}-snapshot`, + { + dbInstanceIdentifier: identifier!, + dbSnapshotIdentifier: `${config.appName}-snapshot-id`, + tags: config.tags, + }, + { parent }, + ); +}); const snapshotDb = snapshot.apply(snapshot => { return new studion.DatabaseBuilder(`${config.appName}-snapshot-db`) .withInstance({ - applyImmediately: true, + skipFinalSnapshot: true, }) .withVpc(vpc.vpc) .withTags(config.tags) diff --git a/tests/database/snapshot-db.test.ts b/tests/database/snapshot-db.test.ts index c7131470..f5ff43ee 100644 --- a/tests/database/snapshot-db.test.ts +++ b/tests/database/snapshot-db.test.ts @@ -16,7 +16,7 @@ export function testSnapshotDb(ctx: DatabaseTestContext) { assert.ok(snapshotDb.instance, 'Database instance should be defined'); const command = new DescribeDBInstancesCommand({ - DBInstanceIdentifier: snapshotDb.instance.dbInstanceIdentifier, + DBInstanceIdentifier: snapshotDb.instance.identifier, }); const { DBInstances } = await ctx.clients.rds.send(command); @@ -27,7 +27,7 @@ export function testSnapshotDb(ctx: DatabaseTestContext) { const [DBInstance] = DBInstances; assert.strictEqual( DBInstance.DBInstanceIdentifier, - snapshotDb.instance.dbInstanceIdentifier, + snapshotDb.instance.identifier, 'Database instance identifier should match', ); }); @@ -66,9 +66,9 @@ export function testSnapshotDb(ctx: DatabaseTestContext) { const snapshotDb = ctx.outputs.snapshotDb.value; assert.strictEqual( - snapshotDb.instance.dbSnapshotIdentifier, + snapshotDb.instance.snapshotIdentifier, snapshotDb.encryptedSnapshotCopy.targetDbSnapshotIdentifier, - 'Db snapshot identifier should be set correctly', + 'Snapshot identifier should be set correctly', ); }); } From e0092f487dea8e3c66b5185cd0c2bff3c80cce4e Mon Sep 17 00:00:00 2001 From: mandryllo Date: Thu, 2 Apr 2026 13:49:06 +0200 Subject: [PATCH 4/8] refactor: update replica --- src/components/database/database-replica.ts | 1 + src/components/database/index.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/database/database-replica.ts b/src/components/database/database-replica.ts index 2395214b..bb09ed14 100644 --- a/src/components/database/database-replica.ts +++ b/src/components/database/database-replica.ts @@ -102,6 +102,7 @@ export class DatabaseReplica extends pulumi.ComponentResource { applyImmediately: argsWithDefaults.applyImmediately, allowMajorVersionUpgrade: argsWithDefaults.allowMajorVersionUpgrade, autoMinorVersionUpgrade: argsWithDefaults.autoMinorVersionUpgrade, + maintenanceWindow: 'Mon:07:00-Mon:07:30', replicateSourceDb: argsWithDefaults.replicateSourceDb, parameterGroupName: argsWithDefaults.parameterGroupName, storageEncrypted: true, diff --git a/src/components/database/index.ts b/src/components/database/index.ts index 61d1b95d..8dd6f571 100644 --- a/src/components/database/index.ts +++ b/src/components/database/index.ts @@ -263,7 +263,7 @@ export class Database extends pulumi.ComponentResource { const replica = new DatabaseReplica( `${this.name}-replica`, { - replicateSourceDb: this.instance.dbInstanceIdentifier.apply(id => id!), + replicateSourceDb: this.instance.identifier.apply(id => id!), dbSecurityGroup: this.dbSecurityGroup, monitoringRole, ...config, From 041b9011b1ea73c06e2673bf018c1072e02ee18d Mon Sep 17 00:00:00 2001 From: mandryllo Date: Thu, 2 Apr 2026 13:49:35 +0200 Subject: [PATCH 5/8] test: update replica db tests --- tests/database/configurable-replica-db.test.ts | 6 +++--- tests/database/infrastructure/index.ts | 2 ++ tests/database/replica-db.test.ts | 14 +++++++------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/tests/database/configurable-replica-db.test.ts b/tests/database/configurable-replica-db.test.ts index 78b8cf12..e8aea512 100644 --- a/tests/database/configurable-replica-db.test.ts +++ b/tests/database/configurable-replica-db.test.ts @@ -9,17 +9,17 @@ import { it } from 'node:test'; export function testConfigurableReplica(ctx: DatabaseTestContext) { it('should create a primary instance with a configurable replica', async () => { const configurableReplicaDb = ctx.outputs.configurableReplicaDb.value; - const { dbInstanceIdentifier } = configurableReplicaDb.instance; + const { identifier } = configurableReplicaDb.instance; const command = new DescribeDBInstancesCommand({ - DBInstanceIdentifier: dbInstanceIdentifier, + DBInstanceIdentifier: identifier, }); const { DBInstances } = await ctx.clients.rds.send(command); assert.ok( DBInstances && DBInstances.length === 1 && - DBInstances[0].DBInstanceIdentifier === dbInstanceIdentifier, + DBInstances[0].DBInstanceIdentifier === identifier, 'Primary database instance should be created', ); }); diff --git a/tests/database/infrastructure/index.ts b/tests/database/infrastructure/index.ts index edd23897..8957f3e2 100644 --- a/tests/database/infrastructure/index.ts +++ b/tests/database/infrastructure/index.ts @@ -96,6 +96,7 @@ const snapshotDb = snapshot.apply(snapshot => { const replicaDb = new studion.DatabaseBuilder(`${config.appName}-replica-db`) .withInstance({ dbName: config.dbName, + skipFinalSnapshot: true, }) .withCredentials({ username: config.dbUsername, @@ -109,6 +110,7 @@ const configurableReplicaDb = new studion.DatabaseBuilder( ) .withInstance({ dbName: config.dbName, + skipFinalSnapshot: true, }) .withCredentials({ username: config.dbUsername, diff --git a/tests/database/replica-db.test.ts b/tests/database/replica-db.test.ts index bc73ea91..f3db6373 100644 --- a/tests/database/replica-db.test.ts +++ b/tests/database/replica-db.test.ts @@ -6,17 +6,17 @@ import { it } from 'node:test'; export function testReplicaDb(ctx: DatabaseTestContext) { it('should create a primary instance with a replica', async () => { const replicaDb = ctx.outputs.replicaDb.value; - const { dbInstanceIdentifier } = replicaDb.instance; + const { identifier } = replicaDb.instance; const command = new DescribeDBInstancesCommand({ - DBInstanceIdentifier: dbInstanceIdentifier, + DBInstanceIdentifier: identifier, }); const { DBInstances } = await ctx.clients.rds.send(command); assert.ok( DBInstances && DBInstances.length === 1 && - DBInstances[0].DBInstanceIdentifier === dbInstanceIdentifier, + DBInstances[0].DBInstanceIdentifier === identifier, 'Primary database instance should be created', ); }); @@ -47,12 +47,12 @@ export function testReplicaDb(ctx: DatabaseTestContext) { assert.strictEqual( replicaInstance.replicateSourceDb, - dbInstance.dbInstanceIdentifier, + dbInstance.identifier, 'Replica instance should have correct source db instance identifier', ); const command = new DescribeDBInstancesCommand({ - DBInstanceIdentifier: dbInstance.dbInstanceIdentifier, + DBInstanceIdentifier: dbInstance.identifier, }); const { DBInstances } = await ctx.clients.rds.send(command); @@ -97,9 +97,9 @@ export function testReplicaDb(ctx: DatabaseTestContext) { storageEncrypted: true, publiclyAccessible: false, skipFinalSnapshot: true, - vpcSecurityGroupIds: primaryInstance.vpcSecurityGroups, + vpcSecurityGroupIds: primaryInstance.vpcSecurityGroupIds, dbSubnetGroupName: primaryInstance.dbSubnetGroupName, - parameterGroupName: primaryInstance.dbParameterGroupName, + parameterGroupName: primaryInstance.parameterGroupName, }, 'Replica instance should be configured correctly', ); From 3745a1ff813e3def33f1c98a4867c0cb9a3e361c Mon Sep 17 00:00:00 2001 From: mandryllo Date: Thu, 2 Apr 2026 13:49:50 +0200 Subject: [PATCH 6/8] test: update ssm connect db tests --- tests/database/infrastructure/index.ts | 1 + tests/database/ssm-connect.test.ts | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/tests/database/infrastructure/index.ts b/tests/database/infrastructure/index.ts index 8957f3e2..15a97086 100644 --- a/tests/database/infrastructure/index.ts +++ b/tests/database/infrastructure/index.ts @@ -134,6 +134,7 @@ const ssmConnectDb = new studion.DatabaseBuilder( ) .withInstance({ dbName: config.dbName, + skipFinalSnapshot: true, }) .withCredentials({ username: config.dbUsername, diff --git a/tests/database/ssm-connect.test.ts b/tests/database/ssm-connect.test.ts index dcfa4d7e..289be552 100644 --- a/tests/database/ssm-connect.test.ts +++ b/tests/database/ssm-connect.test.ts @@ -25,17 +25,17 @@ export function testSSMConnectDb(ctx: DatabaseTestContext) { it('should create a db instance', async () => { const ssmConnectDb = ctx.outputs.ssmConnectDb.value; - const { dbInstanceIdentifier } = ssmConnectDb.instance; + const { identifier } = ssmConnectDb.instance; const command = new DescribeDBInstancesCommand({ - DBInstanceIdentifier: dbInstanceIdentifier, + DBInstanceIdentifier: identifier, }); const { DBInstances } = await ctx.clients.rds.send(command); assert.ok( DBInstances && DBInstances.length === 1 && - DBInstances[0].DBInstanceIdentifier === dbInstanceIdentifier, + DBInstances[0].DBInstanceIdentifier === identifier, 'Database instance should be created', ); }); @@ -256,8 +256,8 @@ export function testSSMConnectDb(ctx: DatabaseTestContext) { it('EC2 instance should be able to connect to the database', async () => { const ssmConnectDb = ctx.outputs.ssmConnectDb.value; const instanceId = ssmConnectDb.ec2SSMConnect.ec2.id; - const dbHost = ssmConnectDb.instance.endpoint.address; - const dbPort = ssmConnectDb.instance.endpoint.port; + const dbHost = ssmConnectDb.instance.address; + const dbPort = ssmConnectDb.instance.port; const testCommand = ` if timeout 5 bash -c " Date: Thu, 2 Apr 2026 13:52:12 +0200 Subject: [PATCH 7/8] refactor: cleanup unused code and dependecies --- package-lock.json | 15 ----- package.json | 1 - tests/database/index.test.ts | 3 - tests/database/util.ts | 122 ----------------------------------- 4 files changed, 141 deletions(-) delete mode 100644 tests/database/util.ts diff --git a/package-lock.json b/package-lock.json index 61e810bc..87ce5207 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,6 @@ "license": "MIT", "dependencies": { "@pulumi/aws": "^7.23.0", - "@pulumi/aws-native": "^1.57.0", "@pulumi/awsx": "^3.3.0", "@pulumi/pulumi": "^3.226.0", "@pulumi/random": "^4.19.1", @@ -3168,7 +3167,6 @@ "integrity": "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@octokit/auth-token": "^6.0.0", "@octokit/graphql": "^9.0.3", @@ -3325,7 +3323,6 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", "license": "Apache-2.0", - "peer": true, "engines": { "node": ">=8.0.0" } @@ -3977,16 +3974,6 @@ "mime": "^2.0.0" } }, - "node_modules/@pulumi/aws-native": { - "version": "1.57.0", - "resolved": "https://registry.npmjs.org/@pulumi/aws-native/-/aws-native-1.57.0.tgz", - "integrity": "sha512-T9rzxRSQo5xNvjdxbCQZZ+n4CwwdQgMZlzioHH9BQEJxEM30kX+vQGL5B49JEKh9S0ufY1hPUFZSyZAyrXP8XQ==", - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "@pulumi/pulumi": "^3.142.0" - } - }, "node_modules/@pulumi/aws/node_modules/mime": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", @@ -5111,7 +5098,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -8923,7 +8909,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "devOptional": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/package.json b/package.json index 2f199be2..1a2cecd1 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,6 @@ "prettier": "@studion/prettier-config", "dependencies": { "@pulumi/aws": "^7.23.0", - "@pulumi/aws-native": "^1.57.0", "@pulumi/awsx": "^3.3.0", "@pulumi/pulumi": "^3.226.0", "@pulumi/random": "^4.19.1", diff --git a/tests/database/index.test.ts b/tests/database/index.test.ts index af9d9b26..4fd279f1 100644 --- a/tests/database/index.test.ts +++ b/tests/database/index.test.ts @@ -1,4 +1,3 @@ -import { cleanupReplicas, cleanupSnapshots } from './util'; import { describe, before, after } from 'node:test'; import { DescribeDBInstancesCommand, @@ -55,9 +54,7 @@ describe('Database component deployment', () => { }); after(async () => { - await cleanupReplicas(ctx); await automation.destroy(programArgs); - await cleanupSnapshots(ctx); }); it('should create a database', async () => { diff --git a/tests/database/util.ts b/tests/database/util.ts deleted file mode 100644 index bdaf66e7..00000000 --- a/tests/database/util.ts +++ /dev/null @@ -1,122 +0,0 @@ -import { - DBInstanceNotFoundFault, - DeleteDBInstanceCommand, - DeleteDBSnapshotCommand, - DescribeDBInstancesCommand, - DescribeDBSnapshotsCommand, -} from '@aws-sdk/client-rds'; -import { NonRetryableError, backOff } from '../util'; -import { createSpinner } from 'nanospinner'; -import { DatabaseTestContext } from './test-context'; -import * as studion from '@studion/infra-code-blocks'; - -export async function cleanupSnapshots(ctx: DatabaseTestContext) { - const spinner = createSpinner('Deleting snapshots...').start(); - - const dbs = [ - ctx.outputs.defaultDb.value, - ctx.outputs.configurableDb.value, - ctx.outputs.snapshotDb.value, - ctx.outputs.replicaDb.value, - ctx.outputs.configurableReplicaDb.value, - ctx.outputs.ssmConnectDb.value, - ]; - await Promise.all( - dbs.map(db => deleteSnapshot(ctx, db.instance.dbInstanceIdentifier)), - ); - - spinner.success({ text: 'Snapshots deleted' }); -} - -async function deleteSnapshot( - ctx: DatabaseTestContext, - DBInstanceIdentifier: string, -) { - const describeCommand = new DescribeDBSnapshotsCommand({ - DBInstanceIdentifier, - SnapshotType: 'manual', - }); - const { DBSnapshots } = await ctx.clients.rds.send(describeCommand); - - if (!DBSnapshots || !DBSnapshots.length) { - throw new Error('Snapshot not found'); - } - const [DBSnapshot] = DBSnapshots; - - const deleteCommand = new DeleteDBSnapshotCommand({ - DBSnapshotIdentifier: DBSnapshot.DBSnapshotIdentifier, - }); - await ctx.clients.rds.send(deleteCommand); -} - -export async function cleanupReplicas(ctx: DatabaseTestContext) { - const spinner = createSpinner('Deleting replicas...').start(); - - const dbs = [ - ctx.outputs.replicaDb.value, - ctx.outputs.configurableReplicaDb.value, - ]; - await Promise.all(dbs.map(db => deleteReplica(ctx, db))); - - spinner.success({ text: 'Replicas deleted' }); -} - -async function deleteReplica(ctx: DatabaseTestContext, db: studion.Database) { - const replicaDBInstanceId = db.replica!.instance - .identifier as unknown as string; - - try { - const deleteCommand = new DeleteDBInstanceCommand({ - DBInstanceIdentifier: replicaDBInstanceId, - SkipFinalSnapshot: true, - }); - - await ctx.clients.rds.send(deleteCommand); - } catch (err) { - if (err instanceof DBInstanceNotFoundFault) { - return; - } - - throw err; - } - - // Wait for replica to be deleted - await backOff(async () => { - try { - const describeCommand = new DescribeDBInstancesCommand({ - DBInstanceIdentifier: replicaDBInstanceId, - }); - const { DBInstances } = await ctx.clients.rds.send(describeCommand); - - if (DBInstances![0].DBInstanceStatus === 'deleting') { - throw new Error('DB instance still deleting'); - } - } catch (err) { - if (err instanceof DBInstanceNotFoundFault) { - return; - } - - throw err; - } - }); - - // Wait for primary instance to exit modifying state - await backOff(async () => { - try { - const primaryDBInstanceId = db.instance - .dbInstanceIdentifier as unknown as string; - const describeCommand = new DescribeDBInstancesCommand({ - DBInstanceIdentifier: primaryDBInstanceId, - }); - const { DBInstances } = await ctx.clients.rds.send(describeCommand); - - if (DBInstances![0].DBInstanceStatus === 'modifying') { - throw new Error('DB instance still modifying'); - } - } catch (err) { - if (err instanceof DBInstanceNotFoundFault) { - throw new NonRetryableError('Db instance not found', { cause: err }); - } - } - }); -} From 2772541e903ed36f695cd4947bd1627d355131b3 Mon Sep 17 00:00:00 2001 From: mandryllo Date: Thu, 2 Apr 2026 21:31:35 +0200 Subject: [PATCH 8/8] refactor: remove unused async await --- tests/database/index.test.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/database/index.test.ts b/tests/database/index.test.ts index 4fd279f1..8e141ff0 100644 --- a/tests/database/index.test.ts +++ b/tests/database/index.test.ts @@ -53,9 +53,7 @@ describe('Database component deployment', () => { ctx.outputs = await automation.deploy(programArgs); }); - after(async () => { - await automation.destroy(programArgs); - }); + after(() => automation.destroy(programArgs)); it('should create a database', async () => { const database = ctx.outputs.defaultDb.value;