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
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var _a;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.DmsServerlessPipeline = void 0;
|
|
5
|
+
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
|
|
6
|
+
const cdk = require("aws-cdk-lib");
|
|
7
|
+
const dms = require("aws-cdk-lib/aws-dms");
|
|
8
|
+
const ec2 = require("aws-cdk-lib/aws-ec2");
|
|
9
|
+
const kms = require("aws-cdk-lib/aws-kms");
|
|
10
|
+
const logs = require("aws-cdk-lib/aws-logs");
|
|
11
|
+
const constructs_1 = require("constructs");
|
|
12
|
+
const dms_roles_1 = require("./dms-roles");
|
|
13
|
+
const endpoint_1 = require("./endpoint");
|
|
14
|
+
const enums_1 = require("./enums");
|
|
15
|
+
const table_mappings_1 = require("./table-mappings");
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
// Valid capacity unit values — documented in the DMS API reference
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
const VALID_CAPACITY_UNITS = new Set([1, 2, 4, 8, 16, 32, 64, 128, 192, 256, 384]);
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// Construct
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
/**
|
|
24
|
+
* An L3 CDK pattern construct that provisions a DMS Serverless replication
|
|
25
|
+
* pipeline:
|
|
26
|
+
*
|
|
27
|
+
* - **Replication config** — backed by `CfnReplicationConfig`; DMS auto-scales
|
|
28
|
+
* capacity between `minCapacityUnits` and `maxCapacityUnits`.
|
|
29
|
+
* - **Source endpoint** — supports every engine DMS supports.
|
|
30
|
+
* - **Target endpoint** — supports every engine DMS supports.
|
|
31
|
+
* - **Subnet group** — private subnet placement.
|
|
32
|
+
* - **KMS key** — storage encryption at rest (created if not provided).
|
|
33
|
+
* - **Security group** — dedicated group (created if not provided).
|
|
34
|
+
* - **IAM roles** — `dms-vpc-role` and `dms-cloudwatch-logs-role`.
|
|
35
|
+
* - **CloudWatch log group** — (optional) retains replication logs.
|
|
36
|
+
*
|
|
37
|
+
* > **CDC start/stop position limitation**: `CfnReplicationConfig` does not
|
|
38
|
+
* > expose `cdcStartTime` / `cdcStartPosition` / `cdcStopPosition`. To start
|
|
39
|
+
* > from a specific position, call the `StartReplication` API directly after
|
|
40
|
+
* > the config is created (e.g. from a Lambda custom resource or CLI).
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* const pipeline = new DmsServerlessPipeline(this, 'ServerlessPipeline', {
|
|
44
|
+
* vpc,
|
|
45
|
+
* maxCapacityUnits: 8,
|
|
46
|
+
* migrationType: MigrationType.FULL_LOAD_AND_CDC,
|
|
47
|
+
* sourceEndpoint: {
|
|
48
|
+
* engine: EndpointEngine.MYSQL,
|
|
49
|
+
* serverName: 'mysql.example.com',
|
|
50
|
+
* port: 3306,
|
|
51
|
+
* username: 'dms_user',
|
|
52
|
+
* password: cdk.SecretValue.secretsManager('mysql-dms-secret'),
|
|
53
|
+
* },
|
|
54
|
+
* targetEndpoint: {
|
|
55
|
+
* engine: EndpointEngine.AURORA_POSTGRESQL,
|
|
56
|
+
* serverName: cluster.clusterEndpoint.hostname,
|
|
57
|
+
* port: 5432,
|
|
58
|
+
* username: 'dms_user',
|
|
59
|
+
* password: cdk.SecretValue.secretsManager('aurora-dms-secret'),
|
|
60
|
+
* },
|
|
61
|
+
* });
|
|
62
|
+
*/
|
|
63
|
+
class DmsServerlessPipeline extends constructs_1.Construct {
|
|
64
|
+
constructor(scope, id, props) {
|
|
65
|
+
super(scope, id);
|
|
66
|
+
this.validateProps(props);
|
|
67
|
+
const removalPolicy = props.removalPolicy ?? cdk.RemovalPolicy.DESTROY;
|
|
68
|
+
const createRoles = props.createDmsServiceRoles ?? true;
|
|
69
|
+
// -----------------------------------------------------------------------
|
|
70
|
+
// dms-vpc-role — required by DMS to place the config inside a VPC.
|
|
71
|
+
// -----------------------------------------------------------------------
|
|
72
|
+
if (createRoles) {
|
|
73
|
+
this.dmsVpcRole = (0, dms_roles_1.ensureDmsVpcRole)(cdk.Stack.of(this));
|
|
74
|
+
}
|
|
75
|
+
// -----------------------------------------------------------------------
|
|
76
|
+
// CloudWatch log group & IAM role
|
|
77
|
+
// -----------------------------------------------------------------------
|
|
78
|
+
const enableLogs = props.enableCloudWatchLogs ?? true;
|
|
79
|
+
if (enableLogs) {
|
|
80
|
+
this.logGroup = new logs.LogGroup(this, 'LogGroup', {
|
|
81
|
+
logGroupName: `/aws/dms/serverless/${id}`,
|
|
82
|
+
retention: props.logRetention ?? logs.RetentionDays.ONE_MONTH,
|
|
83
|
+
removalPolicy,
|
|
84
|
+
});
|
|
85
|
+
if (createRoles) {
|
|
86
|
+
this.dmsCloudWatchRole = (0, dms_roles_1.ensureDmsCloudWatchRole)(cdk.Stack.of(this));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// -----------------------------------------------------------------------
|
|
90
|
+
// KMS key
|
|
91
|
+
// -----------------------------------------------------------------------
|
|
92
|
+
this.encryptionKey =
|
|
93
|
+
props.kmsKey ??
|
|
94
|
+
new kms.Key(this, 'EncryptionKey', {
|
|
95
|
+
description: `DMS serverless replication encryption key for ${id}`,
|
|
96
|
+
enableKeyRotation: true,
|
|
97
|
+
removalPolicy,
|
|
98
|
+
});
|
|
99
|
+
// -----------------------------------------------------------------------
|
|
100
|
+
// Security group
|
|
101
|
+
// -----------------------------------------------------------------------
|
|
102
|
+
const providedSgs = props.securityGroups ?? [];
|
|
103
|
+
if (providedSgs.length === 0) {
|
|
104
|
+
this.securityGroup = new ec2.SecurityGroup(this, 'SecurityGroup', {
|
|
105
|
+
vpc: props.vpc,
|
|
106
|
+
description: `DMS serverless replication security group for ${id}`,
|
|
107
|
+
allowAllOutbound: true,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
this.securityGroup = providedSgs[0];
|
|
112
|
+
}
|
|
113
|
+
const securityGroupIds = providedSgs.length > 0
|
|
114
|
+
? providedSgs.map((sg) => sg.securityGroupId)
|
|
115
|
+
: [this.securityGroup.securityGroupId];
|
|
116
|
+
// -----------------------------------------------------------------------
|
|
117
|
+
// Subnet group
|
|
118
|
+
// -----------------------------------------------------------------------
|
|
119
|
+
const subnetSelection = props.vpcSubnets ?? {
|
|
120
|
+
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
|
|
121
|
+
};
|
|
122
|
+
const subnets = props.vpc.selectSubnets(subnetSelection);
|
|
123
|
+
this.subnetGroup = new dms.CfnReplicationSubnetGroup(this, 'SubnetGroup', {
|
|
124
|
+
replicationSubnetGroupDescription: `DMS serverless subnet group for ${id}`,
|
|
125
|
+
subnetIds: subnets.subnetIds,
|
|
126
|
+
});
|
|
127
|
+
// -----------------------------------------------------------------------
|
|
128
|
+
// Source endpoint
|
|
129
|
+
// -----------------------------------------------------------------------
|
|
130
|
+
if (props.existingSourceEndpoint) {
|
|
131
|
+
this.source = props.existingSourceEndpoint;
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
const sourceOpts = props.sourceEndpoint;
|
|
135
|
+
this.source = new endpoint_1.DmsEndpoint(this, 'SourceEndpoint', {
|
|
136
|
+
endpointType: enums_1.EndpointType.SOURCE,
|
|
137
|
+
engine: sourceOpts.engine,
|
|
138
|
+
endpointIdentifier: sourceOpts.endpointIdentifier,
|
|
139
|
+
serverName: sourceOpts.serverName,
|
|
140
|
+
port: sourceOpts.port,
|
|
141
|
+
username: sourceOpts.username,
|
|
142
|
+
password: sourceOpts.password,
|
|
143
|
+
databaseName: sourceOpts.databaseName,
|
|
144
|
+
extraConnectionAttributes: sourceOpts.extraConnectionAttributes,
|
|
145
|
+
certificateArn: sourceOpts.certificateArn,
|
|
146
|
+
sslMode: sourceOpts.sslMode,
|
|
147
|
+
mySqlSettings: sourceOpts.mySqlSettings,
|
|
148
|
+
postgreSqlSettings: sourceOpts.postgreSqlSettings,
|
|
149
|
+
oracleSettings: sourceOpts.oracleSettings,
|
|
150
|
+
sqlServerSettings: sourceOpts.sqlServerSettings,
|
|
151
|
+
sapAseSettings: sourceOpts.sapAseSettings,
|
|
152
|
+
db2Settings: sourceOpts.db2Settings,
|
|
153
|
+
mongoDbSettings: sourceOpts.mongoDbSettings,
|
|
154
|
+
s3Settings: sourceOpts.s3Settings,
|
|
155
|
+
removalPolicy,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
// -----------------------------------------------------------------------
|
|
159
|
+
// Target endpoint
|
|
160
|
+
// -----------------------------------------------------------------------
|
|
161
|
+
if (props.existingTargetEndpoint) {
|
|
162
|
+
this.target = props.existingTargetEndpoint;
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
const targetOpts = props.targetEndpoint;
|
|
166
|
+
this.target = new endpoint_1.DmsEndpoint(this, 'TargetEndpoint', {
|
|
167
|
+
endpointType: enums_1.EndpointType.TARGET,
|
|
168
|
+
engine: targetOpts.engine,
|
|
169
|
+
endpointIdentifier: targetOpts.endpointIdentifier,
|
|
170
|
+
serverName: targetOpts.serverName,
|
|
171
|
+
port: targetOpts.port,
|
|
172
|
+
username: targetOpts.username,
|
|
173
|
+
password: targetOpts.password,
|
|
174
|
+
databaseName: targetOpts.databaseName,
|
|
175
|
+
extraConnectionAttributes: targetOpts.extraConnectionAttributes,
|
|
176
|
+
certificateArn: targetOpts.certificateArn,
|
|
177
|
+
sslMode: targetOpts.sslMode,
|
|
178
|
+
mySqlSettings: targetOpts.mySqlSettings,
|
|
179
|
+
postgreSqlSettings: targetOpts.postgreSqlSettings,
|
|
180
|
+
oracleSettings: targetOpts.oracleSettings,
|
|
181
|
+
sqlServerSettings: targetOpts.sqlServerSettings,
|
|
182
|
+
sapAseSettings: targetOpts.sapAseSettings,
|
|
183
|
+
db2Settings: targetOpts.db2Settings,
|
|
184
|
+
mongoDbSettings: targetOpts.mongoDbSettings,
|
|
185
|
+
s3Settings: targetOpts.s3Settings,
|
|
186
|
+
dynamoDbSettings: targetOpts.dynamoDbSettings,
|
|
187
|
+
redshiftSettings: targetOpts.redshiftSettings,
|
|
188
|
+
kinesisSettings: targetOpts.kinesisSettings,
|
|
189
|
+
kafkaSettings: targetOpts.kafkaSettings,
|
|
190
|
+
openSearchSettings: targetOpts.openSearchSettings,
|
|
191
|
+
neptuneSettings: targetOpts.neptuneSettings,
|
|
192
|
+
redisSettings: targetOpts.redisSettings,
|
|
193
|
+
removalPolicy,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
// -----------------------------------------------------------------------
|
|
197
|
+
// Table mappings — default to "include everything"
|
|
198
|
+
// -----------------------------------------------------------------------
|
|
199
|
+
const tableMappingsJson = props.tableMappings ?? new table_mappings_1.TableMappings().includeSchema('%').toJson();
|
|
200
|
+
// CfnReplicationConfig.tableMappings expects a JSON object, not a string.
|
|
201
|
+
const tableMappingsObj = JSON.parse(tableMappingsJson);
|
|
202
|
+
const replicationSettingsObj = props.taskSettings !== undefined ? JSON.parse(props.taskSettings) : undefined;
|
|
203
|
+
// -----------------------------------------------------------------------
|
|
204
|
+
// Replication config identifier
|
|
205
|
+
// -----------------------------------------------------------------------
|
|
206
|
+
const configIdentifier = props.replicationConfigIdentifier ??
|
|
207
|
+
cdk.Names.uniqueResourceName(this, { maxLength: 63 }).toLowerCase();
|
|
208
|
+
// -----------------------------------------------------------------------
|
|
209
|
+
// CfnReplicationConfig
|
|
210
|
+
// -----------------------------------------------------------------------
|
|
211
|
+
this.cfnReplicationConfig = new dms.CfnReplicationConfig(this, 'Resource', {
|
|
212
|
+
replicationConfigIdentifier: configIdentifier,
|
|
213
|
+
replicationType: props.migrationType,
|
|
214
|
+
sourceEndpointArn: this.source.endpointArn,
|
|
215
|
+
targetEndpointArn: this.target.endpointArn,
|
|
216
|
+
tableMappings: tableMappingsObj,
|
|
217
|
+
replicationSettings: replicationSettingsObj,
|
|
218
|
+
computeConfig: {
|
|
219
|
+
maxCapacityUnits: props.maxCapacityUnits,
|
|
220
|
+
minCapacityUnits: props.minCapacityUnits,
|
|
221
|
+
multiAz: props.multiAz ?? false,
|
|
222
|
+
kmsKeyId: this.encryptionKey.keyArn,
|
|
223
|
+
replicationSubnetGroupId: this.subnetGroup.ref,
|
|
224
|
+
vpcSecurityGroupIds: securityGroupIds,
|
|
225
|
+
preferredMaintenanceWindow: props.preferredMaintenanceWindow,
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
this.cfnReplicationConfig.applyRemovalPolicy(removalPolicy);
|
|
229
|
+
// The replication config cannot be placed in a VPC until dms-vpc-role exists.
|
|
230
|
+
if (this.dmsVpcRole) {
|
|
231
|
+
this.cfnReplicationConfig.addDependency(this.dmsVpcRole.node.defaultChild);
|
|
232
|
+
}
|
|
233
|
+
this.replicationConfigArn = this.cfnReplicationConfig.ref;
|
|
234
|
+
}
|
|
235
|
+
// ---------------------------------------------------------------------------
|
|
236
|
+
// Private helpers
|
|
237
|
+
// ---------------------------------------------------------------------------
|
|
238
|
+
validateProps(props) {
|
|
239
|
+
if (!VALID_CAPACITY_UNITS.has(props.maxCapacityUnits)) {
|
|
240
|
+
throw new Error(`maxCapacityUnits must be one of ${[...VALID_CAPACITY_UNITS].join(', ')}. Got: ${props.maxCapacityUnits}`);
|
|
241
|
+
}
|
|
242
|
+
if (props.minCapacityUnits !== undefined &&
|
|
243
|
+
!VALID_CAPACITY_UNITS.has(props.minCapacityUnits)) {
|
|
244
|
+
throw new Error(`minCapacityUnits must be one of ${[...VALID_CAPACITY_UNITS].join(', ')}. Got: ${props.minCapacityUnits}`);
|
|
245
|
+
}
|
|
246
|
+
if (props.minCapacityUnits !== undefined &&
|
|
247
|
+
props.minCapacityUnits > props.maxCapacityUnits) {
|
|
248
|
+
throw new Error(`minCapacityUnits (${props.minCapacityUnits}) must be <= maxCapacityUnits (${props.maxCapacityUnits}).`);
|
|
249
|
+
}
|
|
250
|
+
const hasSource = !!props.sourceEndpoint;
|
|
251
|
+
const hasExistingSource = !!props.existingSourceEndpoint;
|
|
252
|
+
if (hasSource && hasExistingSource) {
|
|
253
|
+
throw new Error('Provide either `sourceEndpoint` or `existingSourceEndpoint`, not both.');
|
|
254
|
+
}
|
|
255
|
+
if (!hasSource && !hasExistingSource) {
|
|
256
|
+
throw new Error('One of `sourceEndpoint` or `existingSourceEndpoint` is required.');
|
|
257
|
+
}
|
|
258
|
+
const hasTarget = !!props.targetEndpoint;
|
|
259
|
+
const hasExistingTarget = !!props.existingTargetEndpoint;
|
|
260
|
+
if (hasTarget && hasExistingTarget) {
|
|
261
|
+
throw new Error('Provide either `targetEndpoint` or `existingTargetEndpoint`, not both.');
|
|
262
|
+
}
|
|
263
|
+
if (!hasTarget && !hasExistingTarget) {
|
|
264
|
+
throw new Error('One of `targetEndpoint` or `existingTargetEndpoint` is required.');
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
exports.DmsServerlessPipeline = DmsServerlessPipeline;
|
|
269
|
+
_a = JSII_RTTI_SYMBOL_1;
|
|
270
|
+
DmsServerlessPipeline[_a] = { fqn: "cdk-dms-replication.DmsServerlessPipeline", version: "0.0.0" };
|
|
271
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVybGVzcy1waXBlbGluZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9zZXJ2ZXJsZXNzLXBpcGVsaW5lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsbUNBQW1DO0FBQ25DLDJDQUEyQztBQUMzQywyQ0FBMkM7QUFFM0MsMkNBQTJDO0FBQzNDLDZDQUE2QztBQUM3QywyQ0FBdUM7QUFDdkMsMkNBQXdFO0FBQ3hFLHlDQUF1RDtBQUN2RCxtQ0FBc0Q7QUFFdEQscURBQWlEO0FBRWpELDhFQUE4RTtBQUM5RSxtRUFBbUU7QUFDbkUsOEVBQThFO0FBQzlFLE1BQU0sb0JBQW9CLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztBQThLbkYsOEVBQThFO0FBQzlFLFlBQVk7QUFDWiw4RUFBOEU7QUFFOUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXVDRztBQUNILE1BQWEscUJBQXNCLFNBQVEsc0JBQVM7SUFxQ2xELFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBaUM7UUFDekUsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUVqQixJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBRTFCLE1BQU0sYUFBYSxHQUFHLEtBQUssQ0FBQyxhQUFhLElBQUksR0FBRyxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUM7UUFDdkUsTUFBTSxXQUFXLEdBQUcsS0FBSyxDQUFDLHFCQUFxQixJQUFJLElBQUksQ0FBQztRQUV4RCwwRUFBMEU7UUFDMUUsbUVBQW1FO1FBQ25FLDBFQUEwRTtRQUMxRSxJQUFJLFdBQVcsRUFBRSxDQUFDO1lBQ2hCLElBQUks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QUM7UUFDNUYsQ0FBQztRQUNELElBQUksQ0FBQyxTQUFTLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1lBQ3JDLE1BQU0sSUFBSSxLQUFLLENBQUMsa0VBQWtFLENBQUMsQ0FBQztRQUN0RixDQUFDO0lBQ0gsQ0FBQzs7QUFuUkgsc0RBb1JDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgY2RrIGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCAqIGFzIGRtcyBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZG1zJztcbmltcG9ydCAqIGFzIGVjMiBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZWMyJztcbmltcG9ydCAqIGFzIGlhbSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtaWFtJztcbmltcG9ydCAqIGFzIGttcyBmcm9tICdhd3MtY2RrLWxpYi9hd3Mta21zJztcbmltcG9ydCAqIGFzIGxvZ3MgZnJvbSAnYXdzLWNkay1saWIvYXdzLWxvZ3MnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBlbnN1cmVEbXNDbG91ZFdhdGNoUm9sZSwgZW5zdXJlRG1zVnBjUm9sZSB9IGZyb20gJy4vZG1zLXJvbGVzJztcbmltcG9ydCB7IERtc0VuZHBvaW50LCBJRG1zRW5kcG9pbnQgfSBmcm9tICcuL2VuZHBvaW50JztcbmltcG9ydCB7IEVuZHBvaW50VHlwZSwgTWlncmF0aW9uVHlwZSB9IGZyb20gJy4vZW51bXMnO1xuaW1wb3J0IHsgU291cmNlRW5kcG9pbnRPcHRpb25zLCBUYXJnZXRFbmRwb2ludE9wdGlvbnMgfSBmcm9tICcuL21pZ3JhdGlvbi1waXBlbGluZSc7XG5pbXBvcnQgeyBUYWJsZU1hcHBpbmdzIH0gZnJvbSAnLi90YWJsZS1tYXBwaW5ncyc7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gVmFsaWQgY2FwYWNpdHkgdW5pdCB2YWx1ZXMg4oCUIGRvY3VtZW50ZWQgaW4gdGhlIERNUyBBUEkgcmVmZXJlbmNlXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbmNvbnN0IFZBTElEX0NBUEFDSVRZX1VOSVRTID0gbmV3IFNldChbMSwgMiwgNCwgOCwgMTYsIDMyLCA2NCwgMTI4LCAxOTIsIDI1NiwgMzg0XSk7XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gUHJvcHNcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKiogUHJvcHMgZm9yIHtAbGluayBEbXNTZXJ2ZXJsZXNzUGlwZWxpbmV9LiAqL1xuZXhwb3J0IGludGVyZmFjZSBEbXNTZXJ2ZXJsZXNzUGlwZWxpbmVQcm9wcyB7XG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gTmV0d29ya2luZ1xuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgLyoqXG4gICAqIFZQQyBpbiB3aGljaCB0byBwbGFjZSB0aGUgc2VydmVybGVzcyByZXBsaWNhdGlvbiBjb25maWcuXG4gICAqIFRoZSBjb25maWcgaXMgcGxhY2VkIGluIHByaXZhdGUgc3VibmV0cy5cbiAgICovXG4gIHJlYWRvbmx5IHZwYzogZWMyLklWcGM7XG5cbiAgLyoqXG4gICAqIFN1Ym5ldCBzZWxlY3Rpb24gZm9yIHRoZSByZXBsaWNhdGlvbiBzdWJuZXQgZ3JvdXAuXG4gICAqIEBkZWZhdWx0IHByaXZhdGUgc3VibmV0cyB3aXRoIGVncmVzc1xuICAgKi9cbiAgcmVhZG9ubHkgdnBjU3VibmV0cz86IGVjMi5TdWJuZXRTZWxlY3Rpb247XG5cbiAgLyoqXG4gICAqIFNlY3VyaXR5IGdyb3VwcyB0byBhdHRhY2ggdG8gdGhlIHNlcnZlcmxlc3MgcmVwbGljYXRpb24gY29uZmlnLlxuICAgKiBBIG5ldyBzZWN1cml0eSBncm91cCBpcyBjcmVhdGVkIGlmIG5vbmUgYXJlIHByb3ZpZGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgc2VjdXJpdHlHcm91cHM/OiBlYzIuSVNlY3VyaXR5R3JvdXBbXTtcblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIENvbXB1dGUgY29uZmlnXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICAvKipcbiAgICogTWF4aW11bSBudW1iZXIgb2YgRE1TIENhcGFjaXR5IFVuaXRzIChEQ1VzKSB0aGUgc2VydmVybGVzcyByZXBsaWNhdGlvbiBtYXlcbiAgICogc2NhbGUgdXAgdG8uXG4gICAqXG4gICAqIFZhbGlkIHZhbHVlczogMSwgMiwgNCwgOCwgMTYsIDMyLCA2NCwgMTI4LCAxOTIsIDI1NiwgMzg0LlxuICAgKi9cbiAgcmVhZG9ubHkgbWF4Q2FwYWNpdHlVbml0czogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBNaW5pbXVtIG51bWJlciBvZiBEQ1VzIERNUyB3aWxsIHByb3Zpc2lvbiBhdCBzdGFydC11cC5cbiAgICogQGRlZmF1bHQgRE1TIGF1dG8tZGV0ZXJtaW5lcyBiYXNlZCBvbiB3b3JrbG9hZFxuICAgKi9cbiAgcmVhZG9ubHkgbWluQ2FwYWNpdHlVbml0cz86IG51bWJlcjtcblxuICAvKipcbiAgICogV2hldGhlciB0aGUgc2VydmVybGVzcyByZXBsaWNhdGlvbiBpcyBNdWx0aS1BWi5cbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IG11bHRpQXo/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBQcmVmZXJyZWQgbWFpbnRlbmFuY2Ugd2luZG93LCBlLmcuIFwic3VuOjA0OjAwLXN1bjowNDozMFwiLlxuICAgKi9cbiAgcmVhZG9ubHkgcHJlZmVycmVkTWFpbnRlbmFuY2VXaW5kb3c/OiBzdHJpbmc7XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyBFbmNyeXB0aW9uXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICAvKipcbiAgICogS01TIGtleSB1c2VkIHRvIGVuY3J5cHQgcmVwbGljYXRpb24gc3RvcmFnZSBhdCByZXN0LlxuICAgKiBBIG5ldyBrZXkgaXMgY3JlYXRlZCBpZiBub3QgcHJvdmlkZWQuXG4gICAqL1xuICByZWFkb25seSBrbXNLZXk/OiBrbXMuSUtleTtcblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIEVuZHBvaW50c1xuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgLyoqXG4gICAqIFNvdXJjZSBlbmRwb2ludCBjb25maWd1cmF0aW9uLlxuICAgKiBQcm92aWRlIHRoaXMgT1IgYGV4aXN0aW5nU291cmNlRW5kcG9pbnRgIOKAlCBub3QgYm90aC5cbiAgICovXG4gIHJlYWRvbmx5IHNvdXJjZUVuZHBvaW50PzogU291cmNlRW5kcG9pbnRPcHRpb25zO1xuXG4gIC8qKlxuICAgKiBBbiBleGlzdGluZyB7QGxpbmsgSURtc0VuZHBvaW50fSB0byB1c2UgYXMgdGhlIHNvdXJjZS5cbiAgICogUHJvdmlkZSB0aGlzIE9SIGBzb3VyY2VFbmRwb2ludGAg4oCUIG5vdCBib3RoLlxuICAgKi9cbiAgcmVhZG9ubHkgZXhpc3RpbmdTb3VyY2VFbmRwb2ludD86IElEbXNFbmRwb2ludDtcblxuICAvKipcbiAgICogVGFyZ2V0IGVuZHBvaW50IGNvbmZpZ3VyYXRpb24uXG4gICAqIFByb3ZpZGUgdGhpcyBPUiBgZXhpc3RpbmdUYXJnZXRFbmRwb2ludGAg4oCUIG5vdCBib3RoLlxuICAgKi9cbiAgcmVhZG9ubHkgdGFyZ2V0RW5kcG9pbnQ/OiBUYXJnZXRFbmRwb2ludE9wdGlvbnM7XG5cbiAgLyoqXG4gICAqIEFuIGV4aXN0aW5nIHtAbGluayBJRG1zRW5kcG9pbnR9IHRvIHVzZSBhcyB0aGUgdGFyZ2V0LlxuICAgKiBQcm92aWRlIHRoaXMgT1IgYHRhcmdldEVuZHBvaW50YCDigJQgbm90IGJvdGguXG4gICAqL1xuICByZWFkb25seSBleGlzdGluZ1RhcmdldEVuZHBvaW50PzogSURtc0VuZHBvaW50O1xuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gTWlncmF0aW9uIGNvbmZpZ1xuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgLyoqIFRoZSB0eXBlIG9mIG1pZ3JhdGlvbiB0byBwZXJmb3JtLiAqL1xuICByZWFkb25seSBtaWdyYXRpb25UeXBlOiBNaWdyYXRpb25UeXBlO1xuXG4gIC8qKlxuICAgKiBUYWJsZSBtYXBwaW5ncyBKU09OIHN0cmluZy5cbiAgICogVXNlIHtAbGluayBUYWJsZU1hcHBpbmdzfSB0byBidWlsZCB0aGlzLlxuICAgKiBEZWZhdWx0cyB0byBcImluY2x1ZGUgYWxsIHRhYmxlcyBpbiBhbGwgc2NoZW1hc1wiIGlmIG5vdCBwcm92aWRlZC5cbiAgICovXG4gIHJlYWRvbmx5IHRhYmxlTWFwcGluZ3M/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFJlcGxpY2F0aW9uIHNldHRpbmdzIEpTT04gc3RyaW5nIChlcXVpdmFsZW50IHRvIHRhc2sgc2V0dGluZ3MgZm9yIGNsYXNzaWMgRE1TKS5cbiAgICogVXNlIHtAbGluayBUYXNrU2V0dGluZ3N9IHRvIGJ1aWxkIHRoaXMuXG4gICAqIFNlbnNpYmxlIGRlZmF1bHRzIGFyZSBhcHBsaWVkIGJ5IERNUyBpZiBub3QgcHJvdmlkZWQuXG4gICAqXG4gICAqIEByZW1hcmtzIERNUyBTZXJ2ZXJsZXNzIGRvZXMgbm90IHN1cHBvcnQgc2V0dGluZyBDREMgc3RhcnQvc3RvcCBwb3NpdGlvbnNcbiAgICogdmlhIENsb3VkRm9ybWF0aW9uLiBUbyBzdGFydCByZXBsaWNhdGlvbiBmcm9tIGEgc3BlY2lmaWMgTFNOIG9yIHRpbWVzdGFtcFxuICAgKiBhZnRlciB0aGUgcmVwbGljYXRpb24gY29uZmlnIGhhcyBiZWVuIGNyZWF0ZWQsIGNhbGwgdGhlXG4gICAqIGBTdGFydFJlcGxpY2F0aW9uYCBBUEkgd2l0aCBgU3RhcnRSZXBsaWNhdGlvblRhc2tUeXBlYCBzZXQgdG9cbiAgICogYHN0YXJ0LXJlcGxpY2F0aW9uYCBhbmQgc3VwcGx5IGBDZGNTdGFydFBvc2l0aW9uYCBvciBgQ2RjU3RhcnRUaW1lYC5cbiAgICovXG4gIHJlYWRvbmx5IHRhc2tTZXR0aW5ncz86IHN0cmluZztcblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIE9ic2VydmFiaWxpdHlcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGNyZWF0ZSBhIENsb3VkV2F0Y2ggbG9nIGdyb3VwIGZvciB0aGUgcmVwbGljYXRpb24gY29uZmlnLlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBlbmFibGVDbG91ZFdhdGNoTG9ncz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFJldGVudGlvbiBwZXJpb2QgZm9yIHRoZSBDbG91ZFdhdGNoIGxvZyBncm91cC5cbiAgICogQGRlZmF1bHQgbG9ncy5SZXRlbnRpb25EYXlzLk9ORV9NT05USFxuICAgKi9cbiAgcmVhZG9ubHkgbG9nUmV0ZW50aW9uPzogbG9ncy5SZXRlbnRpb25EYXlzO1xuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gSUFNIC8gc2VydmljZSByb2xlc1xuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdG8gY3JlYXRlIHRoZSB0d28gYWNjb3VudC1sZXZlbCBETVMgc2VydmljZSByb2xlcyAoYGRtcy12cGMtcm9sZWBcbiAgICogYW5kIGBkbXMtY2xvdWR3YXRjaC1sb2dzLXJvbGVgKSByZXF1aXJlZCBieSBETVMuXG4gICAqXG4gICAqIFNldCB0byBgZmFsc2VgIGlmIHRoZSByb2xlcyBhbHJlYWR5IGV4aXN0IOKAlCBmb3IgZXhhbXBsZSwgYmVjYXVzZSBhXG4gICAqIGBEbXNNaWdyYXRpb25QaXBlbGluZWAgb3IgYSBwcmlvciBtYW51YWwgZGVwbG95bWVudCBhbHJlYWR5IGNyZWF0ZWQgdGhlbS5cbiAgICogQXR0ZW1wdGluZyB0byBjcmVhdGUgcm9sZXMgd2l0aCB0aGUgc2FtZSBuYW1lIHR3aWNlIGNhdXNlcyBhIENsb3VkRm9ybWF0aW9uXG4gICAqIGBFbnRpdHlBbHJlYWR5RXhpc3RzYCBlcnJvci5cbiAgICpcbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgY3JlYXRlRG1zU2VydmljZVJvbGVzPzogYm9vbGVhbjtcblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIE5hbWluZyAvIGxpZmVjeWNsZVxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgLyoqXG4gICAqIExvZ2ljYWwgaWRlbnRpZmllciBmb3IgdGhlIHJlcGxpY2F0aW9uIGNvbmZpZyByZXNvdXJjZS5cbiAgICogQGRlZmF1bHQgdW5pcXVlIG5hbWUgZGVyaXZlZCBmcm9tIHRoZSBjb25zdHJ1Y3QgaWRcbiAgICovXG4gIHJlYWRvbmx5IHJlcGxpY2F0aW9uQ29uZmlnSWRlbnRpZmllcj86IHN0cmluZztcblxuICAvKipcbiAgICogUmVtb3ZhbCBwb2xpY3kgYXBwbGllZCB0byBhbGwgcmVzb3VyY2VzIGluIHRoZSBwaXBlbGluZS5cbiAgICogQGRlZmF1bHQgY2RrLlJlbW92YWxQb2xpY3kuREVTVFJPWVxuICAgKi9cbiAgcmVhZG9ubHkgcmVtb3ZhbFBvbGljeT86IGNkay5SZW1vdmFsUG9saWN5O1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIENvbnN0cnVjdFxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogQW4gTDMgQ0RLIHBhdHRlcm4gY29uc3RydWN0IHRoYXQgcHJvdmlzaW9ucyBhIERNUyBTZXJ2ZXJsZXNzIHJlcGxpY2F0aW9uXG4gKiBwaXBlbGluZTpcbiAqXG4gKiAtICoqUmVwbGljYXRpb24gY29uZmlnKiog4oCUIGJhY2tlZCBieSBgQ2ZuUmVwbGljYXRpb25Db25maWdgOyBETVMgYXV0by1zY2FsZXNcbiAqICAgY2FwYWNpdHkgYmV0d2VlbiBgbWluQ2FwYWNpdHlVbml0c2AgYW5kIGBtYXhDYXBhY2l0eVVuaXRzYC5cbiAqIC0gKipTb3VyY2UgZW5kcG9pbnQqKiDigJQgc3VwcG9ydHMgZXZlcnkgZW5naW5lIERNUyBzdXBwb3J0cy5cbiAqIC0gKipUYXJnZXQgZW5kcG9pbnQqKiDigJQgc3VwcG9ydHMgZXZlcnkgZW5naW5lIERNUyBzdXBwb3J0cy5cbiAqIC0gKipTdWJuZXQgZ3JvdXAqKiDigJQgcHJpdmF0ZSBzdWJuZXQgcGxhY2VtZW50LlxuICogLSAqKktNUyBrZXkqKiDigJQgc3RvcmFnZSBlbmNyeXB0aW9uIGF0IHJlc3QgKGNyZWF0ZWQgaWYgbm90IHByb3ZpZGVkKS5cbiAqIC0gKipTZWN1cml0eSBncm91cCoqIOKAlCBkZWRpY2F0ZWQgZ3JvdXAgKGNyZWF0ZWQgaWYgbm90IHByb3ZpZGVkKS5cbiAqIC0gKipJQU0gcm9sZXMqKiDigJQgYGRtcy12cGMtcm9sZWAgYW5kIGBkbXMtY2xvdWR3YXRjaC1sb2dzLXJvbGVgLlxuICogLSAqKkNsb3VkV2F0Y2ggbG9nIGdyb3VwKiog4oCUIChvcHRpb25hbCkgcmV0YWlucyByZXBsaWNhdGlvbiBsb2dzLlxuICpcbiAqID4gKipDREMgc3RhcnQvc3RvcCBwb3NpdGlvbiBsaW1pdGF0aW9uKio6IGBDZm5SZXBsaWNhdGlvbkNvbmZpZ2AgZG9lcyBub3RcbiAqID4gZXhwb3NlIGBjZGNTdGFydFRpbWVgIC8gYGNkY1N0YXJ0UG9zaXRpb25gIC8gYGNkY1N0b3BQb3NpdGlvbmAuIFRvIHN0YXJ0XG4gKiA+IGZyb20gYSBzcGVjaWZpYyBwb3NpdGlvbiwgY2FsbCB0aGUgYFN0YXJ0UmVwbGljYXRpb25gIEFQSSBkaXJlY3RseSBhZnRlclxuICogPiB0aGUgY29uZmlnIGlzIGNyZWF0ZWQgKGUuZy4gZnJvbSBhIExhbWJkYSBjdXN0b20gcmVzb3VyY2Ugb3IgQ0xJKS5cbiAqXG4gKiBAZXhhbXBsZVxuICogY29uc3QgcGlwZWxpbmUgPSBuZXcgRG1zU2VydmVybGVzc1BpcGVsaW5lKHRoaXMsICdTZXJ2ZXJsZXNzUGlwZWxpbmUnLCB7XG4gKiAgIHZwYyxcbiAqICAgbWF4Q2FwYWNpdHlVbml0czogOCxcbiAqICAgbWlncmF0aW9uVHlwZTogTWlncmF0aW9uVHlwZS5GVUxMX0xPQURfQU5EX0NEQyxcbiAqICAgc291cmNlRW5kcG9pbnQ6IHtcbiAqICAgICBlbmdpbmU6IEVuZHBvaW50RW5naW5lLk1ZU1FMLFxuICogICAgIHNlcnZlck5hbWU6ICdteXNxbC5leGFtcGxlLmNvbScsXG4gKiAgICAgcG9ydDogMzMwNixcbiAqICAgICB1c2VybmFtZTogJ2Rtc191c2VyJyxcbiAqICAgICBwYXNzd29yZDogY2RrLlNlY3JldFZhbHVlLnNlY3JldHNNYW5hZ2VyKCdteXNxbC1kbXMtc2VjcmV0JyksXG4gKiAgIH0sXG4gKiAgIHRhcmdldEVuZHBvaW50OiB7XG4gKiAgICAgZW5naW5lOiBFbmRwb2ludEVuZ2luZS5BVVJPUkFfUE9TVEdSRVNRTCxcbiAqICAgICBzZXJ2ZXJOYW1lOiBjbHVzdGVyLmNsdXN0ZXJFbmRwb2ludC5ob3N0bmFtZSxcbiAqICAgICBwb3J0OiA1NDMyLFxuICogICAgIHVzZXJuYW1lOiAnZG1zX3VzZXInLFxuICogICAgIHBhc3N3b3JkOiBjZGsuU2VjcmV0VmFsdWUuc2VjcmV0c01hbmFnZXIoJ2F1cm9yYS1kbXMtc2VjcmV0JyksXG4gKiAgIH0sXG4gKiB9KTtcbiAqL1xuZXhwb3J0IGNsYXNzIERtc1NlcnZlcmxlc3NQaXBlbGluZSBleHRlbmRzIENvbnN0cnVjdCB7XG4gIC8qKiBUaGUgdW5kZXJseWluZyBgQ2ZuUmVwbGljYXRpb25Db25maWdgIHJlc291cmNlLiAqL1xuICByZWFkb25seSBjZm5SZXBsaWNhdGlvbkNvbmZpZzogZG1zLkNmblJlcGxpY2F0aW9uQ29uZmlnO1xuXG4gIC8qKiBUaGUgQVJOIG9mIHRoZSByZXBsaWNhdGlvbiBjb25maWcuICovXG4gIHJlYWRvbmx5IHJlcGxpY2F0aW9uQ29uZmlnQXJuOiBzdHJpbmc7XG5cbiAgLyoqIFRoZSBzb3VyY2UgZW5kcG9pbnQgdXNlZCBieSB0aGlzIHBpcGVsaW5lLiAqL1xuICByZWFkb25seSBzb3VyY2U6IElEbXNFbmRwb2ludDtcblxuICAvKiogVGhlIHRhcmdldCBlbmRwb2ludCB1c2VkIGJ5IHRoaXMgcGlwZWxpbmUuICovXG4gIHJlYWRvbmx5IHRhcmdldDogSURtc0VuZHBvaW50O1xuXG4gIC8qKiBUaGUgcmVwbGljYXRpb24gc3VibmV0IGdyb3VwIGNyZWF0ZWQgZm9yIHRoaXMgcGlwZWxpbmUuICovXG4gIHJlYWRvbmx5IHN1Ym5ldEdyb3VwOiBkbXMuQ2ZuUmVwbGljYXRpb25TdWJuZXRHcm91cDtcblxuICAvKiogVGhlIEtNUyBrZXkgdXNlZCBmb3Igc3RvcmFnZSBlbmNyeXB0aW9uLiAqL1xuICByZWFkb25seSBlbmNyeXB0aW9uS2V5OiBrbXMuSUtleTtcblxuICAvKiogVGhlIHNlY3VyaXR5IGdyb3VwIGF0dGFjaGVkIHRvIHRoaXMgcGlwZWxpbmUuICovXG4gIHJlYWRvbmx5IHNlY3VyaXR5R3JvdXA6IGVjMi5JU2VjdXJpdHlHcm91cDtcblxuICAvKiogQ2xvdWRXYXRjaCBsb2cgZ3JvdXAgZm9yIHRoZSByZXBsaWNhdGlvbiBjb25maWcgKGlmIGVuYWJsZUNsb3VkV2F0Y2hMb2dzIGlzIHRydWUpLiAqL1xuICByZWFkb25seSBsb2dHcm91cD86IGxvZ3MuTG9nR3JvdXA7XG5cbiAgLyoqXG4gICAqIElBTSByb2xlIHRoYXQgYWxsb3dzIERNUyB0byB3cml0ZSB0byBDbG91ZFdhdGNoIExvZ3MuXG4gICAqIGB1bmRlZmluZWRgIHdoZW4gYGNyZWF0ZURtc1NlcnZpY2VSb2xlc2AgaXMgYGZhbHNlYC5cbiAgICovXG4gIHJlYWRvbmx5IGRtc0Nsb3VkV2F0Y2hSb2xlPzogaWFtLlJvbGU7XG5cbiAgLyoqXG4gICAqIElBTSByb2xlIHRoYXQgYWxsb3dzIERNUyB0byBtYW5hZ2UgVlBDIHJlc291cmNlcyAoZG1zLXZwYy1yb2xlKS5cbiAgICogYHVuZGVmaW5lZGAgd2hlbiBgY3JlYXRlRG1zU2VydmljZVJvbGVzYCBpcyBgZmFsc2VgLlxuICAgKi9cbiAgcmVhZG9ubHkgZG1zVnBjUm9sZT86IGlhbS5Sb2xlO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBEbXNTZXJ2ZXJsZXNzUGlwZWxpbmVQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICB0aGlzLnZhbGlkYXRlUHJvcHMocHJvcHMpO1xuXG4gICAgY29uc3QgcmVtb3ZhbFBvbGljeSA9IHByb3BzLnJlbW92YWxQb2xpY3kgPz8gY2RrLlJlbW92YWxQb2xpY3kuREVTVFJPWTtcbiAgICBjb25zdCBjcmVhdGVSb2xlcyA9IHByb3BzLmNyZWF0ZURtc1NlcnZpY2VSb2xlcyA/PyB0cnVlO1xuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBkbXMtdnBjLXJvbGUg4oCUIHJlcXVpcmVkIGJ5IERNUyB0byBwbGFjZSB0aGUgY29uZmlnIGluc2lkZSBhIFZQQy5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIGlmIChjcmVhdGVSb2xlcykge1xuICAgICAgdGhpcy5kbXNWcGNSb2xlID0gZW5zdXJlRG1zVnBjUm9sZShjZGsuU3RhY2sub2YodGhpcykpO1xuICAgIH1cblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gQ2xvdWRXYXRjaCBsb2cgZ3JvdXAgJiBJQU0gcm9sZVxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgY29uc3QgZW5hYmxlTG9ncyA9IHByb3BzLmVuYWJsZUNsb3VkV2F0Y2hMb2dzID8/IHRydWU7XG5cbiAgICBpZiAoZW5hYmxlTG9ncykge1xuICAgICAgdGhpcy5sb2dHcm91cCA9IG5ldyBsb2dzLkxvZ0dyb3VwKHRoaXMsICdMb2dHcm91cCcsIHtcbiAgICAgICAgbG9nR3JvdXBOYW1lOiBgL2F3cy9kbXMvc2VydmVybGVzcy8ke2lkfWAsXG4gICAgICAgIHJldGVudGlvbjogcHJvcHMubG9nUmV0ZW50aW9uID8/IGxvZ3MuUmV0ZW50aW9uRGF5cy5PTkVfTU9OVEgsXG4gICAgICAgIHJlbW92YWxQb2xpY3ksXG4gICAgICB9KTtcblxuICAgICAgaWYgKGNyZWF0ZVJvbGVzKSB7XG4gICAgICAgIHRoaXMuZG1zQ2xvdWRXYXRjaFJvbGUgPSBlbnN1cmVEbXNDbG91ZFdhdGNoUm9sZShjZGsuU3RhY2sub2YodGhpcykpO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gS01TIGtleVxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgdGhpcy5lbmNyeXB0aW9uS2V5ID1cbiAgICAgIHByb3BzLmttc0tleSA/P1xuICAgICAgbmV3IGttcy5LZXkodGhpcywgJ0VuY3J5cHRpb25LZXknLCB7XG4gICAgICAgIGRlc2NyaXB0aW9uOiBgRE1TIHNlcnZlcmxlc3MgcmVwbGljYXRpb24gZW5jcnlwdGlvbiBrZXkgZm9yICR7aWR9YCxcbiAgICAgICAgZW5hYmxlS2V5Um90YXRpb246IHRydWUsXG4gICAgICAgIHJlbW92YWxQb2xpY3ksXG4gICAgICB9KTtcblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gU2VjdXJpdHkgZ3JvdXBcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIGNvbnN0IHByb3ZpZGVkU2dzID0gcHJvcHMuc2VjdXJpdHlHcm91cHMgPz8gW107XG4gICAgaWYgKHByb3ZpZGVkU2dzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhpcy5zZWN1cml0eUdyb3VwID0gbmV3IGVjMi5TZWN1cml0eUdyb3VwKHRoaXMsICdTZWN1cml0eUdyb3VwJywge1xuICAgICAgICB2cGM6IHByb3BzLnZwYyxcbiAgICAgICAgZGVzY3JpcHRpb246IGBETVMgc2VydmVybGVzcyByZXBsaWNhdGlvbiBzZWN1cml0eSBncm91cCBmb3IgJHtpZH1gLFxuICAgICAgICBhbGxvd0FsbE91dGJvdW5kOiB0cnVlLFxuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuc2VjdXJpdHlHcm91cCA9IHByb3ZpZGVkU2dzWzBdO1xuICAgIH1cblxuICAgIGNvbnN0IHNlY3VyaXR5R3JvdXBJZHMgPVxuICAgICAgcHJvdmlkZWRTZ3MubGVuZ3RoID4gMFxuICAgICAgICA/IHByb3ZpZGVkU2dzLm1hcCgoc2cpID0+IHNnLnNlY3VyaXR5R3JvdXBJZClcbiAgICAgICAgOiBbdGhpcy5zZWN1cml0eUdyb3VwLnNlY3VyaXR5R3JvdXBJZF07XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIFN1Ym5ldCBncm91cFxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgY29uc3Qgc3VibmV0U2VsZWN0aW9uID0gcHJvcHMudnBjU3VibmV0cyA/PyB7XG4gICAgICBzdWJuZXRUeXBlOiBlYzIuU3VibmV0VHlwZS5QUklWQVRFX1dJVEhfRUdSRVNTLFxuICAgIH07XG4gICAgY29uc3Qgc3VibmV0cyA9IHByb3BzLnZwYy5zZWxlY3RTdWJuZXRzKHN1Ym5ldFNlbGVjdGlvbik7XG5cbiAgICB0aGlzLnN1Ym5ldEdyb3VwID0gbmV3IGRtcy5DZm5SZXBsaWNhdGlvblN1Ym5ldEdyb3VwKHRoaXMsICdTdWJuZXRHcm91cCcsIHtcbiAgICAgIHJlcGxpY2F0aW9uU3VibmV0R3JvdXBEZXNjcmlwdGlvbjogYERNUyBzZXJ2ZXJsZXNzIHN1Ym5ldCBncm91cCBmb3IgJHtpZH1gLFxuICAgICAgc3VibmV0SWRzOiBzdWJuZXRzLnN1Ym5ldElkcyxcbiAgICB9KTtcblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gU291cmNlIGVuZHBvaW50XG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBpZiAocHJvcHMuZXhpc3RpbmdTb3VyY2VFbmRwb2ludCkge1xuICAgICAgdGhpcy5zb3VyY2UgPSBwcm9wcy5leGlzdGluZ1NvdXJjZUVuZHBvaW50O1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBzb3VyY2VPcHRzID0gcHJvcHMuc291cmNlRW5kcG9pbnQhO1xuICAgICAgdGhpcy5zb3VyY2UgPSBuZXcgRG1zRW5kcG9pbnQodGhpcywgJ1NvdXJjZUVuZHBvaW50Jywge1xuICAgICAgICBlbmRwb2ludFR5cGU6IEVuZHBvaW50VHlwZS5TT1VSQ0UsXG4gICAgICAgIGVuZ2luZTogc291cmNlT3B0cy5lbmdpbmUsXG4gICAgICAgIGVuZHBvaW50SWRlbnRpZmllcjogc291cmNlT3B0cy5lbmRwb2ludElkZW50aWZpZXIsXG4gICAgICAgIHNlcnZlck5hbWU6IHNvdXJjZU9wdHMuc2VydmVyTmFtZSxcbiAgICAgICAgcG9ydDogc291cmNlT3B0cy5wb3J0LFxuICAgICAgICB1c2VybmFtZTogc291cmNlT3B0cy51c2VybmFtZSxcbiAgICAgICAgcGFzc3dvcmQ6IHNvdXJjZU9wdHMucGFzc3dvcmQsXG4gICAgICAgIGRhdGFiYXNlTmFtZTogc291cmNlT3B0cy5kYXRhYmFzZU5hbWUsXG4gICAgICAgIGV4dHJhQ29ubmVjdGlvbkF0dHJpYnV0ZXM6IHNvdXJjZU9wdHMuZXh0cmFDb25uZWN0aW9uQXR0cmlidXRlcyxcbiAgICAgICAgY2VydGlmaWNhdGVBcm46IHNvdXJjZU9wdHMuY2VydGlmaWNhdGVBcm4sXG4gICAgICAgIHNzbE1vZGU6IHNvdXJjZU9wdHMuc3NsTW9kZSxcbiAgICAgICAgbXlTcWxTZXR0aW5nczogc291cmNlT3B0cy5teVNxbFNldHRpbmdzLFxuICAgICAgICBwb3N0Z3JlU3FsU2V0dGluZ3M6IHNvdXJjZU9wdHMucG9zdGdyZVNxbFNldHRpbmdzLFxuICAgICAgICBvcmFjbGVTZXR0aW5nczogc291cmNlT3B0cy5vcmFjbGVTZXR0aW5ncyxcbiAgICAgICAgc3FsU2VydmVyU2V0dGluZ3M6IHNvdXJjZU9wdHMuc3FsU2VydmVyU2V0dGluZ3MsXG4gICAgICAgIHNhcEFzZVNldHRpbmdzOiBzb3VyY2VPcHRzLnNhcEFzZVNldHRpbmdzLFxuICAgICAgICBkYjJTZXR0aW5nczogc291cmNlT3B0cy5kYjJTZXR0aW5ncyxcbiAgICAgICAgbW9uZ29EYlNldHRpbmdzOiBzb3VyY2VPcHRzLm1vbmdvRGJTZXR0aW5ncyxcbiAgICAgICAgczNTZXR0aW5nczogc291cmNlT3B0cy5zM1NldHRpbmdzLFxuICAgICAgICByZW1vdmFsUG9saWN5LFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBUYXJnZXQgZW5kcG9pbnRcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIGlmIChwcm9wcy5leGlzdGluZ1RhcmdldEVuZHBvaW50KSB7XG4gICAgICB0aGlzLnRhcmdldCA9IHByb3BzLmV4aXN0aW5nVGFyZ2V0RW5kcG9pbnQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHRhcmdldE9wdHMgPSBwcm9wcy50YXJnZXRFbmRwb2ludCE7XG4gICAgICB0aGlzLnRhcmdldCA9IG5ldyBEbXNFbmRwb2ludCh0aGlzLCAnVGFyZ2V0RW5kcG9pbnQnLCB7XG4gICAgICAgIGVuZHBvaW50VHlwZTogRW5kcG9pbnRUeXBlLlRBUkdFVCxcbiAgICAgICAgZW5naW5lOiB0YXJnZXRPcHRzLmVuZ2luZSxcbiAgICAgICAgZW5kcG9pbnRJZGVudGlmaWVyOiB0YXJnZXRPcHRzLmVuZHBvaW50SWRlbnRpZmllcixcbiAgICAgICAgc2VydmVyTmFtZTogdGFyZ2V0T3B0cy5zZXJ2ZXJOYW1lLFxuICAgICAgICBwb3J0OiB0YXJnZXRPcHRzLnBvcnQsXG4gICAgICAgIHVzZXJuYW1lOiB0YXJnZXRPcHRzLnVzZXJuYW1lLFxuICAgICAgICBwYXNzd29yZDogdGFyZ2V0T3B0cy5wYXNzd29yZCxcbiAgICAgICAgZGF0YWJhc2VOYW1lOiB0YXJnZXRPcHRzLmRhdGFiYXNlTmFtZSxcbiAgICAgICAgZXh0cmFDb25uZWN0aW9uQXR0cmlidXRlczogdGFyZ2V0T3B0cy5leHRyYUNvbm5lY3Rpb25BdHRyaWJ1dGVzLFxuICAgICAgICBjZXJ0aWZpY2F0ZUFybjogdGFyZ2V0T3B0cy5jZXJ0aWZpY2F0ZUFybixcbiAgICAgICAgc3NsTW9kZTogdGFyZ2V0T3B0cy5zc2xNb2RlLFxuICAgICAgICBteVNxbFNldHRpbmdzOiB0YXJnZXRPcHRzLm15U3FsU2V0dGluZ3MsXG4gICAgICAgIHBvc3RncmVTcWxTZXR0aW5nczogdGFyZ2V0T3B0cy5wb3N0Z3JlU3FsU2V0dGluZ3MsXG4gICAgICAgIG9yYWNsZVNldHRpbmdzOiB0YXJnZXRPcHRzLm9yYWNsZVNldHRpbmdzLFxuICAgICAgICBzcWxTZXJ2ZXJTZXR0aW5nczogdGFyZ2V0T3B0cy5zcWxTZXJ2ZXJTZXR0aW5ncyxcbiAgICAgICAgc2FwQXNlU2V0dGluZ3M6IHRhcmdldE9wdHMuc2FwQXNlU2V0dGluZ3MsXG4gICAgICAgIGRiMlNldHRpbmdzOiB0YXJnZXRPcHRzLmRiMlNldHRpbmdzLFxuICAgICAgICBtb25nb0RiU2V0dGluZ3M6IHRhcmdldE9wdHMubW9uZ29EYlNldHRpbmdzLFxuICAgICAgICBzM1NldHRpbmdzOiB0YXJnZXRPcHRzLnMzU2V0dGluZ3MsXG4gICAgICAgIGR5bmFtb0RiU2V0dGluZ3M6IHRhcmdldE9wdHMuZHluYW1vRGJTZXR0aW5ncyxcbiAgICAgICAgcmVkc2hpZnRTZXR0aW5nczogdGFyZ2V0T3B0cy5yZWRzaGlmdFNldHRpbmdzLFxuICAgICAgICBraW5lc2lzU2V0dGluZ3M6IHRhcmdldE9wdHMua2luZXNpc1NldHRpbmdzLFxuICAgICAgICBrYWZrYVNldHRpbmdzOiB0YXJnZXRPcHRzLmthZmthU2V0dGluZ3MsXG4gICAgICAgIG9wZW5TZWFyY2hTZXR0aW5nczogdGFyZ2V0T3B0cy5vcGVuU2VhcmNoU2V0dGluZ3MsXG4gICAgICAgIG5lcHR1bmVTZXR0aW5nczogdGFyZ2V0T3B0cy5uZXB0dW5lU2V0dGluZ3MsXG4gICAgICAgIHJlZGlzU2V0dGluZ3M6IHRhcmdldE9wdHMucmVkaXNTZXR0aW5ncyxcbiAgICAgICAgcmVtb3ZhbFBvbGljeSxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gVGFibGUgbWFwcGluZ3Mg4oCUIGRlZmF1bHQgdG8gXCJpbmNsdWRlIGV2ZXJ5dGhpbmdcIlxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgY29uc3QgdGFibGVNYXBwaW5nc0pzb24gPVxuICAgICAgcHJvcHMudGFibGVNYXBwaW5ncyA/PyBuZXcgVGFibGVNYXBwaW5ncygpLmluY2x1ZGVTY2hlbWEoJyUnKS50b0pzb24oKTtcbiAgICAvLyBDZm5SZXBsaWNhdGlvbkNvbmZpZy50YWJsZU1hcHBpbmdzIGV4cGVjdHMgYSBKU09OIG9iamVjdCwgbm90IGEgc3RyaW5nLlxuICAgIGNvbnN0IHRhYmxlTWFwcGluZ3NPYmogPSBKU09OLnBhcnNlKHRhYmxlTWFwcGluZ3NKc29uKTtcblxuICAgIGNvbnN0IHJlcGxpY2F0aW9uU2V0dGluZ3NPYmogPVxuICAgICAgcHJvcHMudGFza1NldHRpbmdzICE9PSB1bmRlZmluZWQgPyBKU09OLnBhcnNlKHByb3BzLnRhc2tTZXR0aW5ncykgOiB1bmRlZmluZWQ7XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIFJlcGxpY2F0aW9uIGNvbmZpZyBpZGVudGlmaWVyXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBjb25zdCBjb25maWdJZGVudGlmaWVyID1cbiAgICAgIHByb3BzLnJlcGxpY2F0aW9uQ29uZmlnSWRlbnRpZmllciA/P1xuICAgICAgY2RrLk5hbWVzLnVuaXF1ZVJlc291cmNlTmFtZSh0aGlzLCB7IG1heExlbmd0aDogNjMgfSkudG9Mb3dlckNhc2UoKTtcblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gQ2ZuUmVwbGljYXRpb25Db25maWdcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIHRoaXMuY2ZuUmVwbGljYXRpb25Db25maWcgPSBuZXcgZG1zLkNmblJlcGxpY2F0aW9uQ29uZmlnKHRoaXMsICdSZXNvdXJjZScsIHtcbiAgICAgIHJlcGxpY2F0aW9uQ29uZmlnSWRlbnRpZmllcjogY29uZmlnSWRlbnRpZmllcixcbiAgICAgIHJlcGxpY2F0aW9uVHlwZTogcHJvcHMubWlncmF0aW9uVHlwZSxcbiAgICAgIHNvdXJjZUVuZHBvaW50QXJuOiB0aGlzLnNvdXJjZS5lbmRwb2ludEFybixcbiAgICAgIHRhcmdldEVuZHBvaW50QXJuOiB0aGlzLnRhcmdldC5lbmRwb2ludEFybixcbiAgICAgIHRhYmxlTWFwcGluZ3M6IHRhYmxlTWFwcGluZ3NPYmosXG4gICAgICByZXBsaWNhdGlvblNldHRpbmdzOiByZXBsaWNhdGlvblNldHRpbmdzT2JqLFxuICAgICAgY29tcHV0ZUNvbmZpZzoge1xuICAgICAgICBtYXhDYXBhY2l0eVVuaXRzOiBwcm9wcy5tYXhDYXBhY2l0eVVuaXRzLFxuICAgICAgICBtaW5DYXBhY2l0eVVuaXRzOiBwcm9wcy5taW5DYXBhY2l0eVVuaXRzLFxuICAgICAgICBtdWx0aUF6OiBwcm9wcy5tdWx0aUF6ID8/IGZhbHNlLFxuICAgICAgICBrbXNLZXlJZDogdGhpcy5lbmNyeXB0aW9uS2V5LmtleUFybixcbiAgICAgICAgcmVwbGljYXRpb25TdWJuZXRHcm91cElkOiB0aGlzLnN1Ym5ldEdyb3VwLnJlZixcbiAgICAgICAgdnBjU2VjdXJpdHlHcm91cElkczogc2VjdXJpdHlHcm91cElkcyxcbiAgICAgICAgcHJlZmVycmVkTWFpbnRlbmFuY2VXaW5kb3c6IHByb3BzLnByZWZlcnJlZE1haW50ZW5hbmNlV2luZG93LFxuICAgICAgfSxcbiAgICB9KTtcbiAgICB0aGlzLmNmblJlcGxpY2F0aW9uQ29uZmlnLmFwcGx5UmVtb3ZhbFBvbGljeShyZW1vdmFsUG9saWN5KTtcblxuICAgIC8vIFRoZSByZXBsaWNhdGlvbiBjb25maWcgY2Fubm90IGJlIHBsYWNlZCBpbiBhIFZQQyB1bnRpbCBkbXMtdnBjLXJvbGUgZXhpc3RzLlxuICAgIGlmICh0aGlzLmRtc1ZwY1JvbGUpIHtcbiAgICAgIHRoaXMuY2ZuUmVwbGljYXRpb25Db25maWcuYWRkRGVwZW5kZW5jeShcbiAgICAgICAgdGhpcy5kbXNWcGNSb2xlLm5vZGUuZGVmYXVsdENoaWxkIGFzIGNkay5DZm5SZXNvdXJjZSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgdGhpcy5yZXBsaWNhdGlvbkNvbmZpZ0FybiA9IHRoaXMuY2ZuUmVwbGljYXRpb25Db25maWcucmVmO1xuICB9XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIFByaXZhdGUgaGVscGVyc1xuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICBwcml2YXRlIHZhbGlkYXRlUHJvcHMocHJvcHM6IERtc1NlcnZlcmxlc3NQaXBlbGluZVByb3BzKTogdm9pZCB7XG4gICAgaWYgKCFWQUxJRF9DQVBBQ0lUWV9VTklUUy5oYXMocHJvcHMubWF4Q2FwYWNpdHlVbml0cykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYG1heENhcGFjaXR5VW5pdHMgbXVzdCBiZSBvbmUgb2YgJHtbLi4uVkFMSURfQ0FQQUNJVFlfVU5JVFNdLmpvaW4oJywgJyl9LiBHb3Q6ICR7cHJvcHMubWF4Q2FwYWNpdHlVbml0c31gLFxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKFxuICAgICAgcHJvcHMubWluQ2FwYWNpdHlVbml0cyAhPT0gdW5kZWZpbmVkICYmXG4gICAgICAhVkFMSURfQ0FQQUNJVFlfVU5JVFMuaGFzKHByb3BzLm1pbkNhcGFjaXR5VW5pdHMpXG4gICAgKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBtaW5DYXBhY2l0eVVuaXRzIG11c3QgYmUgb25lIG9mICR7Wy4uLlZBTElEX0NBUEFDSVRZX1VOSVRTXS5qb2luKCcsICcpfS4gR290OiAke3Byb3BzLm1pbkNhcGFjaXR5VW5pdHN9YCxcbiAgICAgICk7XG4gICAgfVxuICAgIGlmIChcbiAgICAgIHByb3BzLm1pbkNhcGFjaXR5VW5pdHMgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgcHJvcHMubWluQ2FwYWNpdHlVbml0cyA+IHByb3BzLm1heENhcGFjaXR5VW5pdHNcbiAgICApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgYG1pbkNhcGFjaXR5VW5pdHMgKCR7cHJvcHMubWluQ2FwYWNpdHlVbml0c30pIG11c3QgYmUgPD0gbWF4Q2FwYWNpdHlVbml0cyAoJHtwcm9wcy5tYXhDYXBhY2l0eVVuaXRzfSkuYCxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgY29uc3QgaGFzU291cmNlID0gISFwcm9wcy5zb3VyY2VFbmRwb2ludDtcbiAgICBjb25zdCBoYXNFeGlzdGluZ1NvdXJjZSA9ICEhcHJvcHMuZXhpc3RpbmdTb3VyY2VFbmRwb2ludDtcbiAgICBpZiAoaGFzU291cmNlICYmIGhhc0V4aXN0aW5nU291cmNlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Byb3ZpZGUgZWl0aGVyIGBzb3VyY2VFbmRwb2ludGAgb3IgYGV4aXN0aW5nU291cmNlRW5kcG9pbnRgLCBub3QgYm90aC4nKTtcbiAgICB9XG4gICAgaWYgKCFoYXNTb3VyY2UgJiYgIWhhc0V4aXN0aW5nU291cmNlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ09uZSBvZiBgc291cmNlRW5kcG9pbnRgIG9yIGBleGlzdGluZ1NvdXJjZUVuZHBvaW50YCBpcyByZXF1aXJlZC4nKTtcbiAgICB9XG5cbiAgICBjb25zdCBoYXNUYXJnZXQgPSAhIXByb3BzLnRhcmdldEVuZHBvaW50O1xuICAgIGNvbnN0IGhhc0V4aXN0aW5nVGFyZ2V0ID0gISFwcm9wcy5leGlzdGluZ1RhcmdldEVuZHBvaW50O1xuICAgIGlmIChoYXNUYXJnZXQgJiYgaGFzRXhpc3RpbmdUYXJnZXQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignUHJvdmlkZSBlaXRoZXIgYHRhcmdldEVuZHBvaW50YCBvciBgZXhpc3RpbmdUYXJnZXRFbmRwb2ludGAsIG5vdCBib3RoLicpO1xuICAgIH1cbiAgICBpZiAoIWhhc1RhcmdldCAmJiAhaGFzRXhpc3RpbmdUYXJnZXQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignT25lIG9mIGB0YXJnZXRFbmRwb2ludGAgb3IgYGV4aXN0aW5nVGFyZ2V0RW5kcG9pbnRgIGlzIHJlcXVpcmVkLicpO1xuICAgIH1cbiAgfVxufVxuIl19
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Table mappings define which schemas/tables DMS migrates and how they are
|
|
3
|
+
* transformed. This builder produces the JSON string that DMS expects for
|
|
4
|
+
* the `tableMappings` property of a replication task.
|
|
5
|
+
*
|
|
6
|
+
* @see https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Tasks.CustomizingTasks.TableMapping.html
|
|
7
|
+
*/
|
|
8
|
+
/** Whether the rule selects or excludes objects. */
|
|
9
|
+
export declare enum SelectionAction {
|
|
10
|
+
INCLUDE = "include",
|
|
11
|
+
EXCLUDE = "exclude",
|
|
12
|
+
EXPLICIT = "explicit"
|
|
13
|
+
}
|
|
14
|
+
/** Table-level transformation actions. */
|
|
15
|
+
export declare enum TransformationAction {
|
|
16
|
+
/** Convert the name to lowercase. */
|
|
17
|
+
CONVERT_LOWERCASE = "convert-lowercase",
|
|
18
|
+
/** Convert the name to uppercase. */
|
|
19
|
+
CONVERT_UPPERCASE = "convert-uppercase",
|
|
20
|
+
/** Add a prefix to the name. */
|
|
21
|
+
ADD_PREFIX = "add-prefix",
|
|
22
|
+
/** Remove a prefix from the name. */
|
|
23
|
+
REMOVE_PREFIX = "remove-prefix",
|
|
24
|
+
/** Add a suffix to the name. */
|
|
25
|
+
ADD_SUFFIX = "add-suffix",
|
|
26
|
+
/** Remove a suffix from the name. */
|
|
27
|
+
REMOVE_SUFFIX = "remove-suffix",
|
|
28
|
+
/** Rename the object. */
|
|
29
|
+
RENAME = "rename",
|
|
30
|
+
/** Remove the column. */
|
|
31
|
+
REMOVE_COLUMN = "remove-column",
|
|
32
|
+
/** Add a column. */
|
|
33
|
+
ADD_COLUMN = "add-column",
|
|
34
|
+
/** Include the column. */
|
|
35
|
+
INCLUDE_COLUMN = "include-column"
|
|
36
|
+
}
|
|
37
|
+
/** The object type a rule targets. */
|
|
38
|
+
export declare enum RuleObjectLocator {
|
|
39
|
+
SCHEMA = "schema",
|
|
40
|
+
TABLE = "table",
|
|
41
|
+
COLUMN = "column",
|
|
42
|
+
TABLE_TABLESPACE = "table-tablespace",
|
|
43
|
+
INDEX_TABLESPACE = "index-tablespace"
|
|
44
|
+
}
|
|
45
|
+
/** Data type for added columns. */
|
|
46
|
+
export declare enum ColumnDataType {
|
|
47
|
+
STRING = "string",
|
|
48
|
+
INT4 = "int4",
|
|
49
|
+
INT8 = "int8",
|
|
50
|
+
FLOAT4 = "float4",
|
|
51
|
+
FLOAT8 = "float8",
|
|
52
|
+
NUMERIC = "numeric",
|
|
53
|
+
DATETIME = "datetime",
|
|
54
|
+
BYTES = "bytes",
|
|
55
|
+
BLOB = "blob"
|
|
56
|
+
}
|
|
57
|
+
/** A column added via an ADD_COLUMN transformation. */
|
|
58
|
+
export interface AddColumnDefinition {
|
|
59
|
+
/** Name of the new column. */
|
|
60
|
+
readonly columnName: string;
|
|
61
|
+
/** Data type of the new column. */
|
|
62
|
+
readonly columnType: ColumnDataType;
|
|
63
|
+
/** Character length for string columns. */
|
|
64
|
+
readonly columnLength?: number;
|
|
65
|
+
/** Precision for numeric columns. */
|
|
66
|
+
readonly columnPrecision?: number;
|
|
67
|
+
/** Scale for numeric columns. */
|
|
68
|
+
readonly columnScale?: number;
|
|
69
|
+
/**
|
|
70
|
+
* Constant value to populate the column with.
|
|
71
|
+
* Exactly one of `columnValue` or `expression` must be set.
|
|
72
|
+
*/
|
|
73
|
+
readonly columnValue?: string;
|
|
74
|
+
/**
|
|
75
|
+
* Expression (e.g. `$timestamp`) to populate the column.
|
|
76
|
+
* Exactly one of `columnValue` or `expression` must be set.
|
|
77
|
+
*/
|
|
78
|
+
readonly expression?: string;
|
|
79
|
+
}
|
|
80
|
+
/** Object locator identifying the schema, table, and optional column a rule targets. */
|
|
81
|
+
export interface RuleObjectLocatorValue {
|
|
82
|
+
readonly schemaName: string;
|
|
83
|
+
readonly tableName?: string;
|
|
84
|
+
readonly columnName?: string;
|
|
85
|
+
}
|
|
86
|
+
/** Represents a single, fully built rule in the table-mappings JSON. */
|
|
87
|
+
export interface TableMappingRule {
|
|
88
|
+
readonly ruleType: string;
|
|
89
|
+
readonly ruleId: string;
|
|
90
|
+
readonly ruleName: string;
|
|
91
|
+
readonly objectLocator: RuleObjectLocatorValue;
|
|
92
|
+
readonly ruleAction: string;
|
|
93
|
+
readonly value?: string;
|
|
94
|
+
readonly oldValue?: string;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Fluent builder for DMS table mappings.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* const mappings = new TableMappings()
|
|
101
|
+
* .includeSchema('public')
|
|
102
|
+
* .includeTable('public', 'orders')
|
|
103
|
+
* .excludeTable('public', 'audit_log')
|
|
104
|
+
* .renameSchema('public', 'prod')
|
|
105
|
+
* .toLowerCaseTable('public', '%')
|
|
106
|
+
* .toJson();
|
|
107
|
+
*/
|
|
108
|
+
export declare class TableMappings {
|
|
109
|
+
private readonly rules;
|
|
110
|
+
private nextId;
|
|
111
|
+
/**
|
|
112
|
+
* Include all tables in a schema.
|
|
113
|
+
* Use `%` as a wildcard for `schemaName` to include all schemas.
|
|
114
|
+
*/
|
|
115
|
+
includeSchema(schemaName: string): TableMappings;
|
|
116
|
+
/** Exclude all tables in a schema. */
|
|
117
|
+
excludeSchema(schemaName: string): TableMappings;
|
|
118
|
+
/**
|
|
119
|
+
* Include a specific table (or a wildcard pattern) within a schema.
|
|
120
|
+
* Use `%` for `tableName` to match all tables in the schema.
|
|
121
|
+
*/
|
|
122
|
+
includeTable(schemaName: string, tableName: string): TableMappings;
|
|
123
|
+
/** Exclude a specific table (or wildcard) within a schema. */
|
|
124
|
+
excludeTable(schemaName: string, tableName: string): TableMappings;
|
|
125
|
+
/**
|
|
126
|
+
* Explicitly include a single table. Unlike `include`, `explicit` means DMS
|
|
127
|
+
* only migrates this one table regardless of other `include` rules.
|
|
128
|
+
*/
|
|
129
|
+
explicitTable(schemaName: string, tableName: string): TableMappings;
|
|
130
|
+
private addSelectionRule;
|
|
131
|
+
/** Rename a schema. */
|
|
132
|
+
renameSchema(schemaName: string, newName: string): TableMappings;
|
|
133
|
+
/** Convert all schema names to lowercase. */
|
|
134
|
+
toLowerCaseSchema(schemaName: string): TableMappings;
|
|
135
|
+
/** Convert all schema names to uppercase. */
|
|
136
|
+
toUpperCaseSchema(schemaName: string): TableMappings;
|
|
137
|
+
/** Add a prefix to schema names. */
|
|
138
|
+
addPrefixToSchema(schemaName: string, prefix: string): TableMappings;
|
|
139
|
+
/** Add a suffix to schema names. */
|
|
140
|
+
addSuffixToSchema(schemaName: string, suffix: string): TableMappings;
|
|
141
|
+
/** Rename a table. */
|
|
142
|
+
renameTable(schemaName: string, tableName: string, newName: string): TableMappings;
|
|
143
|
+
/** Convert matching table names to lowercase. Use `%` to match all tables. */
|
|
144
|
+
toLowerCaseTable(schemaName: string, tableName: string): TableMappings;
|
|
145
|
+
/** Convert matching table names to uppercase. */
|
|
146
|
+
toUpperCaseTable(schemaName: string, tableName: string): TableMappings;
|
|
147
|
+
/** Add a prefix to table names. */
|
|
148
|
+
addPrefixToTable(schemaName: string, tableName: string, prefix: string): TableMappings;
|
|
149
|
+
/** Add a suffix to table names. */
|
|
150
|
+
addSuffixToTable(schemaName: string, tableName: string, suffix: string): TableMappings;
|
|
151
|
+
/** Rename a column in a table. */
|
|
152
|
+
renameColumn(schemaName: string, tableName: string, columnName: string, newName: string): TableMappings;
|
|
153
|
+
/** Convert matching column names to lowercase. */
|
|
154
|
+
toLowerCaseColumn(schemaName: string, tableName: string, columnName: string): TableMappings;
|
|
155
|
+
/** Convert matching column names to uppercase. */
|
|
156
|
+
toUpperCaseColumn(schemaName: string, tableName: string, columnName: string): TableMappings;
|
|
157
|
+
/** Remove a column from a table. */
|
|
158
|
+
removeColumn(schemaName: string, tableName: string, columnName: string): TableMappings;
|
|
159
|
+
/**
|
|
160
|
+
* Add a new column to a table.
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* mappings.addColumn('public', 'orders', {
|
|
164
|
+
* columnName: 'migration_ts',
|
|
165
|
+
* columnType: ColumnDataType.DATETIME,
|
|
166
|
+
* expression: '$timestamp',
|
|
167
|
+
* });
|
|
168
|
+
*/
|
|
169
|
+
addColumn(schemaName: string, tableName: string, column: AddColumnDefinition): TableMappings;
|
|
170
|
+
private buildDataType;
|
|
171
|
+
private addTransformationRule;
|
|
172
|
+
/**
|
|
173
|
+
* Serialise the accumulated rules to the JSON string expected by DMS.
|
|
174
|
+
* Passes the result directly to `replicationTaskSettings` or
|
|
175
|
+
* `DmsReplicationTask.tableMappings`.
|
|
176
|
+
*/
|
|
177
|
+
toJson(): string;
|
|
178
|
+
}
|