Skip to content

Commit febb6cd

Browse files
committed
Add custom db tests
1 parent 04800c7 commit febb6cd

File tree

8 files changed

+947
-155
lines changed

8 files changed

+947
-155
lines changed

package-lock.json

Lines changed: 725 additions & 152 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"@aws-sdk/client-efs": "^3.758.0",
5454
"@aws-sdk/client-elastic-load-balancing-v2": "^3.764.0",
5555
"@aws-sdk/client-elasticache": "^3.901.0",
56+
"@aws-sdk/client-iam": "^3.952.0",
5657
"@aws-sdk/client-kms": "^3.943.0",
5758
"@aws-sdk/client-rds": "^3.943.0",
5859
"@aws-sdk/client-route-53": "^3.782.0",

tests/database/custom-db.test.ts

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
import {
2+
GetRoleCommand,
3+
ListAttachedRolePoliciesCommand,
4+
} from '@aws-sdk/client-iam';
5+
import * as assert from 'node:assert';
6+
import { DatabaseTestContext } from './test-context';
7+
import { it } from 'node:test';
8+
import { ListTagsForResourceCommand } from '@aws-sdk/client-rds';
9+
10+
export function testCustomDb(ctx: DatabaseTestContext) {
11+
it('should properly configure instance', () => {
12+
const customDb = ctx.outputs.customDb.value;
13+
14+
assert.strictEqual(
15+
customDb.instance.applyImmediately,
16+
ctx.config.applyImmediately,
17+
'Apply immediately argument should be set correctly',
18+
);
19+
assert.strictEqual(
20+
customDb.instance.allowMajorVersionUpgrade,
21+
ctx.config.allowMajorVersionUpgrade,
22+
'Allow major version upgrade argument should be set correctly',
23+
);
24+
assert.strictEqual(
25+
customDb.instance.autoMinorVersionUpgrade,
26+
ctx.config.autoMinorVersionUpgrade,
27+
'Auto minor version upgrade argument should be set correctly',
28+
);
29+
});
30+
31+
it('should properly configure password', () => {
32+
const customDb = ctx.outputs.customDb.value;
33+
34+
assert.ok(customDb.password, 'Password should exist');
35+
assert.strictEqual(
36+
customDb.instance.masterUserPassword,
37+
ctx.config.dbPassword,
38+
'Master user password should be set correctly',
39+
);
40+
});
41+
42+
it('should properly configure storage', () => {
43+
const customDb = ctx.outputs.customDb.value;
44+
45+
assert.strictEqual(
46+
customDb.instance.allocatedStorage,
47+
ctx.config.allocatedStorage.toString(),
48+
'Allocated storage argument should be set correctly',
49+
);
50+
assert.strictEqual(
51+
customDb.instance.maxAllocatedStorage,
52+
ctx.config.maxAllocatedStorage,
53+
'Max allocated storage argument should be set correctly',
54+
);
55+
});
56+
57+
it('should properly configure monitoring options', () => {
58+
const customDb = ctx.outputs.customDb.value;
59+
60+
assert.strictEqual(
61+
customDb.instance.enablePerformanceInsights,
62+
true,
63+
'Performance insights should be enabled',
64+
);
65+
assert.strictEqual(
66+
customDb.instance.performanceInsightsRetentionPeriod,
67+
7,
68+
'Performance insights retention period should be set correctly',
69+
);
70+
assert.strictEqual(
71+
customDb.instance.monitoringInterval,
72+
60,
73+
'Monitoring interval should be set correctly',
74+
);
75+
assert.ok(
76+
customDb.instance.monitoringRoleArn,
77+
'Monitoring role ARN should exist',
78+
);
79+
});
80+
81+
it('should create monitoring IAM role and attach correct policy', async () => {
82+
const customDb = ctx.outputs.customDb.value;
83+
const roleName = customDb.monitoringRole.name;
84+
85+
const roleCommand = new GetRoleCommand({
86+
RoleName: roleName,
87+
});
88+
const { Role } = await ctx.clients.iam.send(roleCommand);
89+
assert.ok(Role, 'Monitoring IAM role should exist');
90+
91+
const policyCommand = new ListAttachedRolePoliciesCommand({
92+
RoleName: roleName,
93+
});
94+
const { AttachedPolicies } = await ctx.clients.iam.send(policyCommand);
95+
assert.ok(
96+
AttachedPolicies && AttachedPolicies.length > 0,
97+
'Attached policies should exist',
98+
);
99+
const [attachedPolicy] = AttachedPolicies;
100+
assert.strictEqual(
101+
attachedPolicy.PolicyArn,
102+
'arn:aws:iam::aws:policy/service-role/AmazonRDSEnhancedMonitoringRole',
103+
'Monitoring IAM role should have correct policy attached',
104+
);
105+
});
106+
107+
it('should properly configure kms', () => {
108+
const customDb = ctx.outputs.customDb.value;
109+
const kms = ctx.outputs.kms.value;
110+
111+
assert.ok(customDb.kmsKeyId, 'Kms key id should exist');
112+
assert.strictEqual(
113+
customDb.instance.kmsKeyId,
114+
kms.arn,
115+
'Kms key id should be set correctly',
116+
);
117+
});
118+
119+
it('should properly configure parameter group', () => {
120+
const customDb = ctx.outputs.customDb.value;
121+
const paramGroup = ctx.outputs.paramGroup.value;
122+
123+
assert.strictEqual(
124+
customDb.instance.dbParameterGroupName,
125+
paramGroup.name,
126+
'Parameter group name should be set correctly',
127+
);
128+
});
129+
130+
it('should properly configure tags', async () => {
131+
const customDb = ctx.outputs.customDb.value;
132+
133+
const command = new ListTagsForResourceCommand({
134+
ResourceName: customDb.instance.dbInstanceArn,
135+
});
136+
const { TagList } = await ctx.clients.rds.send(command);
137+
assert.ok(TagList && TagList.length > 0, 'Tags should exist');
138+
139+
Object.entries(ctx.config.tags).map(([Key, Value]) => {
140+
const tag = TagList.find(tag => tag.Key === Key);
141+
assert.ok(tag, `${Key} tag should exist`);
142+
assert.strictEqual(tag.Value, Value, `${Key} tag should set correctly`);
143+
});
144+
});
145+
}

tests/database/index.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ import { cleanupSnapshots } from './utils/cleanup-snapshots';
44
import * as config from './infrastructure/config';
55
import { DatabaseTestContext } from './test-context';
66
import { EC2Client } from '@aws-sdk/client-ec2';
7+
import { IAMClient } from '@aws-sdk/client-iam';
78
import { InlineProgramArgs } from '@pulumi/pulumi/automation';
89
import { KMSClient } from '@aws-sdk/client-kms';
910
import { RDSClient } from '@aws-sdk/client-rds';
11+
import { testCustomDb } from './custom-db.test';
1012
import { testDefaultDb } from './default-db.test';
1113

1214
const programArgs: InlineProgramArgs = {
@@ -28,6 +30,7 @@ describe('Database component deployment', () => {
2830
rds: new RDSClient({ region }),
2931
ec2: new EC2Client({ region }),
3032
kms: new KMSClient({ region }),
33+
iam: new IAMClient({ region }),
3134
},
3235
};
3336

@@ -38,5 +41,6 @@ describe('Database component deployment', () => {
3841
after(() => automation.destroy(programArgs));
3942

4043
describe('Default database', () => testDefaultDb(ctx));
44+
describe('Custom database', () => testCustomDb(ctx));
4145
after(() => cleanupSnapshots(ctx));
4246
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,16 @@
1+
import * as pulumi from '@pulumi/pulumi';
2+
13
export const appName = 'db-test';
4+
export const stackName = pulumi.getStack();
5+
export const tags = {
6+
Project: appName,
7+
Environment: stackName,
8+
};
29
export const dbName = 'dbname';
310
export const dbUsername = 'dbusername';
11+
export const dbPassword = 'dbpassword';
12+
export const applyImmediately = true;
13+
export const allowMajorVersionUpgrade = true;
14+
export const autoMinorVersionUpgrade = false;
15+
export const allocatedStorage = 10;
16+
export const maxAllocatedStorage = 50;

tests/database/infrastructure/index.ts

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import * as aws from '@pulumi/aws';
12
import { next as studion } from '@studion/infra-code-blocks';
23
import { DatabaseBuilder } from '../../../dist/v2/components/database/builder';
34
import * as config from './config';
@@ -14,4 +15,44 @@ const defaultDb = new DatabaseBuilder(`${config.appName}-default`)
1415
.withVpc(vpc.vpc)
1516
.build();
1617

17-
export { vpc, defaultDb };
18+
const kms = new aws.kms.Key(`${config.appName}-kms`, {
19+
description: `${config.appName} RDS encryption key`,
20+
customerMasterKeySpec: 'SYMMETRIC_DEFAULT',
21+
isEnabled: true,
22+
keyUsage: 'ENCRYPT_DECRYPT',
23+
multiRegion: false,
24+
enableKeyRotation: true,
25+
tags: config.tags,
26+
});
27+
28+
const paramGroup = new aws.rds.ParameterGroup(
29+
`${config.appName}-parameter-group`,
30+
{
31+
family: 'postgres17',
32+
tags: config.tags,
33+
},
34+
);
35+
36+
const customDb = new DatabaseBuilder(`${config.appName}-custom`)
37+
.withInstance({
38+
dbName: config.dbName,
39+
applyImmediately: config.applyImmediately,
40+
allowMajorVersionUpgrade: config.allowMajorVersionUpgrade,
41+
autoMinorVersionUpgrade: config.autoMinorVersionUpgrade,
42+
})
43+
.withCredentials({
44+
username: config.dbUsername,
45+
password: config.dbPassword,
46+
})
47+
.withStorage({
48+
allocatedStorage: config.allocatedStorage,
49+
maxAllocatedStorage: config.maxAllocatedStorage,
50+
})
51+
.withVpc(vpc.vpc)
52+
.withMonitoring()
53+
.withKms(kms.arn)
54+
.withParameterGroup(paramGroup.name)
55+
.withTags(config.tags)
56+
.build();
57+
58+
export { vpc, defaultDb, kms, paramGroup, customDb };

tests/database/test-context.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { EC2Client } from '@aws-sdk/client-ec2';
2+
import { IAMClient } from '@aws-sdk/client-iam';
23
import { KMSClient } from '@aws-sdk/client-kms';
34
import { OutputMap } from '@pulumi/pulumi/automation';
45
import { RDSClient } from '@aws-sdk/client-rds';
@@ -9,8 +10,19 @@ interface ConfigContext {
910

1011
interface DatabaseTestConfig {
1112
appName: string;
13+
stackName: string;
14+
tags: {
15+
Project: string;
16+
Environment: string;
17+
};
1218
dbName: string;
1319
dbUsername: string;
20+
dbPassword: string;
21+
applyImmediately: boolean;
22+
allowMajorVersionUpgrade: boolean;
23+
autoMinorVersionUpgrade: boolean;
24+
allocatedStorage: number;
25+
maxAllocatedStorage: number;
1426
}
1527

1628
interface PulumiProgramContext {
@@ -22,6 +34,7 @@ interface AwsContext {
2234
rds: RDSClient;
2335
ec2: EC2Client;
2436
kms: KMSClient;
37+
iam: IAMClient;
2538
};
2639
}
2740

tests/database/utils/cleanup-snapshots.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ import { DatabaseTestContext } from '../test-context';
88
export async function cleanupSnapshots(ctx: DatabaseTestContext) {
99
const spinner = createSpinner('Deleting snapshots...').start();
1010

11-
const defaultDb = ctx.outputs.defaultDb.value;
12-
await deleteSnapshot(ctx, defaultDb.instance.dbInstanceIdentifier);
11+
const dbs = [ctx.outputs.defaultDb.value, ctx.outputs.customDb.value];
12+
await Promise.all(
13+
dbs.map(db => deleteSnapshot(ctx, db.instance.dbInstanceIdentifier)),
14+
);
1315

1416
spinner.success({ text: 'Snapshots deleted' });
1517
}

0 commit comments

Comments
 (0)