cdk-dms-replication 0.0.0
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/.jsii +13491 -0
- package/API.md +8606 -0
- package/LICENSE +202 -0
- package/README.md +883 -0
- package/cdk.context.json +1 -0
- package/integ/sample-app.ts +229 -0
- package/lib/dms-roles.d.ts +14 -0
- package/lib/dms-roles.js +42 -0
- package/lib/endpoint-settings.d.ts +419 -0
- package/lib/endpoint-settings.js +3 -0
- package/lib/endpoint.d.ts +143 -0
- package/lib/endpoint.js +402 -0
- package/lib/enums.d.ts +231 -0
- package/lib/enums.js +266 -0
- package/lib/index.d.ts +9 -0
- package/lib/index.js +49 -0
- package/lib/migration-pipeline.d.ts +253 -0
- package/lib/migration-pipeline.js +218 -0
- package/lib/replication-instance.d.ts +99 -0
- package/lib/replication-instance.js +93 -0
- package/lib/replication-task.d.ts +72 -0
- package/lib/replication-task.js +46 -0
- package/lib/serverless-pipeline.d.ts +196 -0
- package/lib/serverless-pipeline.js +271 -0
- package/lib/table-mappings.d.ts +178 -0
- package/lib/table-mappings.js +283 -0
- package/lib/task-settings.d.ts +228 -0
- package/lib/task-settings.js +291 -0
- package/package.json +170 -0
- package/scripts/sync-instance-classes.js +213 -0
package/cdk.context.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import * as cdk from 'aws-cdk-lib';
|
|
2
|
+
import * as ec2 from 'aws-cdk-lib/aws-ec2';
|
|
3
|
+
import * as kms from 'aws-cdk-lib/aws-kms';
|
|
4
|
+
import {
|
|
5
|
+
DmsEndpoint,
|
|
6
|
+
DmsMigrationPipeline,
|
|
7
|
+
DmsReplicationInstance,
|
|
8
|
+
DmsServerlessPipeline,
|
|
9
|
+
EndpointEngine,
|
|
10
|
+
EndpointType,
|
|
11
|
+
MigrationType,
|
|
12
|
+
ReplicationInstanceClass,
|
|
13
|
+
TableMappings,
|
|
14
|
+
TaskSettings,
|
|
15
|
+
LobMode,
|
|
16
|
+
ErrorAction,
|
|
17
|
+
} from '../src';
|
|
18
|
+
|
|
19
|
+
const app = new cdk.App();
|
|
20
|
+
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Stack 1: Classic DmsMigrationPipeline — MySQL → Aurora PostgreSQL
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
const classicStack = new cdk.Stack(app, 'IntegClassicPipeline');
|
|
25
|
+
|
|
26
|
+
const classicVpc = new ec2.Vpc(classicStack, 'Vpc', {
|
|
27
|
+
maxAzs: 2,
|
|
28
|
+
natGateways: 1,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
new DmsMigrationPipeline(classicStack, 'MySqlToAurora', {
|
|
32
|
+
vpc: classicVpc,
|
|
33
|
+
migrationType: MigrationType.FULL_LOAD_AND_CDC,
|
|
34
|
+
replicationInstanceClass: ReplicationInstanceClass.R6I_LARGE,
|
|
35
|
+
sourceEndpoint: {
|
|
36
|
+
engine: EndpointEngine.MYSQL,
|
|
37
|
+
serverName: 'mysql.example.com',
|
|
38
|
+
port: 3306,
|
|
39
|
+
username: 'dms_user',
|
|
40
|
+
password: cdk.SecretValue.secretsManager('mysql-dms-secret'),
|
|
41
|
+
databaseName: 'mydb',
|
|
42
|
+
},
|
|
43
|
+
targetEndpoint: {
|
|
44
|
+
engine: EndpointEngine.AURORA_POSTGRESQL,
|
|
45
|
+
serverName: 'aurora.cluster.us-east-1.rds.amazonaws.com',
|
|
46
|
+
port: 5432,
|
|
47
|
+
username: 'dms_user',
|
|
48
|
+
password: cdk.SecretValue.secretsManager('aurora-dms-secret'),
|
|
49
|
+
databaseName: 'mydb',
|
|
50
|
+
},
|
|
51
|
+
tableMappings: new TableMappings().includeSchema('public').toJson(),
|
|
52
|
+
taskSettings: new TaskSettings()
|
|
53
|
+
.withLobMode(LobMode.LIMITED_LOB, 32)
|
|
54
|
+
.withFullLoadSubTasks(16)
|
|
55
|
+
.withBatchApply(true, 5, 60)
|
|
56
|
+
.withDataErrorPolicy(ErrorAction.IGNORE_RECORD, 100)
|
|
57
|
+
.toJson(),
|
|
58
|
+
multiAz: true,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
// Stack 2: Classic pipeline — Oracle → S3 (no CDC roles, shared KMS key)
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
const oracleStack = new cdk.Stack(app, 'IntegOracleToS3');
|
|
65
|
+
|
|
66
|
+
const oracleVpc = new ec2.Vpc(oracleStack, 'Vpc', { maxAzs: 2, natGateways: 1 });
|
|
67
|
+
const sharedKey = new kms.Key(oracleStack, 'SharedKey', { enableKeyRotation: true });
|
|
68
|
+
|
|
69
|
+
new DmsMigrationPipeline(oracleStack, 'OracleToS3', {
|
|
70
|
+
vpc: oracleVpc,
|
|
71
|
+
migrationType: MigrationType.FULL_LOAD,
|
|
72
|
+
replicationInstanceClass: ReplicationInstanceClass.C6I_2XLARGE,
|
|
73
|
+
encryptionKey: sharedKey,
|
|
74
|
+
sourceEndpoint: {
|
|
75
|
+
engine: EndpointEngine.ORACLE,
|
|
76
|
+
serverName: 'oracle.example.com',
|
|
77
|
+
port: 1521,
|
|
78
|
+
username: 'dms_user',
|
|
79
|
+
password: cdk.SecretValue.secretsManager('oracle-dms-secret'),
|
|
80
|
+
databaseName: 'ORCL',
|
|
81
|
+
oracleSettings: {
|
|
82
|
+
addSupplementalLogging: true,
|
|
83
|
+
useLogminerReader: true,
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
targetEndpoint: {
|
|
87
|
+
engine: EndpointEngine.S3,
|
|
88
|
+
s3Settings: {
|
|
89
|
+
bucketName: 'my-dms-target-bucket',
|
|
90
|
+
serviceAccessRoleArn: 'arn:aws:iam::123456789012:role/dms-s3-role',
|
|
91
|
+
dataFormat: 'parquet' as any,
|
|
92
|
+
datePartitionEnabled: true,
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
createDmsServiceRoles: false,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
// Stack 3: Serverless pipeline — PostgreSQL → Redshift
|
|
100
|
+
// ---------------------------------------------------------------------------
|
|
101
|
+
const serverlessStack = new cdk.Stack(app, 'IntegServerlessPipeline');
|
|
102
|
+
|
|
103
|
+
const serverlessVpc = new ec2.Vpc(serverlessStack, 'Vpc', { maxAzs: 2, natGateways: 1 });
|
|
104
|
+
|
|
105
|
+
new DmsServerlessPipeline(serverlessStack, 'PgToRedshift', {
|
|
106
|
+
vpc: serverlessVpc,
|
|
107
|
+
maxCapacityUnits: 16,
|
|
108
|
+
minCapacityUnits: 2,
|
|
109
|
+
migrationType: MigrationType.FULL_LOAD_AND_CDC,
|
|
110
|
+
sourceEndpoint: {
|
|
111
|
+
engine: EndpointEngine.POSTGRES,
|
|
112
|
+
serverName: 'pg.example.com',
|
|
113
|
+
port: 5432,
|
|
114
|
+
username: 'dms_user',
|
|
115
|
+
password: cdk.SecretValue.secretsManager('pg-dms-secret'),
|
|
116
|
+
databaseName: 'mydb',
|
|
117
|
+
postgreSqlSettings: {
|
|
118
|
+
pluginName: 'pglogical' as any,
|
|
119
|
+
heartbeatEnable: true,
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
targetEndpoint: {
|
|
123
|
+
engine: EndpointEngine.REDSHIFT,
|
|
124
|
+
serverName: 'redshift.cluster.us-east-1.redshift.amazonaws.com',
|
|
125
|
+
port: 5439,
|
|
126
|
+
username: 'dms_user',
|
|
127
|
+
password: cdk.SecretValue.secretsManager('redshift-dms-secret'),
|
|
128
|
+
databaseName: 'mydb',
|
|
129
|
+
},
|
|
130
|
+
tableMappings: new TableMappings().includeSchema('public').toJson(),
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
// Stack 4: Standalone DmsReplicationInstance (escape-hatch usage)
|
|
135
|
+
// ---------------------------------------------------------------------------
|
|
136
|
+
const instanceStack = new cdk.Stack(app, 'IntegReplicationInstance');
|
|
137
|
+
|
|
138
|
+
const instanceVpc = new ec2.Vpc(instanceStack, 'Vpc', { maxAzs: 2, natGateways: 1 });
|
|
139
|
+
|
|
140
|
+
const ri = new DmsReplicationInstance(instanceStack, 'Instance', {
|
|
141
|
+
vpc: instanceVpc,
|
|
142
|
+
replicationInstanceClass: ReplicationInstanceClass.T3_MEDIUM,
|
|
143
|
+
allocatedStorage: 50,
|
|
144
|
+
engineVersion: '3.5.4',
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
ri.allowInboundFrom(
|
|
148
|
+
ec2.Peer.ipv4('10.0.0.0/8'),
|
|
149
|
+
ec2.Port.tcp(5432),
|
|
150
|
+
'Allow internal PostgreSQL',
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
// ---------------------------------------------------------------------------
|
|
154
|
+
// Stack 5: CDC-only pipeline — SQL Server → Kinesis
|
|
155
|
+
// Exercises MigrationType.CDC and cdcStartPosition, which take a different
|
|
156
|
+
// code path in DmsReplicationTask than FULL_LOAD or FULL_LOAD_AND_CDC.
|
|
157
|
+
// ---------------------------------------------------------------------------
|
|
158
|
+
const cdcStack = new cdk.Stack(app, 'IntegCdcPipeline');
|
|
159
|
+
|
|
160
|
+
const cdcVpc = new ec2.Vpc(cdcStack, 'Vpc', { maxAzs: 2, natGateways: 1 });
|
|
161
|
+
|
|
162
|
+
new DmsMigrationPipeline(cdcStack, 'SqlServerToKinesis', {
|
|
163
|
+
vpc: cdcVpc,
|
|
164
|
+
migrationType: MigrationType.CDC,
|
|
165
|
+
replicationInstanceClass: ReplicationInstanceClass.R6I_LARGE,
|
|
166
|
+
sourceEndpoint: {
|
|
167
|
+
engine: EndpointEngine.SQLSERVER,
|
|
168
|
+
serverName: 'sqlserver.example.com',
|
|
169
|
+
port: 1433,
|
|
170
|
+
username: 'dms_user',
|
|
171
|
+
password: cdk.SecretValue.secretsManager('sqlserver-dms-secret'),
|
|
172
|
+
databaseName: 'mydb',
|
|
173
|
+
sqlServerSettings: {
|
|
174
|
+
readBackupOnly: true,
|
|
175
|
+
tlogAccessMode: 'BackupOnly',
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
targetEndpoint: {
|
|
179
|
+
engine: EndpointEngine.KINESIS,
|
|
180
|
+
kinesisSettings: {
|
|
181
|
+
streamArn: 'arn:aws:kinesis:us-east-1:123456789012:stream/dms-cdc-stream',
|
|
182
|
+
serviceAccessRoleArn: 'arn:aws:iam::123456789012:role/dms-kinesis-role',
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
cdcStartPosition: '0000000000000001:00000001:00000001',
|
|
186
|
+
tableMappings: new TableMappings().includeSchema('%').toJson(),
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// ---------------------------------------------------------------------------
|
|
190
|
+
// Stack 6: Existing endpoints escape hatch — pre-created DmsEndpoint objects
|
|
191
|
+
// Exercises existingSourceEndpoint / existingTargetEndpoint, which skip
|
|
192
|
+
// endpoint creation inside the pipeline construct.
|
|
193
|
+
// ---------------------------------------------------------------------------
|
|
194
|
+
const escapeStack = new cdk.Stack(app, 'IntegExistingEndpoints');
|
|
195
|
+
|
|
196
|
+
const escapeVpc = new ec2.Vpc(escapeStack, 'Vpc', { maxAzs: 2, natGateways: 1 });
|
|
197
|
+
|
|
198
|
+
const existingSource = new DmsEndpoint(escapeStack, 'Source', {
|
|
199
|
+
endpointType: EndpointType.SOURCE,
|
|
200
|
+
engine: EndpointEngine.POSTGRES,
|
|
201
|
+
serverName: 'pg.example.com',
|
|
202
|
+
port: 5432,
|
|
203
|
+
username: 'dms_user',
|
|
204
|
+
password: cdk.SecretValue.secretsManager('pg-dms-secret'),
|
|
205
|
+
databaseName: 'appdb',
|
|
206
|
+
postgreSqlSettings: {
|
|
207
|
+
pluginName: 'pglogical' as any,
|
|
208
|
+
slotName: 'dms_replication_slot',
|
|
209
|
+
},
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
const existingTarget = new DmsEndpoint(escapeStack, 'Target', {
|
|
213
|
+
endpointType: EndpointType.TARGET,
|
|
214
|
+
engine: EndpointEngine.S3,
|
|
215
|
+
s3Settings: {
|
|
216
|
+
bucketName: 'dms-escape-bucket',
|
|
217
|
+
serviceAccessRoleArn: 'arn:aws:iam::123456789012:role/dms-s3-role',
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
new DmsMigrationPipeline(escapeStack, 'Pipeline', {
|
|
222
|
+
vpc: escapeVpc,
|
|
223
|
+
migrationType: MigrationType.FULL_LOAD_AND_CDC,
|
|
224
|
+
existingSourceEndpoint: existingSource,
|
|
225
|
+
existingTargetEndpoint: existingTarget,
|
|
226
|
+
tableMappings: new TableMappings().includeSchema('public').toJson(),
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
app.synth();
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as cdk from 'aws-cdk-lib';
|
|
2
|
+
import * as iam from 'aws-cdk-lib/aws-iam';
|
|
3
|
+
/**
|
|
4
|
+
* Returns the account-level `dms-vpc-role` IAM role, creating it once per stack.
|
|
5
|
+
* DMS requires this exact role name before it can place replication instances or
|
|
6
|
+
* serverless configs inside a VPC.
|
|
7
|
+
*/
|
|
8
|
+
export declare function ensureDmsVpcRole(stack: cdk.Stack): iam.Role;
|
|
9
|
+
/**
|
|
10
|
+
* Returns the account-level `dms-cloudwatch-logs-role` IAM role, creating it
|
|
11
|
+
* once per stack. DMS requires this exact role name to publish task logs to
|
|
12
|
+
* CloudWatch Logs.
|
|
13
|
+
*/
|
|
14
|
+
export declare function ensureDmsCloudWatchRole(stack: cdk.Stack): iam.Role;
|
package/lib/dms-roles.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ensureDmsVpcRole = ensureDmsVpcRole;
|
|
4
|
+
exports.ensureDmsCloudWatchRole = ensureDmsCloudWatchRole;
|
|
5
|
+
const iam = require("aws-cdk-lib/aws-iam");
|
|
6
|
+
/**
|
|
7
|
+
* Returns the account-level `dms-vpc-role` IAM role, creating it once per stack.
|
|
8
|
+
* DMS requires this exact role name before it can place replication instances or
|
|
9
|
+
* serverless configs inside a VPC.
|
|
10
|
+
*/
|
|
11
|
+
function ensureDmsVpcRole(stack) {
|
|
12
|
+
const existing = stack.node.tryFindChild('DmsVpcRole');
|
|
13
|
+
if (existing)
|
|
14
|
+
return existing;
|
|
15
|
+
return new iam.Role(stack, 'DmsVpcRole', {
|
|
16
|
+
roleName: 'dms-vpc-role',
|
|
17
|
+
assumedBy: new iam.ServicePrincipal('dms.amazonaws.com'),
|
|
18
|
+
managedPolicies: [
|
|
19
|
+
iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonDMSVPCManagementRole'),
|
|
20
|
+
],
|
|
21
|
+
description: 'Allows DMS to manage VPC resources for replication instances',
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Returns the account-level `dms-cloudwatch-logs-role` IAM role, creating it
|
|
26
|
+
* once per stack. DMS requires this exact role name to publish task logs to
|
|
27
|
+
* CloudWatch Logs.
|
|
28
|
+
*/
|
|
29
|
+
function ensureDmsCloudWatchRole(stack) {
|
|
30
|
+
const existing = stack.node.tryFindChild('DmsCloudWatchLogsRole');
|
|
31
|
+
if (existing)
|
|
32
|
+
return existing;
|
|
33
|
+
return new iam.Role(stack, 'DmsCloudWatchLogsRole', {
|
|
34
|
+
roleName: 'dms-cloudwatch-logs-role',
|
|
35
|
+
assumedBy: new iam.ServicePrincipal('dms.amazonaws.com'),
|
|
36
|
+
managedPolicies: [
|
|
37
|
+
iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonDMSCloudWatchLogsRole'),
|
|
38
|
+
],
|
|
39
|
+
description: 'Allows DMS to publish task logs to CloudWatch Logs',
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG1zLXJvbGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2Rtcy1yb2xlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQVFBLDRDQVdDO0FBT0QsMERBV0M7QUFwQ0QsMkNBQTJDO0FBRTNDOzs7O0dBSUc7QUFDSCxTQUFnQixnQkFBZ0IsQ0FBQyxLQUFnQjtJQUMvQyxNQUFNLFFBQVEsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUN2RCxJQUFJLFFBQVE7UUFBRSxPQUFPLFFBQW9CLENBQUM7SUFDMUMsT0FBTyxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLFlBQVksRUFBRTtRQUN2QyxRQUFRLEVBQUUsY0FBYztRQUN4QixTQUFTLEVBQUUsSUFBSSxHQUFHLENBQUMsZ0JBQWdCLENBQUMsbUJBQW1CLENBQUM7UUFDeEQsZUFBZSxFQUFFO1lBQ2YsR0FBRyxDQUFDLGFBQWEsQ0FBQyx3QkFBd0IsQ0FBQyx5Q0FBeUMsQ0FBQztTQUN0RjtRQUNELFdBQVcsRUFBRSw4REFBOEQ7S0FDNUUsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFnQix1QkFBdUIsQ0FBQyxLQUFnQjtJQUN0RCxNQUFNLFFBQVEsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO0lBQ2xFLElBQUksUUFBUTtRQUFFLE9BQU8sUUFBb0IsQ0FBQztJQUMxQyxPQUFPLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsdUJBQXVCLEVBQUU7UUFDbEQsUUFBUSxFQUFFLDBCQUEwQjtRQUNwQyxTQUFTLEVBQUUsSUFBSSxHQUFHLENBQUMsZ0JBQWdCLENBQUMsbUJBQW1CLENBQUM7UUFDeEQsZUFBZSxFQUFFO1lBQ2YsR0FBRyxDQUFDLGFBQWEsQ0FBQyx3QkFBd0IsQ0FBQywwQ0FBMEMsQ0FBQztTQUN2RjtRQUNELFdBQVcsRUFBRSxvREFBb0Q7S0FDbEUsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGNkayBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgKiBhcyBpYW0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWlhbSc7XG5cbi8qKlxuICogUmV0dXJucyB0aGUgYWNjb3VudC1sZXZlbCBgZG1zLXZwYy1yb2xlYCBJQU0gcm9sZSwgY3JlYXRpbmcgaXQgb25jZSBwZXIgc3RhY2suXG4gKiBETVMgcmVxdWlyZXMgdGhpcyBleGFjdCByb2xlIG5hbWUgYmVmb3JlIGl0IGNhbiBwbGFjZSByZXBsaWNhdGlvbiBpbnN0YW5jZXMgb3JcbiAqIHNlcnZlcmxlc3MgY29uZmlncyBpbnNpZGUgYSBWUEMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbnN1cmVEbXNWcGNSb2xlKHN0YWNrOiBjZGsuU3RhY2spOiBpYW0uUm9sZSB7XG4gIGNvbnN0IGV4aXN0aW5nID0gc3RhY2subm9kZS50cnlGaW5kQ2hpbGQoJ0Rtc1ZwY1JvbGUnKTtcbiAgaWYgKGV4aXN0aW5nKSByZXR1cm4gZXhpc3RpbmcgYXMgaWFtLlJvbGU7XG4gIHJldHVybiBuZXcgaWFtLlJvbGUoc3RhY2ssICdEbXNWcGNSb2xlJywge1xuICAgIHJvbGVOYW1lOiAnZG1zLXZwYy1yb2xlJyxcbiAgICBhc3N1bWVkQnk6IG5ldyBpYW0uU2VydmljZVByaW5jaXBhbCgnZG1zLmFtYXpvbmF3cy5jb20nKSxcbiAgICBtYW5hZ2VkUG9saWNpZXM6IFtcbiAgICAgIGlhbS5NYW5hZ2VkUG9saWN5LmZyb21Bd3NNYW5hZ2VkUG9saWN5TmFtZSgnc2VydmljZS1yb2xlL0FtYXpvbkRNU1ZQQ01hbmFnZW1lbnRSb2xlJyksXG4gICAgXSxcbiAgICBkZXNjcmlwdGlvbjogJ0FsbG93cyBETVMgdG8gbWFuYWdlIFZQQyByZXNvdXJjZXMgZm9yIHJlcGxpY2F0aW9uIGluc3RhbmNlcycsXG4gIH0pO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIGFjY291bnQtbGV2ZWwgYGRtcy1jbG91ZHdhdGNoLWxvZ3Mtcm9sZWAgSUFNIHJvbGUsIGNyZWF0aW5nIGl0XG4gKiBvbmNlIHBlciBzdGFjay4gRE1TIHJlcXVpcmVzIHRoaXMgZXhhY3Qgcm9sZSBuYW1lIHRvIHB1Ymxpc2ggdGFzayBsb2dzIHRvXG4gKiBDbG91ZFdhdGNoIExvZ3MuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbnN1cmVEbXNDbG91ZFdhdGNoUm9sZShzdGFjazogY2RrLlN0YWNrKTogaWFtLlJvbGUge1xuICBjb25zdCBleGlzdGluZyA9IHN0YWNrLm5vZGUudHJ5RmluZENoaWxkKCdEbXNDbG91ZFdhdGNoTG9nc1JvbGUnKTtcbiAgaWYgKGV4aXN0aW5nKSByZXR1cm4gZXhpc3RpbmcgYXMgaWFtLlJvbGU7XG4gIHJldHVybiBuZXcgaWFtLlJvbGUoc3RhY2ssICdEbXNDbG91ZFdhdGNoTG9nc1JvbGUnLCB7XG4gICAgcm9sZU5hbWU6ICdkbXMtY2xvdWR3YXRjaC1sb2dzLXJvbGUnLFxuICAgIGFzc3VtZWRCeTogbmV3IGlhbS5TZXJ2aWNlUHJpbmNpcGFsKCdkbXMuYW1hem9uYXdzLmNvbScpLFxuICAgIG1hbmFnZWRQb2xpY2llczogW1xuICAgICAgaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKCdzZXJ2aWNlLXJvbGUvQW1hem9uRE1TQ2xvdWRXYXRjaExvZ3NSb2xlJyksXG4gICAgXSxcbiAgICBkZXNjcmlwdGlvbjogJ0FsbG93cyBETVMgdG8gcHVibGlzaCB0YXNrIGxvZ3MgdG8gQ2xvdWRXYXRjaCBMb2dzJyxcbiAgfSk7XG59XG4iXX0=
|