Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
7b8bac4
Create db v2 component
mandryllo Dec 2, 2025
396e648
Remove ability to create custom parameter group
mandryllo Dec 5, 2025
b295e28
Cleanup
mandryllo Dec 5, 2025
35bc5cb
Fix kms key id type
mandryllo Dec 5, 2025
19c3ece
Cleanup
mandryllo Dec 5, 2025
ce83def
Cleanup vpc parameters
mandryllo Dec 5, 2025
292b549
Cleanup types
mandryllo Dec 5, 2025
d4120ce
Fix formatting
mandryllo Dec 5, 2025
b09a6c0
Cleanup
mandryllo Dec 8, 2025
53061fe
Create db builder component
mandryllo Dec 2, 2025
c32427b
Fix typo
mandryllo Dec 3, 2025
cb12a13
Remove custom parameter group args
mandryllo Dec 5, 2025
784af7f
Cleanup private props
mandryllo Dec 5, 2025
4df9363
Remove parameter group name from builder
mandryllo Dec 5, 2025
b439523
Cleanup naming
mandryllo Dec 5, 2025
0195797
Fix formatting
mandryllo Dec 5, 2025
2d399cf
Cleanup
mandryllo Dec 8, 2025
b17a54f
Expose db v2 components
mandryllo Dec 3, 2025
def9885
Add type tests
mandryllo Dec 8, 2025
9cc3856
Add default db tests
mandryllo Dec 8, 2025
bb298bc
Cleanup database types
mandryllo Dec 10, 2025
6af2d1b
Cleanup
mandryllo Dec 10, 2025
950fe1a
Revert allocatedStorage type to number
mandryllo Dec 10, 2025
ff389f9
Remove withKms method from builder
mandryllo Dec 10, 2025
817f100
Update type tests
mandryllo Dec 10, 2025
0605888
Update integration tests
mandryllo Dec 10, 2025
15927fe
fix tags
mandryllo Dec 10, 2025
f72366f
Fix snapshot id
mandryllo Dec 10, 2025
3b4d3e5
Remove export
mandryllo Dec 10, 2025
ef9fea4
Fix imports in tests
mandryllo Dec 10, 2025
c826e12
Fix wrong condition
mandryllo Dec 11, 2025
20a59e3
Cleanup final snapshots
mandryllo Dec 15, 2025
3648874
Fix getting snapshots
mandryllo Dec 15, 2025
3bba784
Update database builder
mandryllo Dec 16, 2025
3602506
Cleanup
mandryllo Dec 16, 2025
7822894
Fix type tests
mandryllo Dec 16, 2025
3107de3
Create db v2 component
mandryllo Dec 2, 2025
e0cae9b
Remove ability to create custom parameter group
mandryllo Dec 5, 2025
117e798
Cleanup
mandryllo Dec 5, 2025
7c2b479
Fix kms key id type
mandryllo Dec 5, 2025
06fe2d8
Cleanup
mandryllo Dec 5, 2025
17f5e9e
Cleanup vpc parameters
mandryllo Dec 5, 2025
f491332
Cleanup types
mandryllo Dec 5, 2025
9056cf8
Fix formatting
mandryllo Dec 5, 2025
75308bc
Cleanup
mandryllo Dec 8, 2025
3ba47f5
Create db builder component
mandryllo Dec 2, 2025
6b0648f
Fix typo
mandryllo Dec 3, 2025
65f030a
Remove custom parameter group args
mandryllo Dec 5, 2025
bfec1fc
Cleanup private props
mandryllo Dec 5, 2025
a48d054
Remove parameter group name from builder
mandryllo Dec 5, 2025
379dc30
Cleanup naming
mandryllo Dec 5, 2025
14d208b
Fix formatting
mandryllo Dec 5, 2025
c629546
Cleanup
mandryllo Dec 8, 2025
6906eb4
Cleanup database types
mandryllo Dec 10, 2025
8f5939e
Cleanup
mandryllo Dec 10, 2025
80804be
Revert allocatedStorage type to number
mandryllo Dec 10, 2025
98fb66b
Remove withKms method from builder
mandryllo Dec 10, 2025
5cfb8f9
fix tags
mandryllo Dec 10, 2025
823598e
Fix snapshot id
mandryllo Dec 10, 2025
9d7d045
Fix wrong condition
mandryllo Dec 11, 2025
1937146
Update database builder
mandryllo Dec 16, 2025
311d792
Cleanup
mandryllo Dec 16, 2025
b43859c
Move applyImmediately to instance config
mandryllo Dec 16, 2025
62b03d9
Update builder methods
mandryllo Dec 16, 2025
e8a017b
Update tests
mandryllo Dec 16, 2025
f9fdc02
Move kms key from storage type
mandryllo Dec 16, 2025
6467dff
Update builder
mandryllo Dec 16, 2025
3375e86
Cleanup default tests
mandryllo Dec 16, 2025
dce0103
Fix allocated storage type
mandryllo Dec 16, 2025
a783195
Revert "Fix allocated storage type"
mandryllo Dec 16, 2025
41783a5
Update after merge
mandryllo Dec 19, 2025
6f9884f
Add custom db tests
mandryllo Dec 16, 2025
54ca753
Merge branch 'master' into feat/db-v2-tests
mandryllo Jan 12, 2026
b70eb78
Cleanup
mandryllo Jan 12, 2026
b3e2bc8
Merge branch 'master' into feat/db-v2-tests
mandryllo Jan 12, 2026
b0d1817
Merge branch 'feat/db-v2-tests' into feat/custom-db-v2-tests
mandryllo Jan 12, 2026
8f7df17
Cleanup
mandryllo Jan 12, 2026
dd0efc7
Merge branch 'master' into feat/db-v2-tests
mandryllo Jan 13, 2026
d760f4e
Resolve comments
mandryllo Jan 14, 2026
242e60f
Merge branch 'master' into feat/db-v2-tests
mandryllo Jan 14, 2026
44df91e
Update dependecies
mandryllo Jan 14, 2026
39160de
Merge branch 'feat/db-v2-tests' into feat/custom-db-v2-tests
mandryllo Jan 14, 2026
c7c47fe
Rename custom to configurable
mandryllo Jan 14, 2026
790d762
Cleanup
mandryllo Jan 14, 2026
23cf048
Merge branch 'master' into feat/db-v2-tests
mandryllo Jan 15, 2026
71f458f
Merge branch 'feat/db-v2-tests' into feat/custom-db-v2-tests
mandryllo Jan 15, 2026
5befbf0
Fix typo
mandryllo Jan 15, 2026
bb0f995
Add parent
mandryllo Jan 15, 2026
5dd8521
Merge branch 'feat/db-v2-tests' into feat/custom-db-v2-tests
mandryllo Jan 15, 2026
31acb68
Merge branch 'master' into feat/db-v2-tests
mandryllo Jan 16, 2026
c17d9e1
Merge branch 'feat/db-v2-tests' into feat/custom-db-v2-tests
mandryllo Jan 16, 2026
1ee6a4a
Merge branch 'master' into feat/custom-db-v2-tests
mandryllo Jan 16, 2026
1062118
Merge branch 'master' into feat/custom-db-v2-tests
mandryllo Jan 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
925 changes: 749 additions & 176 deletions package-lock.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
"prettier": "@studion/prettier-config",
"dependencies": {
"@pulumi/aws": "^6.66.3",
"@pulumi/aws-v7": "npm:@pulumi/aws@^7.15.0",
"@pulumi/aws-native": "^1.38.0",
"@pulumi/aws-v7": "npm:@pulumi/aws@^7.15.0",
"@pulumi/awsx": "^2.21.0",
"@pulumi/awsx-v3": "npm:@pulumi/awsx@^3.1.0",
"@pulumi/pulumi": "^3.146.0",
Expand All @@ -55,6 +55,7 @@
"@aws-sdk/client-efs": "^3.758.0",
"@aws-sdk/client-elastic-load-balancing-v2": "^3.764.0",
"@aws-sdk/client-elasticache": "^3.901.0",
"@aws-sdk/client-iam": "^3.970.0",
"@aws-sdk/client-kms": "^3.943.0",
"@aws-sdk/client-rds": "^3.943.0",
"@aws-sdk/client-route-53": "^3.782.0",
Expand Down
149 changes: 149 additions & 0 deletions tests/database/configurable-db.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import {
GetRoleCommand,
ListAttachedRolePoliciesCommand,
} from '@aws-sdk/client-iam';
import * as assert from 'node:assert';
import { DatabaseTestContext } from './test-context';
import { it } from 'node:test';
import { ListTagsForResourceCommand } from '@aws-sdk/client-rds';

export function testConfigurableDb(ctx: DatabaseTestContext) {
it('should properly configure instance', () => {
const configurableDb = ctx.outputs.configurableDb.value;

assert.strictEqual(
configurableDb.instance.applyImmediately,
ctx.config.applyImmediately,
'Apply immediately argument should be set correctly',
);
assert.strictEqual(
configurableDb.instance.allowMajorVersionUpgrade,
ctx.config.allowMajorVersionUpgrade,
'Allow major version upgrade argument should be set correctly',
);
assert.strictEqual(
configurableDb.instance.autoMinorVersionUpgrade,
ctx.config.autoMinorVersionUpgrade,
'Auto minor version upgrade argument should be set correctly',
);
});

it('should properly configure password', () => {
const configurableDb = ctx.outputs.configurableDb.value;

assert.ok(configurableDb.password, 'Password should exist');
assert.strictEqual(
configurableDb.instance.masterUserPassword,
ctx.config.dbPassword,
'Master user password should be set correctly',
);
});

it('should properly configure storage', () => {
const configurableDb = ctx.outputs.configurableDb.value;

assert.strictEqual(
configurableDb.instance.allocatedStorage,
ctx.config.allocatedStorage.toString(),
'Allocated storage argument should be set correctly',
);
assert.strictEqual(
configurableDb.instance.maxAllocatedStorage,
ctx.config.maxAllocatedStorage,
'Max allocated storage argument should be set correctly',
);
});

it('should properly configure monitoring options', () => {
const configurableDb = ctx.outputs.configurableDb.value;

assert.strictEqual(
configurableDb.instance.enablePerformanceInsights,
true,
'Performance insights should be enabled',
);
assert.strictEqual(
configurableDb.instance.performanceInsightsRetentionPeriod,
7,
'Performance insights retention period should be set correctly',
);
assert.strictEqual(
configurableDb.instance.monitoringInterval,
60,
'Monitoring interval should be set correctly',
);
assert.ok(
configurableDb.instance.monitoringRoleArn,
'Monitoring role ARN should exist',
);
});

it('should create monitoring IAM role and attach correct policy', async () => {
const configurableDb = ctx.outputs.configurableDb.value;
const roleName = configurableDb.monitoringRole.name;

const roleCommand = new GetRoleCommand({
RoleName: roleName,
});
const { Role } = await ctx.clients.iam.send(roleCommand);
assert.ok(Role, 'Monitoring IAM role should exist');

const policyCommand = new ListAttachedRolePoliciesCommand({
RoleName: roleName,
});
const { AttachedPolicies } = await ctx.clients.iam.send(policyCommand);
assert.ok(
AttachedPolicies && AttachedPolicies.length > 0,
'Attached policies should exist',
);
const [attachedPolicy] = AttachedPolicies;
assert.strictEqual(
attachedPolicy.PolicyArn,
'arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole',
'Monitoring IAM role should have correct policy attached',
);
});

it('should properly configure kms', () => {
const configurableDb = ctx.outputs.configurableDb.value;
const kms = ctx.outputs.kms.value;

assert.ok(configurableDb.kmsKeyId, 'Kms key id should exist');
assert.strictEqual(
configurableDb.instance.kmsKeyId,
kms.arn,
'Kms key id should be set correctly',
);
});

it('should properly configure parameter group', () => {
const configurableDb = ctx.outputs.configurableDb.value;
const paramGroup = ctx.outputs.paramGroup.value;

assert.strictEqual(
configurableDb.instance.dbParameterGroupName,
paramGroup.name,
'Parameter group name should be set correctly',
);
});

it('should properly configure tags', async () => {
const configurableDb = ctx.outputs.configurableDb.value;

const command = new ListTagsForResourceCommand({
ResourceName: configurableDb.instance.dbInstanceArn,
});
const { TagList } = await ctx.clients.rds.send(command);
assert.ok(TagList && TagList.length > 0, 'Tags should exist');

Object.entries(ctx.config.tags).map(([Key, Value]) => {
const tag = TagList.find(tag => tag.Key === Key);
assert.ok(tag, `${Key} tag should exist`);
assert.strictEqual(
tag.Value,
Value,
`${Key} tag should be set correctly`,
);
});
});
}
5 changes: 5 additions & 0 deletions tests/database/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ import { cleanupSnapshots } from './util';
import * as config from './infrastructure/config';
import { DatabaseTestContext } from './test-context';
import { EC2Client } from '@aws-sdk/client-ec2';
import { IAMClient } from '@aws-sdk/client-iam';
import { InlineProgramArgs } from '@pulumi/pulumi/automation';
import { it } from 'node:test';
import { KMSClient } from '@aws-sdk/client-kms';
import { RDSClient } from '@aws-sdk/client-rds';
import { requireEnv } from '../util';
import { testConfigurableDb } from './configurable-db.test';

const programArgs: InlineProgramArgs = {
stackName: 'dev',
Expand All @@ -37,6 +39,7 @@ const ctx: DatabaseTestContext = {
rds: new RDSClient({ region }),
ec2: new EC2Client({ region }),
kms: new KMSClient({ region }),
iam: new IAMClient({ region }),
},
};

Expand Down Expand Up @@ -202,4 +205,6 @@ describe('Database component deployment', () => {
'KMS key rotation should be enabled',
);
});

describe('With configurable options', () => testConfigurableDb(ctx));
});
13 changes: 13 additions & 0 deletions tests/database/infrastructure/config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
import * as pulumi from '@pulumi/pulumi';

export const appName = 'db-test';
export const stackName = pulumi.getStack();
export const tags = {
Project: appName,
Environment: stackName,
};
export const dbName = 'dbname';
export const dbUsername = 'dbusername';
export const dbPassword = 'dbpassword';
export const applyImmediately = true;
export const allowMajorVersionUpgrade = true;
export const autoMinorVersionUpgrade = false;
export const allocatedStorage = 10;
export const maxAllocatedStorage = 50;
60 changes: 53 additions & 7 deletions tests/database/infrastructure/index.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,69 @@
import { appName, dbName, dbUsername } from './config';
import * as aws from '@pulumi/aws';
import * as config from './config';
import * as pulumi from '@pulumi/pulumi';
import { next as studion } from '@studion/infra-code-blocks';
import { DatabaseBuilder } from '../../../src/v2/components/database/builder';

const parent = new pulumi.ComponentResource(
'studion:database:TestGroup',
`${appName}-root`,
`${config.appName}-root`,
);

const vpc = new studion.Vpc(`${appName}-vpc`, {}, { parent });
const vpc = new studion.Vpc(`${config.appName}-vpc`, {}, { parent });

const defaultDb = new DatabaseBuilder(`${appName}-default-db`)
const defaultDb = new DatabaseBuilder(`${config.appName}-default-db`)
.withInstance({
dbName,
dbName: config.dbName,
})
.withCredentials({
username: dbUsername,
username: config.dbUsername,
})
.withVpc(vpc.vpc)
.build({ parent });

export { vpc, defaultDb };
const kms = new aws.kms.Key(
`${config.appName}-kms-key`,
{
description: `${config.appName} RDS encryption key`,
customerMasterKeySpec: 'SYMMETRIC_DEFAULT',
isEnabled: true,
keyUsage: 'ENCRYPT_DECRYPT',
multiRegion: false,
enableKeyRotation: true,
tags: config.tags,
},
{ parent },
);

const paramGroup = new aws.rds.ParameterGroup(
`${config.appName}-parameter-group`,
{
family: 'postgres17',
tags: config.tags,
},
{ parent },
);

const configurableDb = new DatabaseBuilder(`${config.appName}-configurable-db`)
.withInstance({
dbName: config.dbName,
applyImmediately: config.applyImmediately,
allowMajorVersionUpgrade: config.allowMajorVersionUpgrade,
autoMinorVersionUpgrade: config.autoMinorVersionUpgrade,
})
.withCredentials({
username: config.dbUsername,
password: config.dbPassword,
})
.withStorage({
allocatedStorage: config.allocatedStorage,
maxAllocatedStorage: config.maxAllocatedStorage,
})
.withVpc(vpc.vpc)
.withMonitoring()
.withKms(kms.arn)
.withParameterGroup(paramGroup.name)
.withTags(config.tags)
.build({ parent });

export { vpc, defaultDb, kms, paramGroup, configurableDb };
13 changes: 13 additions & 0 deletions tests/database/test-context.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { EC2Client } from '@aws-sdk/client-ec2';
import { IAMClient } from '@aws-sdk/client-iam';
import { KMSClient } from '@aws-sdk/client-kms';
import { OutputMap } from '@pulumi/pulumi/automation';
import { RDSClient } from '@aws-sdk/client-rds';
Expand All @@ -9,8 +10,19 @@ interface ConfigContext {

interface DatabaseTestConfig {
appName: string;
stackName: string;
tags: {
Project: string;
Environment: string;
};
dbName: string;
dbUsername: string;
dbPassword: string;
applyImmediately: boolean;
allowMajorVersionUpgrade: boolean;
autoMinorVersionUpgrade: boolean;
allocatedStorage: number;
maxAllocatedStorage: number;
}

interface PulumiProgramContext {
Expand All @@ -22,6 +34,7 @@ interface AwsContext {
rds: RDSClient;
ec2: EC2Client;
kms: KMSClient;
iam: IAMClient;
};
}

Expand Down
6 changes: 4 additions & 2 deletions tests/database/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import { DatabaseTestContext } from './test-context';
export async function cleanupSnapshots(ctx: DatabaseTestContext) {
const spinner = createSpinner('Deleting snapshots...').start();

const defaultDb = ctx.outputs.defaultDb.value;
await deleteSnapshot(ctx, defaultDb.instance.dbInstanceIdentifier);
const dbs = [ctx.outputs.defaultDb.value, ctx.outputs.configurableDb.value];
await Promise.all(
dbs.map(db => deleteSnapshot(ctx, db.instance.dbInstanceIdentifier)),
);

spinner.success({ text: 'Snapshots deleted' });
}
Expand Down