@digitraffic/common 2022.11.1-1 → 2022.11.10-1
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/aws/infra/canaries/canary.js +1 -1
- package/dist/aws/infra/canaries/database-checker.d.ts +22 -8
- package/dist/aws/infra/canaries/database-checker.js +36 -27
- package/dist/aws/infra/canaries/database-checker.js.map +1 -1
- package/dist/aws/infra/canaries/url-checker.js +1 -1
- package/dist/aws/infra/import-util.d.ts +21 -0
- package/dist/aws/infra/import-util.js +53 -0
- package/dist/aws/infra/import-util.js.map +1 -0
- package/dist/aws/infra/stack/rest_apis.d.ts +1 -1
- package/dist/aws/infra/stack/rest_apis.js +2 -2
- package/dist/aws/infra/stack/rest_apis.js.map +1 -1
- package/dist/aws/infra/stacks/db-dns-stack.d.ts +11 -0
- package/dist/aws/infra/stacks/db-dns-stack.js +63 -0
- package/dist/aws/infra/stacks/db-dns-stack.js.map +1 -0
- package/dist/aws/infra/stacks/db-proxy-stack.d.ts +19 -0
- package/dist/aws/infra/stacks/db-proxy-stack.js +74 -0
- package/dist/aws/infra/stacks/db-proxy-stack.js.map +1 -0
- package/dist/aws/infra/stacks/db-stack.d.ts +31 -0
- package/dist/aws/infra/stacks/db-stack.js +91 -0
- package/dist/aws/infra/stacks/db-stack.js.map +1 -0
- package/dist/aws/infra/stacks/intra-stack-configuration.d.ts +5 -0
- package/dist/aws/infra/stacks/intra-stack-configuration.js +3 -0
- package/dist/aws/infra/stacks/intra-stack-configuration.js.map +1 -0
- package/dist/aws/infra/stacks/network-stack.d.ts +12 -0
- package/dist/aws/infra/stacks/network-stack.js +36 -0
- package/dist/aws/infra/stacks/network-stack.js.map +1 -0
- package/dist/aws/infra/usage-plans.d.ts +3 -2
- package/dist/aws/infra/usage-plans.js +5 -4
- package/dist/aws/infra/usage-plans.js.map +1 -1
- package/package.json +3 -3
- package/src/aws/infra/canaries/canary.ts +1 -1
- package/src/aws/infra/canaries/database-checker.ts +42 -36
- package/src/aws/infra/canaries/url-checker.ts +1 -1
- package/src/aws/infra/import-util.ts +57 -0
- package/src/aws/infra/stack/rest_apis.ts +2 -2
- package/src/aws/infra/stacks/db-dns-stack.ts +88 -0
- package/src/aws/infra/stacks/db-proxy-stack.ts +129 -0
- package/src/aws/infra/stacks/db-stack.ts +165 -0
- package/src/aws/infra/stacks/intra-stack-configuration.ts +6 -0
- package/src/aws/infra/stacks/network-stack.ts +46 -0
- package/src/aws/infra/usage-plans.ts +15 -6
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"db-stack.js","sourceRoot":"","sources":["../../../../src/aws/infra/stacks/db-stack.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"intra-stack-configuration.js","sourceRoot":"","sources":["../../../../src/aws/infra/stacks/intra-stack-configuration.ts"],"names":[],"mappings":""}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import { Stack } from "aws-cdk-lib";
|
2
|
+
import { Construct } from "constructs";
|
3
|
+
import { Vpc } from "aws-cdk-lib/aws-ec2";
|
4
|
+
import { InfraStackConfiguration } from "./intra-stack-configuration";
|
5
|
+
export interface NetworkConfiguration {
|
6
|
+
readonly vpcName: string;
|
7
|
+
readonly cidr: string;
|
8
|
+
}
|
9
|
+
export declare class NetworkStack extends Stack {
|
10
|
+
constructor(scope: Construct, id: string, isc: InfraStackConfiguration, configuration: NetworkConfiguration);
|
11
|
+
createVpc(configuration: NetworkConfiguration): Vpc;
|
12
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.NetworkStack = void 0;
|
4
|
+
const aws_cdk_lib_1 = require("aws-cdk-lib");
|
5
|
+
const aws_ec2_1 = require("aws-cdk-lib/aws-ec2");
|
6
|
+
class NetworkStack extends aws_cdk_lib_1.Stack {
|
7
|
+
constructor(scope, id, isc, configuration) {
|
8
|
+
super(scope, id, {
|
9
|
+
env: isc.env,
|
10
|
+
});
|
11
|
+
this.createVpc(configuration);
|
12
|
+
}
|
13
|
+
createVpc(configuration) {
|
14
|
+
return new aws_ec2_1.Vpc(this, "DigitrafficVPC", {
|
15
|
+
vpcName: configuration.vpcName,
|
16
|
+
availabilityZones: ["eu-west-1a", "eu-west-1b"],
|
17
|
+
enableDnsHostnames: true,
|
18
|
+
enableDnsSupport: true,
|
19
|
+
cidr: configuration.cidr,
|
20
|
+
subnetConfiguration: [
|
21
|
+
{
|
22
|
+
name: "public",
|
23
|
+
cidrMask: 24,
|
24
|
+
subnetType: aws_ec2_1.SubnetType.PUBLIC,
|
25
|
+
},
|
26
|
+
{
|
27
|
+
name: "private",
|
28
|
+
cidrMask: 24,
|
29
|
+
subnetType: aws_ec2_1.SubnetType.PRIVATE_WITH_NAT,
|
30
|
+
},
|
31
|
+
],
|
32
|
+
});
|
33
|
+
}
|
34
|
+
}
|
35
|
+
exports.NetworkStack = NetworkStack;
|
36
|
+
//# sourceMappingURL=network-stack.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"network-stack.js","sourceRoot":"","sources":["../../../../src/aws/infra/stacks/network-stack.ts"],"names":[],"mappings":";;;AAAA,6CAAoC;AAEpC,iDAAsD;AAQtD,MAAa,YAAa,SAAQ,mBAAK;IACnC,YACI,KAAgB,EAChB,EAAU,EACV,GAA4B,EAC5B,aAAmC;QAEnC,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE;YACb,GAAG,EAAE,GAAG,CAAC,GAAG;SACf,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;IAClC,CAAC;IAED,SAAS,CAAC,aAAmC;QACzC,OAAO,IAAI,aAAG,CAAC,IAAI,EAAE,gBAAgB,EAAE;YACnC,OAAO,EAAE,aAAa,CAAC,OAAO;YAC9B,iBAAiB,EAAE,CAAC,YAAY,EAAE,YAAY,CAAC;YAC/C,kBAAkB,EAAE,IAAI;YACxB,gBAAgB,EAAE,IAAI;YACtB,IAAI,EAAE,aAAa,CAAC,IAAI;YACxB,mBAAmB,EAAE;gBACjB;oBACI,IAAI,EAAE,QAAQ;oBACd,QAAQ,EAAE,EAAE;oBACZ,UAAU,EAAE,oBAAU,CAAC,MAAM;iBAChC;gBACD;oBACI,IAAI,EAAE,SAAS;oBACf,QAAQ,EAAE,EAAE;oBACZ,UAAU,EAAE,oBAAU,CAAC,gBAAgB;iBAC1C;aACJ;SACJ,CAAC,CAAC;IACP,CAAC;CACJ;AAnCD,oCAmCC"}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { IApiKey, RestApi } from
|
1
|
+
import { IApiKey, RestApi } from "aws-cdk-lib/aws-apigateway";
|
2
2
|
/**
|
3
3
|
* Creates an usage plan for a REST API with a single API key
|
4
4
|
* @param api The REST API
|
@@ -11,5 +11,6 @@ export declare function createUsagePlan(api: RestApi, apiKeyId: string, apiKeyNa
|
|
11
11
|
* Creates a default usage plan for a REST API with a single API key
|
12
12
|
* @param api The REST API
|
13
13
|
* @param apiName Name of the api. Will generate key: apiName + ' API Key' and plan: apiName + ' API Usage Plan'
|
14
|
+
* @param value Optional value for the API key
|
14
15
|
*/
|
15
|
-
export declare function createDefaultUsagePlan(api: RestApi, apiName: string): IApiKey;
|
16
|
+
export declare function createDefaultUsagePlan(api: RestApi, apiName: string, value?: string): IApiKey;
|
@@ -24,11 +24,12 @@ exports.createUsagePlan = createUsagePlan;
|
|
24
24
|
* Creates a default usage plan for a REST API with a single API key
|
25
25
|
* @param api The REST API
|
26
26
|
* @param apiName Name of the api. Will generate key: apiName + ' API Key' and plan: apiName + ' API Usage Plan'
|
27
|
+
* @param value Optional value for the API key
|
27
28
|
*/
|
28
|
-
function createDefaultUsagePlan(api, apiName) {
|
29
|
-
const apiKeyName = apiName +
|
30
|
-
const usagePlanName = apiName +
|
31
|
-
const apiKey = api.addApiKey(apiKeyName, { apiKeyName: apiKeyName });
|
29
|
+
function createDefaultUsagePlan(api, apiName, value) {
|
30
|
+
const apiKeyName = apiName + " API Key";
|
31
|
+
const usagePlanName = apiName + " API Usage Plan";
|
32
|
+
const apiKey = api.addApiKey(apiKeyName, { apiKeyName: apiKeyName, value });
|
32
33
|
const plan = api.addUsagePlan(usagePlanName, {
|
33
34
|
name: usagePlanName,
|
34
35
|
});
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"usage-plans.js","sourceRoot":"","sources":["../../../src/aws/infra/usage-plans.ts"],"names":[],"mappings":";;;AAEA;;;;;;GAMG;AACH,SAAgB,eAAe,
|
1
|
+
{"version":3,"file":"usage-plans.js","sourceRoot":"","sources":["../../../src/aws/infra/usage-plans.ts"],"names":[],"mappings":";;;AAEA;;;;;;GAMG;AACH,SAAgB,eAAe,CAC3B,GAAY,EACZ,QAAgB,EAChB,UAAkB;IAElB,MAAM,MAAM,GAAG,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,UAAU,EAAE;QACtC,IAAI,EAAE,UAAU;KACnB,CAAC,CAAC;IACH,IAAI,CAAC,WAAW,CAAC;QACb,KAAK,EAAE,GAAG,CAAC,eAAe;KAC7B,CAAC,CAAC;IACH,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAEvB,OAAO,MAAM,CAAC;AAClB,CAAC;AAfD,0CAeC;AAED;;;;;GAKG;AACH,SAAgB,sBAAsB,CAClC,GAAY,EACZ,OAAe,EACf,KAAc;IAEd,MAAM,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;IACxC,MAAM,aAAa,GAAG,OAAO,GAAG,iBAAiB,CAAC;IAClD,MAAM,MAAM,GAAG,GAAG,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5E,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,aAAa,EAAE;QACzC,IAAI,EAAE,aAAa;KACtB,CAAC,CAAC;IACH,IAAI,CAAC,WAAW,CAAC;QACb,KAAK,EAAE,GAAG,CAAC,eAAe;KAC7B,CAAC,CAAC;IACH,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAEvB,OAAO,MAAM,CAAC;AAClB,CAAC;AAjBD,wDAiBC"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@digitraffic/common",
|
3
|
-
"version": "2022.11.
|
3
|
+
"version": "2022.11.10-1",
|
4
4
|
"description": "",
|
5
5
|
"repository": {
|
6
6
|
"type": "git",
|
@@ -26,9 +26,9 @@
|
|
26
26
|
"src/**/*.ts"
|
27
27
|
],
|
28
28
|
"dependencies": {
|
29
|
-
"@aws-cdk/aws-synthetics-alpha": "2.
|
29
|
+
"@aws-cdk/aws-synthetics-alpha": "2.50.0-alpha.0",
|
30
30
|
"@types/geojson": "^7946.0.10",
|
31
|
-
"aws-cdk-lib": "2.
|
31
|
+
"aws-cdk-lib": "2.50.0",
|
32
32
|
"aws-sdk": "2.1241.0",
|
33
33
|
"axios": "^0.21.1",
|
34
34
|
"change-case": "4.1.2",
|
@@ -21,7 +21,7 @@ export class DigitrafficCanary extends Canary {
|
|
21
21
|
environmentVariables: LambdaEnvironment
|
22
22
|
) {
|
23
23
|
super(scope, canaryName, {
|
24
|
-
runtime: Runtime.
|
24
|
+
runtime: Runtime.SYNTHETICS_NODEJS_PUPPETEER_3_8,
|
25
25
|
role,
|
26
26
|
test: Test.custom({
|
27
27
|
code: new AssetCode("dist", {
|
@@ -20,11 +20,7 @@ abstract class DatabaseCheck<T> {
|
|
20
20
|
abstract check(value: T): void;
|
21
21
|
}
|
22
22
|
|
23
|
-
|
24
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
25
|
-
interface BaseResponse {}
|
26
|
-
|
27
|
-
interface CountResponse extends BaseResponse {
|
23
|
+
interface CountResponse {
|
28
24
|
count: number;
|
29
25
|
}
|
30
26
|
|
@@ -40,8 +36,12 @@ class CountDatabaseCheck extends DatabaseCheck<CountResponse> {
|
|
40
36
|
) {
|
41
37
|
super(name, sql);
|
42
38
|
|
39
|
+
if (!sql.toLowerCase().includes("select count(*)")) {
|
40
|
+
throw new Error("sql must contain select count(*)");
|
41
|
+
}
|
42
|
+
|
43
43
|
if (minCount == null && maxCount == null) {
|
44
|
-
throw new Error("no max or min given
|
44
|
+
throw new Error("no max or min given");
|
45
45
|
}
|
46
46
|
|
47
47
|
this.minCount = minCount;
|
@@ -49,30 +49,23 @@ class CountDatabaseCheck extends DatabaseCheck<CountResponse> {
|
|
49
49
|
}
|
50
50
|
|
51
51
|
check(value: CountResponse) {
|
52
|
-
if (
|
53
|
-
this.
|
54
|
-
throw new Error("no return value");
|
55
|
-
} else {
|
56
|
-
if ("count" in value) {
|
57
|
-
if (this.minCount && value.count < this.minCount) {
|
58
|
-
this.failed = true;
|
59
|
-
throw new Error(
|
60
|
-
`count was ${value.count}, minimum is ${this.minCount}`
|
61
|
-
);
|
62
|
-
}
|
63
|
-
if (this.maxCount && value.count > this.maxCount) {
|
64
|
-
this.failed = true;
|
65
|
-
throw new Error(
|
66
|
-
`count was ${value.count}, max is ${this.maxCount}`
|
67
|
-
);
|
68
|
-
}
|
69
|
-
} else {
|
52
|
+
if ("count" in value) {
|
53
|
+
if (this.minCount && value.count < this.minCount) {
|
70
54
|
this.failed = true;
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
55
|
+
throw new Error(
|
56
|
+
`count was ${value.count}, minimum is ${this.minCount}`
|
57
|
+
);
|
58
|
+
}
|
59
|
+
if (this.maxCount && value.count > this.maxCount) {
|
60
|
+
this.failed = true;
|
61
|
+
throw new Error(
|
62
|
+
`count was ${value.count}, max is ${this.maxCount}`
|
63
|
+
);
|
75
64
|
}
|
65
|
+
} else {
|
66
|
+
this.failed = true;
|
67
|
+
|
68
|
+
throw new Error("no count available");
|
76
69
|
}
|
77
70
|
}
|
78
71
|
}
|
@@ -84,9 +77,13 @@ const stepConfig = {
|
|
84
77
|
screenshotOnStepFailure: false,
|
85
78
|
};
|
86
79
|
|
87
|
-
|
80
|
+
/**
|
81
|
+
* Checker for sql that checks the count. Meaning that the
|
82
|
+
* sql must be structured as select(*) from table where something.
|
83
|
+
*/
|
84
|
+
export class DatabaseCountChecker {
|
88
85
|
credentialsFunction: () => Promise<void>;
|
89
|
-
checks: DatabaseCheck<
|
86
|
+
checks: DatabaseCheck<CountResponse>[];
|
90
87
|
|
91
88
|
private constructor(credentialsFunction: () => Promise<void>) {
|
92
89
|
this.credentialsFunction = credentialsFunction;
|
@@ -98,30 +95,39 @@ export class DatabaseChecker {
|
|
98
95
|
}
|
99
96
|
|
100
97
|
static createForProxy() {
|
101
|
-
return new
|
98
|
+
return new DatabaseCountChecker(() =>
|
102
99
|
new ProxyHolder(getEnvVariable("SECRET_ID")).setCredentials()
|
103
100
|
);
|
104
101
|
}
|
105
102
|
|
106
103
|
static createForRds() {
|
107
|
-
return new
|
104
|
+
return new DatabaseCountChecker(() =>
|
108
105
|
new RdsHolder(getEnvVariable("SECRET_ID")).setCredentials()
|
109
106
|
);
|
110
107
|
}
|
111
108
|
|
112
|
-
|
109
|
+
/**
|
110
|
+
* Expect that the count is 1
|
111
|
+
*/
|
112
|
+
expectOne(name: string, sql: string) {
|
113
113
|
this.checks.push(new CountDatabaseCheck(name, sql, 1, 1));
|
114
114
|
|
115
115
|
return this;
|
116
116
|
}
|
117
117
|
|
118
|
-
|
118
|
+
/**
|
119
|
+
* Expect that the count is 0
|
120
|
+
*/
|
121
|
+
expectZero(name: string, sql: string) {
|
119
122
|
this.checks.push(new CountDatabaseCheck(name, sql, null, 0));
|
120
123
|
|
121
124
|
return this;
|
122
125
|
}
|
123
126
|
|
124
|
-
|
127
|
+
/**
|
128
|
+
* Expect that the count is 1 or more
|
129
|
+
*/
|
130
|
+
expectOneOrMore(name: string, sql: string) {
|
125
131
|
this.checks.push(new CountDatabaseCheck(name, sql, 1, null));
|
126
132
|
|
127
133
|
return this;
|
@@ -137,7 +143,7 @@ export class DatabaseChecker {
|
|
137
143
|
for (const check of this.checks) {
|
138
144
|
console.info("canary checking sql " + check.sql);
|
139
145
|
|
140
|
-
const value = await db.
|
146
|
+
const value = await db.one<CountResponse>(check.sql);
|
141
147
|
const checkFunction = () => {
|
142
148
|
check.check(value);
|
143
149
|
};
|
@@ -0,0 +1,57 @@
|
|
1
|
+
import { IVpc, Vpc } from "aws-cdk-lib/aws-ec2";
|
2
|
+
import { CfnOutput, Fn, Stack } from "aws-cdk-lib";
|
3
|
+
import { Construct } from "constructs";
|
4
|
+
|
5
|
+
export class OldStackImports {
|
6
|
+
public static AURORAINSTANCE_SG_IMPORT_NAME = "AuroraInstanceSG";
|
7
|
+
public static RDSPROXY_SG_IMPORT_NAME = "RDSProxySG";
|
8
|
+
}
|
9
|
+
|
10
|
+
/**
|
11
|
+
* Import VPC from other stack outputs
|
12
|
+
*/
|
13
|
+
export function importVpc(scope: Construct, environmentName: string): IVpc {
|
14
|
+
const vpcId = importValue(environmentName, "VPCID");
|
15
|
+
const privateSubnetIds = [
|
16
|
+
importValue(environmentName, "digitrafficprivateASubnet"),
|
17
|
+
importValue(environmentName, "digitrafficprivateBSubnet"),
|
18
|
+
];
|
19
|
+
const availabilityZones = ["euw1-az1", "euw1-az2"];
|
20
|
+
|
21
|
+
// VPC reference construction requires vpcId and availability zones
|
22
|
+
// private subnets are used in Lambda configuration
|
23
|
+
return Vpc.fromVpcAttributes(scope, "vpc", {
|
24
|
+
vpcId,
|
25
|
+
privateSubnetIds,
|
26
|
+
availabilityZones,
|
27
|
+
});
|
28
|
+
}
|
29
|
+
|
30
|
+
/**
|
31
|
+
* Import value from other stack output. Stack outputs are named with
|
32
|
+
* digitraffic-${environmentName}-${name} pattern and this function takes care of it
|
33
|
+
*/
|
34
|
+
export function importValue(environmentName: string, name: string): string {
|
35
|
+
return Fn.importValue(outputName(environmentName, name));
|
36
|
+
}
|
37
|
+
|
38
|
+
/**
|
39
|
+
* Export value as stack output. Use same naming pattern as importValue.
|
40
|
+
*/
|
41
|
+
export function exportValue(
|
42
|
+
stack: Stack,
|
43
|
+
environmentName: string,
|
44
|
+
name: string,
|
45
|
+
value: string
|
46
|
+
) {
|
47
|
+
const exportName = outputName(environmentName, name);
|
48
|
+
|
49
|
+
new CfnOutput(stack, exportName, {
|
50
|
+
exportName,
|
51
|
+
value,
|
52
|
+
});
|
53
|
+
}
|
54
|
+
|
55
|
+
export function outputName(environmentName: string, name: string): string {
|
56
|
+
return `digitraffic-${environmentName}-${name}`;
|
57
|
+
}
|
@@ -78,8 +78,8 @@ export class DigitrafficRestApi extends RestApi {
|
|
78
78
|
return newKeyId;
|
79
79
|
}
|
80
80
|
|
81
|
-
createUsagePlanV2(apiName: string): string {
|
82
|
-
const newKeyId = createDefaultUsagePlan(this, apiName).keyId;
|
81
|
+
createUsagePlanV2(apiName: string, apiKey?: string): string {
|
82
|
+
const newKeyId = createDefaultUsagePlan(this, apiName, apiKey).keyId;
|
83
83
|
|
84
84
|
this.apiKeyIds.push(newKeyId);
|
85
85
|
|
@@ -0,0 +1,88 @@
|
|
1
|
+
import { Duration, RemovalPolicy, Stack } from "aws-cdk-lib";
|
2
|
+
import { Construct } from "constructs";
|
3
|
+
import {
|
4
|
+
PrivateHostedZone,
|
5
|
+
RecordSet,
|
6
|
+
RecordTarget,
|
7
|
+
RecordType,
|
8
|
+
} from "aws-cdk-lib/aws-route53";
|
9
|
+
import { InfraStackConfiguration } from "./intra-stack-configuration";
|
10
|
+
import { importValue, importVpc } from "../import-util";
|
11
|
+
import { DbStack } from "./db-stack";
|
12
|
+
import { DbProxyStack } from "./db-proxy-stack";
|
13
|
+
|
14
|
+
const DEFAULT_RECORD_TTL = Duration.seconds(30);
|
15
|
+
|
16
|
+
/**
|
17
|
+
* Creates a dns local zone and creates records for cluster endpoints and proxy endpoints.
|
18
|
+
*
|
19
|
+
*/
|
20
|
+
export class DbDnsStack extends Stack {
|
21
|
+
constructor(scope: Construct, id: string, isc: InfraStackConfiguration) {
|
22
|
+
super(scope, id, {
|
23
|
+
env: isc.env,
|
24
|
+
});
|
25
|
+
|
26
|
+
this.createDnsRecords(isc);
|
27
|
+
}
|
28
|
+
|
29
|
+
createDnsRecords(isc: InfraStackConfiguration) {
|
30
|
+
const vpc = importVpc(this, isc.environmentName);
|
31
|
+
const zone = new PrivateHostedZone(this, "DNSHostedZone", {
|
32
|
+
zoneName: isc.environmentName + ".local",
|
33
|
+
vpc,
|
34
|
+
});
|
35
|
+
|
36
|
+
zone.applyRemovalPolicy(RemovalPolicy.RETAIN);
|
37
|
+
|
38
|
+
const clusterReaderEndpoint = importValue(
|
39
|
+
isc.environmentName,
|
40
|
+
DbStack.CLUSTER_READ_ENDPOINT_EXPORT_NAME
|
41
|
+
);
|
42
|
+
const clusterWriterEndpoint = importValue(
|
43
|
+
isc.environmentName,
|
44
|
+
DbStack.CLUSTER_WRITE_ENDPOINT_EXPORT_NAME
|
45
|
+
);
|
46
|
+
|
47
|
+
const proxyReaderEndpoint = importValue(
|
48
|
+
isc.environmentName,
|
49
|
+
DbProxyStack.PROXY_READER_EXPORT_NAME
|
50
|
+
);
|
51
|
+
const proxyWriterEndpoint = importValue(
|
52
|
+
isc.environmentName,
|
53
|
+
DbProxyStack.PROXY_WRITER_EXPORT_NAME
|
54
|
+
);
|
55
|
+
|
56
|
+
new RecordSet(this, "ReaderRecord", {
|
57
|
+
recordType: RecordType.CNAME,
|
58
|
+
recordName: `db-ro.${isc.environmentName}.local`,
|
59
|
+
target: RecordTarget.fromValues(clusterReaderEndpoint),
|
60
|
+
ttl: DEFAULT_RECORD_TTL,
|
61
|
+
zone,
|
62
|
+
});
|
63
|
+
|
64
|
+
new RecordSet(this, "WriterRecord", {
|
65
|
+
recordType: RecordType.CNAME,
|
66
|
+
recordName: `db.${isc.environmentName}.local`,
|
67
|
+
target: RecordTarget.fromValues(clusterWriterEndpoint),
|
68
|
+
ttl: DEFAULT_RECORD_TTL,
|
69
|
+
zone,
|
70
|
+
});
|
71
|
+
|
72
|
+
new RecordSet(this, "ProxyReaderRecord", {
|
73
|
+
recordType: RecordType.CNAME,
|
74
|
+
recordName: `proxy-ro.${isc.environmentName}.local`,
|
75
|
+
target: RecordTarget.fromValues(proxyReaderEndpoint),
|
76
|
+
ttl: DEFAULT_RECORD_TTL,
|
77
|
+
zone,
|
78
|
+
});
|
79
|
+
|
80
|
+
new RecordSet(this, "ProxyWriterRecord", {
|
81
|
+
recordType: RecordType.CNAME,
|
82
|
+
recordName: `proxy.${isc.environmentName}.local`,
|
83
|
+
target: RecordTarget.fromValues(proxyWriterEndpoint),
|
84
|
+
ttl: DEFAULT_RECORD_TTL,
|
85
|
+
zone,
|
86
|
+
});
|
87
|
+
}
|
88
|
+
}
|
@@ -0,0 +1,129 @@
|
|
1
|
+
import { Duration, Stack } from "aws-cdk-lib";
|
2
|
+
import { Construct } from "constructs";
|
3
|
+
import {
|
4
|
+
CfnDBProxyEndpoint,
|
5
|
+
DatabaseCluster,
|
6
|
+
DatabaseClusterEngine,
|
7
|
+
DatabaseProxy,
|
8
|
+
ProxyTarget,
|
9
|
+
} from "aws-cdk-lib/aws-rds";
|
10
|
+
import { ISecret, Secret } from "aws-cdk-lib/aws-secretsmanager";
|
11
|
+
import { IVpc, SecurityGroup } from "aws-cdk-lib/aws-ec2";
|
12
|
+
import { InfraStackConfiguration } from "./intra-stack-configuration";
|
13
|
+
import { DbConfiguration, DbStack } from "./db-stack";
|
14
|
+
import { exportValue, importValue, importVpc } from "../import-util";
|
15
|
+
|
16
|
+
/**
|
17
|
+
* A stack that creates a Database proxy.
|
18
|
+
*/
|
19
|
+
export class DbProxyStack extends Stack {
|
20
|
+
public static PROXY_READER_EXPORT_NAME = "db-reader-endpoint";
|
21
|
+
public static PROXY_WRITER_EXPORT_NAME = "db-writer-endpoint";
|
22
|
+
|
23
|
+
readonly isc: InfraStackConfiguration;
|
24
|
+
|
25
|
+
constructor(
|
26
|
+
scope: Construct,
|
27
|
+
id: string,
|
28
|
+
isc: InfraStackConfiguration,
|
29
|
+
configuration: DbConfiguration
|
30
|
+
) {
|
31
|
+
super(scope, id, {
|
32
|
+
env: isc.env,
|
33
|
+
});
|
34
|
+
|
35
|
+
this.isc = isc;
|
36
|
+
|
37
|
+
const vpc = importVpc(this, isc.environmentName);
|
38
|
+
const secret = Secret.fromSecretAttributes(this, "proxy-secret", {
|
39
|
+
secretCompleteArn: configuration.secretArn,
|
40
|
+
});
|
41
|
+
const proxy = this.createProxy(vpc, secret, configuration);
|
42
|
+
const readerEndpoint = this.createProxyEndpoints(
|
43
|
+
vpc,
|
44
|
+
proxy,
|
45
|
+
configuration.securityGroupId
|
46
|
+
);
|
47
|
+
this.setOutputs(configuration, proxy, readerEndpoint);
|
48
|
+
}
|
49
|
+
|
50
|
+
createProxy(vpc: IVpc, secret: ISecret, configuration: DbConfiguration) {
|
51
|
+
const proxyId = `${this.isc.environmentName}-proxy`;
|
52
|
+
const securityGroup = SecurityGroup.fromSecurityGroupId(
|
53
|
+
this,
|
54
|
+
"securitygroup",
|
55
|
+
configuration.securityGroupId
|
56
|
+
);
|
57
|
+
|
58
|
+
const cluster = DatabaseCluster.fromDatabaseClusterAttributes(
|
59
|
+
this,
|
60
|
+
"db-cluster",
|
61
|
+
{
|
62
|
+
clusterIdentifier: importValue(
|
63
|
+
this.isc.environmentName,
|
64
|
+
DbStack.CLUSTER_IDENTIFIER_EXPORT_NAME
|
65
|
+
),
|
66
|
+
engine: DatabaseClusterEngine.AURORA_POSTGRESQL,
|
67
|
+
port: DbStack.CLUSTER_PORT,
|
68
|
+
}
|
69
|
+
);
|
70
|
+
|
71
|
+
// CDK tries to allow connections between proxy and cluster
|
72
|
+
// this does not work on cluster references
|
73
|
+
cluster.connections.allowDefaultPortFrom = () => {
|
74
|
+
/* nothing */
|
75
|
+
};
|
76
|
+
|
77
|
+
return new DatabaseProxy(this, proxyId, {
|
78
|
+
dbProxyName: configuration.dbProxyName ?? "AuroraProxy",
|
79
|
+
securityGroups: [securityGroup],
|
80
|
+
proxyTarget: ProxyTarget.fromCluster(cluster),
|
81
|
+
idleClientTimeout: Duration.seconds(1800),
|
82
|
+
maxConnectionsPercent: 50,
|
83
|
+
maxIdleConnectionsPercent: 25,
|
84
|
+
borrowTimeout: Duration.seconds(120),
|
85
|
+
requireTLS: false,
|
86
|
+
secrets: [secret],
|
87
|
+
vpc: vpc,
|
88
|
+
});
|
89
|
+
}
|
90
|
+
|
91
|
+
createProxyEndpoints(
|
92
|
+
vpc: IVpc,
|
93
|
+
proxy: DatabaseProxy,
|
94
|
+
securityGroupId: string
|
95
|
+
) {
|
96
|
+
return new CfnDBProxyEndpoint(this, "ReaderEndpoint", {
|
97
|
+
dbProxyEndpointName: "ReaderEndpoint",
|
98
|
+
dbProxyName: proxy.dbProxyName,
|
99
|
+
vpcSubnetIds: vpc.privateSubnets.map((sub) => sub.subnetId),
|
100
|
+
vpcSecurityGroupIds: [securityGroupId],
|
101
|
+
targetRole: "READ_ONLY",
|
102
|
+
});
|
103
|
+
}
|
104
|
+
|
105
|
+
setOutputs(
|
106
|
+
configuration: DbConfiguration,
|
107
|
+
proxy: DatabaseProxy,
|
108
|
+
proxyEndpoint: CfnDBProxyEndpoint
|
109
|
+
) {
|
110
|
+
const readerEndpoint =
|
111
|
+
configuration.instances > 1
|
112
|
+
? proxyEndpoint.attrEndpoint
|
113
|
+
: proxy.endpoint;
|
114
|
+
|
115
|
+
// if only one instance, then there is no reader-endpoint
|
116
|
+
exportValue(
|
117
|
+
this,
|
118
|
+
this.isc.environmentName,
|
119
|
+
DbProxyStack.PROXY_READER_EXPORT_NAME,
|
120
|
+
readerEndpoint
|
121
|
+
);
|
122
|
+
exportValue(
|
123
|
+
this,
|
124
|
+
this.isc.environmentName,
|
125
|
+
DbProxyStack.PROXY_WRITER_EXPORT_NAME,
|
126
|
+
proxy.endpoint
|
127
|
+
);
|
128
|
+
}
|
129
|
+
}
|