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.
@@ -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
+ }