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,253 @@
1
+ import * as cdk from 'aws-cdk-lib';
2
+ import * as ec2 from 'aws-cdk-lib/aws-ec2';
3
+ import * as iam from 'aws-cdk-lib/aws-iam';
4
+ import * as kms from 'aws-cdk-lib/aws-kms';
5
+ import * as logs from 'aws-cdk-lib/aws-logs';
6
+ import { Construct } from 'constructs';
7
+ import { DmsEndpointProps, IDmsEndpoint } from './endpoint';
8
+ import { MigrationType, ReplicationInstanceClass } from './enums';
9
+ import { DmsReplicationInstance } from './replication-instance';
10
+ import { DmsReplicationTask } from './replication-task';
11
+ /**
12
+ * Properties for the source endpoint of a {@link DmsMigrationPipeline}.
13
+ * Extends {@link DmsEndpointProps} but omits `endpointType` (always SOURCE).
14
+ */
15
+ export interface SourceEndpointOptions {
16
+ readonly engine: DmsEndpointProps['engine'];
17
+ readonly endpointIdentifier?: string;
18
+ readonly serverName?: string;
19
+ readonly port?: number;
20
+ readonly username?: string;
21
+ /**
22
+ * Database password. The resolved value is stored as **plaintext** in the
23
+ * CloudFormation template. Prefer `secretsManagerSecretId` in the
24
+ * engine-specific settings for production workloads.
25
+ */
26
+ readonly password?: cdk.SecretValue;
27
+ readonly databaseName?: string;
28
+ readonly extraConnectionAttributes?: string;
29
+ readonly certificateArn?: string;
30
+ readonly sslMode?: string;
31
+ readonly mySqlSettings?: DmsEndpointProps['mySqlSettings'];
32
+ readonly postgreSqlSettings?: DmsEndpointProps['postgreSqlSettings'];
33
+ readonly oracleSettings?: DmsEndpointProps['oracleSettings'];
34
+ readonly sqlServerSettings?: DmsEndpointProps['sqlServerSettings'];
35
+ readonly sapAseSettings?: DmsEndpointProps['sapAseSettings'];
36
+ readonly db2Settings?: DmsEndpointProps['db2Settings'];
37
+ readonly mongoDbSettings?: DmsEndpointProps['mongoDbSettings'];
38
+ readonly s3Settings?: DmsEndpointProps['s3Settings'];
39
+ }
40
+ /**
41
+ * Properties for the target endpoint of a {@link DmsMigrationPipeline}.
42
+ * Extends {@link DmsEndpointProps} but omits `endpointType` (always TARGET).
43
+ */
44
+ export interface TargetEndpointOptions {
45
+ readonly engine: DmsEndpointProps['engine'];
46
+ readonly endpointIdentifier?: string;
47
+ readonly serverName?: string;
48
+ readonly port?: number;
49
+ readonly username?: string;
50
+ /**
51
+ * Database password. The resolved value is stored as **plaintext** in the
52
+ * CloudFormation template. Prefer `secretsManagerSecretId` in the
53
+ * engine-specific settings for production workloads.
54
+ */
55
+ readonly password?: cdk.SecretValue;
56
+ readonly databaseName?: string;
57
+ readonly extraConnectionAttributes?: string;
58
+ readonly certificateArn?: string;
59
+ readonly sslMode?: string;
60
+ readonly mySqlSettings?: DmsEndpointProps['mySqlSettings'];
61
+ readonly postgreSqlSettings?: DmsEndpointProps['postgreSqlSettings'];
62
+ readonly oracleSettings?: DmsEndpointProps['oracleSettings'];
63
+ readonly sqlServerSettings?: DmsEndpointProps['sqlServerSettings'];
64
+ readonly sapAseSettings?: DmsEndpointProps['sapAseSettings'];
65
+ readonly db2Settings?: DmsEndpointProps['db2Settings'];
66
+ readonly mongoDbSettings?: DmsEndpointProps['mongoDbSettings'];
67
+ readonly s3Settings?: DmsEndpointProps['s3Settings'];
68
+ readonly dynamoDbSettings?: DmsEndpointProps['dynamoDbSettings'];
69
+ readonly redshiftSettings?: DmsEndpointProps['redshiftSettings'];
70
+ readonly kinesisSettings?: DmsEndpointProps['kinesisSettings'];
71
+ readonly kafkaSettings?: DmsEndpointProps['kafkaSettings'];
72
+ readonly openSearchSettings?: DmsEndpointProps['openSearchSettings'];
73
+ readonly neptuneSettings?: DmsEndpointProps['neptuneSettings'];
74
+ readonly redisSettings?: DmsEndpointProps['redisSettings'];
75
+ }
76
+ /** Top-level props for {@link DmsMigrationPipeline}. */
77
+ export interface DmsMigrationPipelineProps {
78
+ /**
79
+ * VPC in which to place the replication instance.
80
+ * The instance is placed in private subnets.
81
+ */
82
+ readonly vpc: ec2.IVpc;
83
+ /**
84
+ * Subnet selection for the replication instance.
85
+ * @default private subnets with egress
86
+ */
87
+ readonly vpcSubnets?: ec2.SubnetSelection;
88
+ /**
89
+ * Replication instance class.
90
+ * @default ReplicationInstanceClass.R6I_LARGE
91
+ */
92
+ readonly replicationInstanceClass?: ReplicationInstanceClass;
93
+ /**
94
+ * Allocated storage for the replication instance in GB.
95
+ * @default 100
96
+ */
97
+ readonly allocatedStorage?: number;
98
+ /**
99
+ * Whether the replication instance is Multi-AZ.
100
+ * @default false
101
+ */
102
+ readonly multiAz?: boolean;
103
+ /**
104
+ * Engine version for the replication instance.
105
+ * @default latest version available in the region (chosen by DMS)
106
+ */
107
+ readonly engineVersion?: string;
108
+ /**
109
+ * KMS key for encrypting the replication instance storage at rest.
110
+ * A new key is created if not provided.
111
+ */
112
+ readonly encryptionKey?: kms.IKey;
113
+ /**
114
+ * Source endpoint configuration.
115
+ * Provide this OR `existingSourceEndpoint` — not both.
116
+ */
117
+ readonly sourceEndpoint?: SourceEndpointOptions;
118
+ /**
119
+ * An existing {@link IDmsEndpoint} to use as the source.
120
+ * Provide this OR `sourceEndpoint` — not both.
121
+ */
122
+ readonly existingSourceEndpoint?: IDmsEndpoint;
123
+ /**
124
+ * Target endpoint configuration.
125
+ * Provide this OR `existingTargetEndpoint` — not both.
126
+ */
127
+ readonly targetEndpoint?: TargetEndpointOptions;
128
+ /**
129
+ * An existing {@link IDmsEndpoint} to use as the target.
130
+ * Provide this OR `targetEndpoint` — not both.
131
+ */
132
+ readonly existingTargetEndpoint?: IDmsEndpoint;
133
+ /** The type of migration to perform. */
134
+ readonly migrationType: MigrationType;
135
+ /**
136
+ * Table mappings JSON string.
137
+ * Use {@link TableMappings} to build this.
138
+ * Defaults to "include all tables in all schemas" if not provided.
139
+ */
140
+ readonly tableMappings?: string;
141
+ /**
142
+ * Task settings JSON string.
143
+ * Use {@link TaskSettings} to build this.
144
+ * Sensible defaults are applied if not provided.
145
+ */
146
+ readonly taskSettings?: string;
147
+ /**
148
+ * CDC start time (ISO-8601 string or Unix epoch seconds).
149
+ * Only used when migrationType includes CDC.
150
+ */
151
+ readonly cdcStartTime?: string;
152
+ /**
153
+ * CDC start position (LSN or equivalent).
154
+ * Only used when migrationType includes CDC.
155
+ */
156
+ readonly cdcStartPosition?: string;
157
+ /**
158
+ * CDC stop position.
159
+ * Only used when migrationType includes CDC.
160
+ */
161
+ readonly cdcStopPosition?: string;
162
+ /**
163
+ * Whether to create a CloudWatch log group for the task.
164
+ * @default true
165
+ */
166
+ readonly enableCloudWatchLogs?: boolean;
167
+ /**
168
+ * Retention period for the CloudWatch log group.
169
+ * @default logs.RetentionDays.ONE_MONTH
170
+ */
171
+ readonly logRetention?: logs.RetentionDays;
172
+ /**
173
+ * Whether to create the two account-level DMS service roles (`dms-vpc-role`
174
+ * and `dms-cloudwatch-logs-role`) required by DMS.
175
+ *
176
+ * Set this to `false` if the roles already exist in the AWS account — for
177
+ * example, because another CDK stack (or a manual deployment) already
178
+ * created them. Attempting to create roles with the same name twice in the
179
+ * same account causes a CloudFormation `EntityAlreadyExists` error.
180
+ *
181
+ * When `false`, the construct expects the roles to already be present and
182
+ * skips creating them. The `dmsVpcRole` and `dmsCloudWatchRole` properties
183
+ * will be `undefined`.
184
+ *
185
+ * @default true
186
+ */
187
+ readonly createDmsServiceRoles?: boolean;
188
+ /**
189
+ * Removal policy applied to all resources in the pipeline.
190
+ * @default cdk.RemovalPolicy.DESTROY
191
+ */
192
+ readonly removalPolicy?: cdk.RemovalPolicy;
193
+ }
194
+ /**
195
+ * An L3 CDK pattern construct that provisions a complete DMS migration pipeline:
196
+ *
197
+ * - **Replication instance** — placed in private subnets with KMS encryption
198
+ * and a dedicated security group.
199
+ * - **Source endpoint** — supports every engine DMS supports.
200
+ * - **Target endpoint** — supports every engine DMS supports.
201
+ * - **Replication task** — wires the instance, endpoints, table mappings and
202
+ * task settings together.
203
+ * - **IAM role** — grants DMS permission to write to CloudWatch Logs.
204
+ * - **CloudWatch log group** — (optional) retains task logs.
205
+ *
206
+ * @example
207
+ * // MySQL → Aurora PostgreSQL, full-load-and-CDC
208
+ * const pipeline = new DmsMigrationPipeline(this, 'MigrationPipeline', {
209
+ * vpc,
210
+ * migrationType: MigrationType.FULL_LOAD_AND_CDC,
211
+ * sourceEndpoint: {
212
+ * engine: EndpointEngine.MYSQL,
213
+ * serverName: 'mysql.example.com',
214
+ * port: 3306,
215
+ * username: 'dms_user',
216
+ * password: cdk.SecretValue.secretsManager('mysql-dms-secret'),
217
+ * databaseName: 'mydb',
218
+ * },
219
+ * targetEndpoint: {
220
+ * engine: EndpointEngine.AURORA_POSTGRESQL,
221
+ * serverName: cluster.clusterEndpoint.hostname,
222
+ * port: 5432,
223
+ * username: 'dms_user',
224
+ * password: cdk.SecretValue.secretsManager('aurora-dms-secret'),
225
+ * databaseName: 'mydb',
226
+ * },
227
+ * tableMappings: new TableMappings().includeSchema('public').toJson(),
228
+ * });
229
+ */
230
+ export declare class DmsMigrationPipeline extends Construct {
231
+ /** The replication instance provisioned by this pipeline. */
232
+ readonly replicationInstance: DmsReplicationInstance;
233
+ /** The source endpoint used by this pipeline. */
234
+ readonly source: IDmsEndpoint;
235
+ /** The target endpoint used by this pipeline. */
236
+ readonly target: IDmsEndpoint;
237
+ /** The replication task that drives the migration. */
238
+ readonly replicationTask: DmsReplicationTask;
239
+ /** CloudWatch log group for the task (if enableCloudWatchLogs is true). */
240
+ readonly logGroup?: logs.LogGroup;
241
+ /**
242
+ * IAM role that allows DMS to write to CloudWatch Logs.
243
+ * `undefined` when `createDmsServiceRoles` is `false`.
244
+ */
245
+ readonly dmsCloudWatchRole?: iam.Role;
246
+ /**
247
+ * IAM role that allows DMS to manage VPC resources (dms-vpc-role).
248
+ * `undefined` when `createDmsServiceRoles` is `false`.
249
+ */
250
+ readonly dmsVpcRole?: iam.Role;
251
+ constructor(scope: Construct, id: string, props: DmsMigrationPipelineProps);
252
+ private validateProps;
253
+ }
@@ -0,0 +1,218 @@
1
+ "use strict";
2
+ var _a;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.DmsMigrationPipeline = void 0;
5
+ const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
6
+ const cdk = require("aws-cdk-lib");
7
+ const logs = require("aws-cdk-lib/aws-logs");
8
+ const constructs_1 = require("constructs");
9
+ const dms_roles_1 = require("./dms-roles");
10
+ const endpoint_1 = require("./endpoint");
11
+ const enums_1 = require("./enums");
12
+ const replication_instance_1 = require("./replication-instance");
13
+ const replication_task_1 = require("./replication-task");
14
+ const table_mappings_1 = require("./table-mappings");
15
+ // ---------------------------------------------------------------------------
16
+ // Construct
17
+ // ---------------------------------------------------------------------------
18
+ /**
19
+ * An L3 CDK pattern construct that provisions a complete DMS migration pipeline:
20
+ *
21
+ * - **Replication instance** — placed in private subnets with KMS encryption
22
+ * and a dedicated security group.
23
+ * - **Source endpoint** — supports every engine DMS supports.
24
+ * - **Target endpoint** — supports every engine DMS supports.
25
+ * - **Replication task** — wires the instance, endpoints, table mappings and
26
+ * task settings together.
27
+ * - **IAM role** — grants DMS permission to write to CloudWatch Logs.
28
+ * - **CloudWatch log group** — (optional) retains task logs.
29
+ *
30
+ * @example
31
+ * // MySQL → Aurora PostgreSQL, full-load-and-CDC
32
+ * const pipeline = new DmsMigrationPipeline(this, 'MigrationPipeline', {
33
+ * vpc,
34
+ * migrationType: MigrationType.FULL_LOAD_AND_CDC,
35
+ * sourceEndpoint: {
36
+ * engine: EndpointEngine.MYSQL,
37
+ * serverName: 'mysql.example.com',
38
+ * port: 3306,
39
+ * username: 'dms_user',
40
+ * password: cdk.SecretValue.secretsManager('mysql-dms-secret'),
41
+ * databaseName: 'mydb',
42
+ * },
43
+ * targetEndpoint: {
44
+ * engine: EndpointEngine.AURORA_POSTGRESQL,
45
+ * serverName: cluster.clusterEndpoint.hostname,
46
+ * port: 5432,
47
+ * username: 'dms_user',
48
+ * password: cdk.SecretValue.secretsManager('aurora-dms-secret'),
49
+ * databaseName: 'mydb',
50
+ * },
51
+ * tableMappings: new TableMappings().includeSchema('public').toJson(),
52
+ * });
53
+ */
54
+ class DmsMigrationPipeline extends constructs_1.Construct {
55
+ constructor(scope, id, props) {
56
+ super(scope, id);
57
+ this.validateProps(props);
58
+ const removalPolicy = props.removalPolicy ?? cdk.RemovalPolicy.DESTROY;
59
+ const createRoles = props.createDmsServiceRoles ?? true;
60
+ // -----------------------------------------------------------------------
61
+ // dms-vpc-role — account-level singleton required by DMS to place
62
+ // replication instances inside a VPC. Must exist before the first
63
+ // CfnReplicationInstance is created in the account.
64
+ // Skip when createDmsServiceRoles is false (roles already exist).
65
+ // -----------------------------------------------------------------------
66
+ if (createRoles) {
67
+ this.dmsVpcRole = (0, dms_roles_1.ensureDmsVpcRole)(cdk.Stack.of(this));
68
+ }
69
+ // -----------------------------------------------------------------------
70
+ // CloudWatch log group & IAM role
71
+ // -----------------------------------------------------------------------
72
+ const enableLogs = props.enableCloudWatchLogs ?? true;
73
+ if (enableLogs) {
74
+ this.logGroup = new logs.LogGroup(this, 'TaskLogGroup', {
75
+ logGroupName: `/aws/dms/tasks/${id}`,
76
+ retention: props.logRetention ?? logs.RetentionDays.ONE_MONTH,
77
+ removalPolicy,
78
+ });
79
+ if (createRoles) {
80
+ // dms-cloudwatch-logs-role is an account-level singleton — DMS requires
81
+ // this exact name. Guard with a stack-level singleton so deploying multiple
82
+ // pipelines in the same stack doesn't create duplicate roles.
83
+ this.dmsCloudWatchRole = (0, dms_roles_1.ensureDmsCloudWatchRole)(cdk.Stack.of(this));
84
+ }
85
+ }
86
+ // -----------------------------------------------------------------------
87
+ // Replication instance
88
+ // -----------------------------------------------------------------------
89
+ this.replicationInstance = new replication_instance_1.DmsReplicationInstance(this, 'ReplicationInstance', {
90
+ vpc: props.vpc,
91
+ vpcSubnets: props.vpcSubnets,
92
+ replicationInstanceClass: props.replicationInstanceClass,
93
+ allocatedStorage: props.allocatedStorage,
94
+ multiAz: props.multiAz,
95
+ engineVersion: props.engineVersion,
96
+ kmsKey: props.encryptionKey,
97
+ removalPolicy,
98
+ });
99
+ // The replication instance cannot be placed in a VPC until dms-vpc-role exists.
100
+ // Only add the dependency when we created the role ourselves.
101
+ if (this.dmsVpcRole) {
102
+ this.replicationInstance.cfnReplicationInstance.addDependency(this.dmsVpcRole.node.defaultChild);
103
+ }
104
+ // -----------------------------------------------------------------------
105
+ // Source endpoint
106
+ // -----------------------------------------------------------------------
107
+ if (props.existingSourceEndpoint) {
108
+ this.source = props.existingSourceEndpoint;
109
+ }
110
+ else {
111
+ const sourceOpts = props.sourceEndpoint;
112
+ this.source = new endpoint_1.DmsEndpoint(this, 'SourceEndpoint', {
113
+ endpointType: enums_1.EndpointType.SOURCE,
114
+ engine: sourceOpts.engine,
115
+ endpointIdentifier: sourceOpts.endpointIdentifier,
116
+ serverName: sourceOpts.serverName,
117
+ port: sourceOpts.port,
118
+ username: sourceOpts.username,
119
+ password: sourceOpts.password,
120
+ databaseName: sourceOpts.databaseName,
121
+ extraConnectionAttributes: sourceOpts.extraConnectionAttributes,
122
+ certificateArn: sourceOpts.certificateArn,
123
+ sslMode: sourceOpts.sslMode,
124
+ mySqlSettings: sourceOpts.mySqlSettings,
125
+ postgreSqlSettings: sourceOpts.postgreSqlSettings,
126
+ oracleSettings: sourceOpts.oracleSettings,
127
+ sqlServerSettings: sourceOpts.sqlServerSettings,
128
+ sapAseSettings: sourceOpts.sapAseSettings,
129
+ db2Settings: sourceOpts.db2Settings,
130
+ mongoDbSettings: sourceOpts.mongoDbSettings,
131
+ s3Settings: sourceOpts.s3Settings,
132
+ removalPolicy,
133
+ });
134
+ }
135
+ // -----------------------------------------------------------------------
136
+ // Target endpoint
137
+ // -----------------------------------------------------------------------
138
+ if (props.existingTargetEndpoint) {
139
+ this.target = props.existingTargetEndpoint;
140
+ }
141
+ else {
142
+ const targetOpts = props.targetEndpoint;
143
+ this.target = new endpoint_1.DmsEndpoint(this, 'TargetEndpoint', {
144
+ endpointType: enums_1.EndpointType.TARGET,
145
+ engine: targetOpts.engine,
146
+ endpointIdentifier: targetOpts.endpointIdentifier,
147
+ serverName: targetOpts.serverName,
148
+ port: targetOpts.port,
149
+ username: targetOpts.username,
150
+ password: targetOpts.password,
151
+ databaseName: targetOpts.databaseName,
152
+ extraConnectionAttributes: targetOpts.extraConnectionAttributes,
153
+ certificateArn: targetOpts.certificateArn,
154
+ sslMode: targetOpts.sslMode,
155
+ mySqlSettings: targetOpts.mySqlSettings,
156
+ postgreSqlSettings: targetOpts.postgreSqlSettings,
157
+ oracleSettings: targetOpts.oracleSettings,
158
+ sqlServerSettings: targetOpts.sqlServerSettings,
159
+ sapAseSettings: targetOpts.sapAseSettings,
160
+ db2Settings: targetOpts.db2Settings,
161
+ mongoDbSettings: targetOpts.mongoDbSettings,
162
+ s3Settings: targetOpts.s3Settings,
163
+ dynamoDbSettings: targetOpts.dynamoDbSettings,
164
+ redshiftSettings: targetOpts.redshiftSettings,
165
+ kinesisSettings: targetOpts.kinesisSettings,
166
+ kafkaSettings: targetOpts.kafkaSettings,
167
+ openSearchSettings: targetOpts.openSearchSettings,
168
+ neptuneSettings: targetOpts.neptuneSettings,
169
+ redisSettings: targetOpts.redisSettings,
170
+ removalPolicy,
171
+ });
172
+ }
173
+ // -----------------------------------------------------------------------
174
+ // Table mappings — default to "include everything"
175
+ // -----------------------------------------------------------------------
176
+ const tableMappings = props.tableMappings ?? new table_mappings_1.TableMappings().includeSchema('%').toJson();
177
+ // -----------------------------------------------------------------------
178
+ // Replication task
179
+ // -----------------------------------------------------------------------
180
+ this.replicationTask = new replication_task_1.DmsReplicationTask(this, 'ReplicationTask', {
181
+ replicationInstanceArn: this.replicationInstance.replicationInstanceArn,
182
+ sourceEndpoint: this.source,
183
+ targetEndpoint: this.target,
184
+ migrationType: props.migrationType,
185
+ tableMappings,
186
+ taskSettings: props.taskSettings,
187
+ cdcStartTime: props.cdcStartTime,
188
+ cdcStartPosition: props.cdcStartPosition,
189
+ cdcStopPosition: props.cdcStopPosition,
190
+ removalPolicy,
191
+ });
192
+ }
193
+ // ---------------------------------------------------------------------------
194
+ // Private helpers
195
+ // ---------------------------------------------------------------------------
196
+ validateProps(props) {
197
+ const hasSource = !!props.sourceEndpoint;
198
+ const hasExistingSource = !!props.existingSourceEndpoint;
199
+ if (hasSource && hasExistingSource) {
200
+ throw new Error('Provide either `sourceEndpoint` or `existingSourceEndpoint`, not both.');
201
+ }
202
+ if (!hasSource && !hasExistingSource) {
203
+ throw new Error('One of `sourceEndpoint` or `existingSourceEndpoint` is required.');
204
+ }
205
+ const hasTarget = !!props.targetEndpoint;
206
+ const hasExistingTarget = !!props.existingTargetEndpoint;
207
+ if (hasTarget && hasExistingTarget) {
208
+ throw new Error('Provide either `targetEndpoint` or `existingTargetEndpoint`, not both.');
209
+ }
210
+ if (!hasTarget && !hasExistingTarget) {
211
+ throw new Error('One of `targetEndpoint` or `existingTargetEndpoint` is required.');
212
+ }
213
+ }
214
+ }
215
+ exports.DmsMigrationPipeline = DmsMigrationPipeline;
216
+ _a = JSII_RTTI_SYMBOL_1;
217
+ DmsMigrationPipeline[_a] = { fqn: "cdk-dms-replication.DmsMigrationPipeline", version: "0.0.0" };
218
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWlncmF0aW9uLXBpcGVsaW5lLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL21pZ3JhdGlvbi1waXBlbGluZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLG1DQUFtQztBQUluQyw2Q0FBNkM7QUFDN0MsMkNBQXVDO0FBQ3ZDLDJDQUF3RTtBQUN4RSx5Q0FBeUU7QUFDekUsbUNBQWdGO0FBQ2hGLGlFQUFnRTtBQUNoRSx5REFBd0Q7QUFDeEQscURBQWlEO0FBNk9qRCw4RUFBOEU7QUFDOUUsWUFBWTtBQUNaLDhFQUE4RTtBQUU5RTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtQ0c7QUFDSCxNQUFhLG9CQUFxQixTQUFRLHNCQUFTO0lBZ0NqRCxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQWdDO1FBQ3hFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUUxQixNQUFNLGFBQWEsR0FBRyxLQUFLLENBQUMsYUFBYSxJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDO1FBQ3ZFLE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQyxxQkFBcUIsSUFBSSxJQUFJLENBQUM7UUFFeEQsMEVBQTBFO1FBQzFFLGtFQUFrRTtRQUNsRSxrRUFBa0U7UUFDbEUsb0RBQW9EO1FBQ3BELGtFQUFrRTtRQUNsRSwwRUFBMEU7UUFDMUUsSUFBSSxXQUFXLEVBQUUsQ0FBQztZQUNoQixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUEsNEJBQWdCLEVBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUN6RCxDQUFDO1FBRUQsMEVBQTBFO1FBQzFFLGtDQUFrQztRQUNsQywwRUFBMEU7UUFDMUUsTUFBTSxVQUFVLEdBQUcsS0FBSyxDQUFDLG9CQUFvQixJQUFJLElBQUksQ0FB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S0FBZ0M7UUFDcEQsTUFBTSxTQUFTLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUM7UUFDekMsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLENBQUMsS0FBSyxDQUFDLHNCQUFzQixDQUFDO1FBQ3pELElBQUksU0FBUyxJQUFJLGlCQUFpQixFQUFFLENBQUM7WUFDbkMsTUFBTSxJQUFJLEtBQUssQ0FDYix3RUFBd0UsQ0FDekUsQ0FBQztRQUNKLENBQUM7UUFDRCxJQUFJLENBQUMsU0FBUyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUNyQyxNQUFNLElBQUksS0FBSyxDQUNiLGtFQUFrRSxDQUNuRSxDQUFDO1FBQ0osQ0FBQztRQUVELE1BQU0sU0FBUyxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsY0FBYyxDQUFDO1FBQ3pDLE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQztRQUN6RCxJQUFJLFNBQVMsSUFBSSxpQkFBaUIsRUFBRSxDQUFDO1lBQ25DLE1BQU0sSUFBSSxLQUFLLENBQ2Isd0VBQXdFLENBQ3pFLENBQUM7UUFDSixDQUFDO1FBQ0QsSUFBSSxDQUFDLFNBQVMsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7WUFDckMsTUFBTSxJQUFJLEtBQUssQ0FDYixrRUFBa0UsQ0FDbkUsQ0FBQztRQUNKLENBQUM7SUFDSCxDQUFDOztBQXROSCxvREF1TkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjZGsgZnJvbSAnYXdzLWNkay1saWInO1xuaW1wb3J0ICogYXMgZWMyIGZyb20gJ2F3cy1jZGstbGliL2F3cy1lYzInO1xuaW1wb3J0ICogYXMgaWFtIGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuaW1wb3J0ICogYXMga21zIGZyb20gJ2F3cy1jZGstbGliL2F3cy1rbXMnO1xuaW1wb3J0ICogYXMgbG9ncyBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbG9ncyc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IGVuc3VyZURtc0Nsb3VkV2F0Y2hSb2xlLCBlbnN1cmVEbXNWcGNSb2xlIH0gZnJvbSAnLi9kbXMtcm9sZXMnO1xuaW1wb3J0IHsgRG1zRW5kcG9pbnQsIERtc0VuZHBvaW50UHJvcHMsIElEbXNFbmRwb2ludCB9IGZyb20gJy4vZW5kcG9pbnQnO1xuaW1wb3J0IHsgRW5kcG9pbnRUeXBlLCBNaWdyYXRpb25UeXBlLCBSZXBsaWNhdGlvbkluc3RhbmNlQ2xhc3MgfSBmcm9tICcuL2VudW1zJztcbmltcG9ydCB7IERtc1JlcGxpY2F0aW9uSW5zdGFuY2UgfSBmcm9tICcuL3JlcGxpY2F0aW9uLWluc3RhbmNlJztcbmltcG9ydCB7IERtc1JlcGxpY2F0aW9uVGFzayB9IGZyb20gJy4vcmVwbGljYXRpb24tdGFzayc7XG5pbXBvcnQgeyBUYWJsZU1hcHBpbmdzIH0gZnJvbSAnLi90YWJsZS1tYXBwaW5ncyc7XG5pbXBvcnQgeyBUYXNrU2V0dGluZ3MgfSBmcm9tICcuL3Rhc2stc2V0dGluZ3MnO1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIFByb3BzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciB0aGUgc291cmNlIGVuZHBvaW50IG9mIGEge0BsaW5rIERtc01pZ3JhdGlvblBpcGVsaW5lfS5cbiAqIEV4dGVuZHMge0BsaW5rIERtc0VuZHBvaW50UHJvcHN9IGJ1dCBvbWl0cyBgZW5kcG9pbnRUeXBlYCAoYWx3YXlzIFNPVVJDRSkuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU291cmNlRW5kcG9pbnRPcHRpb25zIHtcbiAgcmVhZG9ubHkgZW5naW5lOiBEbXNFbmRwb2ludFByb3BzWydlbmdpbmUnXTtcbiAgcmVhZG9ubHkgZW5kcG9pbnRJZGVudGlmaWVyPzogc3RyaW5nO1xuICByZWFkb25seSBzZXJ2ZXJOYW1lPzogc3RyaW5nO1xuICByZWFkb25seSBwb3J0PzogbnVtYmVyO1xuICByZWFkb25seSB1c2VybmFtZT86IHN0cmluZztcbiAgLyoqXG4gICAqIERhdGFiYXNlIHBhc3N3b3JkLiBUaGUgcmVzb2x2ZWQgdmFsdWUgaXMgc3RvcmVkIGFzICoqcGxhaW50ZXh0KiogaW4gdGhlXG4gICAqIENsb3VkRm9ybWF0aW9uIHRlbXBsYXRlLiBQcmVmZXIgYHNlY3JldHNNYW5hZ2VyU2VjcmV0SWRgIGluIHRoZVxuICAgKiBlbmdpbmUtc3BlY2lmaWMgc2V0dGluZ3MgZm9yIHByb2R1Y3Rpb24gd29ya2xvYWRzLlxuICAgKi9cbiAgcmVhZG9ubHkgcGFzc3dvcmQ/OiBjZGsuU2VjcmV0VmFsdWU7XG4gIHJlYWRvbmx5IGRhdGFiYXNlTmFtZT86IHN0cmluZztcbiAgcmVhZG9ubHkgZXh0cmFDb25uZWN0aW9uQXR0cmlidXRlcz86IHN0cmluZztcbiAgcmVhZG9ubHkgY2VydGlmaWNhdGVBcm4/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHNzbE1vZGU/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IG15U3FsU2V0dGluZ3M/OiBEbXNFbmRwb2ludFByb3BzWydteVNxbFNldHRpbmdzJ107XG4gIHJlYWRvbmx5IHBvc3RncmVTcWxTZXR0aW5ncz86IERtc0VuZHBvaW50UHJvcHNbJ3Bvc3RncmVTcWxTZXR0aW5ncyddO1xuICByZWFkb25seSBvcmFjbGVTZXR0aW5ncz86IERtc0VuZHBvaW50UHJvcHNbJ29yYWNsZVNldHRpbmdzJ107XG4gIHJlYWRvbmx5IHNxbFNlcnZlclNldHRpbmdzPzogRG1zRW5kcG9pbnRQcm9wc1snc3FsU2VydmVyU2V0dGluZ3MnXTtcbiAgcmVhZG9ubHkgc2FwQXNlU2V0dGluZ3M/OiBEbXNFbmRwb2ludFByb3BzWydzYXBBc2VTZXR0aW5ncyddO1xuICByZWFkb25seSBkYjJTZXR0aW5ncz86IERtc0VuZHBvaW50UHJvcHNbJ2RiMlNldHRpbmdzJ107XG4gIHJlYWRvbmx5IG1vbmdvRGJTZXR0aW5ncz86IERtc0VuZHBvaW50UHJvcHNbJ21vbmdvRGJTZXR0aW5ncyddO1xuICByZWFkb25seSBzM1NldHRpbmdzPzogRG1zRW5kcG9pbnRQcm9wc1snczNTZXR0aW5ncyddO1xufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIHRoZSB0YXJnZXQgZW5kcG9pbnQgb2YgYSB7QGxpbmsgRG1zTWlncmF0aW9uUGlwZWxpbmV9LlxuICogRXh0ZW5kcyB7QGxpbmsgRG1zRW5kcG9pbnRQcm9wc30gYnV0IG9taXRzIGBlbmRwb2ludFR5cGVgIChhbHdheXMgVEFSR0VUKS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUYXJnZXRFbmRwb2ludE9wdGlvbnMge1xuICByZWFkb25seSBlbmdpbmU6IERtc0VuZHBvaW50UHJvcHNbJ2VuZ2luZSddO1xuICByZWFkb25seSBlbmRwb2ludElkZW50aWZpZXI/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHNlcnZlck5hbWU/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHBvcnQ/OiBudW1iZXI7XG4gIHJlYWRvbmx5IHVzZXJuYW1lPzogc3RyaW5nO1xuICAvKipcbiAgICogRGF0YWJhc2UgcGFzc3dvcmQuIFRoZSByZXNvbHZlZCB2YWx1ZSBpcyBzdG9yZWQgYXMgKipwbGFpbnRleHQqKiBpbiB0aGVcbiAgICogQ2xvdWRGb3JtYXRpb24gdGVtcGxhdGUuIFByZWZlciBgc2VjcmV0c01hbmFnZXJTZWNyZXRJZGAgaW4gdGhlXG4gICAqIGVuZ2luZS1zcGVjaWZpYyBzZXR0aW5ncyBmb3IgcHJvZHVjdGlvbiB3b3JrbG9hZHMuXG4gICAqL1xuICByZWFkb25seSBwYXNzd29yZD86IGNkay5TZWNyZXRWYWx1ZTtcbiAgcmVhZG9ubHkgZGF0YWJhc2VOYW1lPzogc3RyaW5nO1xuICByZWFkb25seSBleHRyYUNvbm5lY3Rpb25BdHRyaWJ1dGVzPzogc3RyaW5nO1xuICByZWFkb25seSBjZXJ0aWZpY2F0ZUFybj86IHN0cmluZztcbiAgcmVhZG9ubHkgc3NsTW9kZT86IHN0cmluZztcbiAgcmVhZG9ubHkgbXlTcWxTZXR0aW5ncz86IERtc0VuZHBvaW50UHJvcHNbJ215U3FsU2V0dGluZ3MnXTtcbiAgcmVhZG9ubHkgcG9zdGdyZVNxbFNldHRpbmdzPzogRG1zRW5kcG9pbnRQcm9wc1sncG9zdGdyZVNxbFNldHRpbmdzJ107XG4gIHJlYWRvbmx5IG9yYWNsZVNldHRpbmdzPzogRG1zRW5kcG9pbnRQcm9wc1snb3JhY2xlU2V0dGluZ3MnXTtcbiAgcmVhZG9ubHkgc3FsU2VydmVyU2V0dGluZ3M/OiBEbXNFbmRwb2ludFByb3BzWydzcWxTZXJ2ZXJTZXR0aW5ncyddO1xuICByZWFkb25seSBzYXBBc2VTZXR0aW5ncz86IERtc0VuZHBvaW50UHJvcHNbJ3NhcEFzZVNldHRpbmdzJ107XG4gIHJlYWRvbmx5IGRiMlNldHRpbmdzPzogRG1zRW5kcG9pbnRQcm9wc1snZGIyU2V0dGluZ3MnXTtcbiAgcmVhZG9ubHkgbW9uZ29EYlNldHRpbmdzPzogRG1zRW5kcG9pbnRQcm9wc1snbW9uZ29EYlNldHRpbmdzJ107XG4gIHJlYWRvbmx5IHMzU2V0dGluZ3M/OiBEbXNFbmRwb2ludFByb3BzWydzM1NldHRpbmdzJ107XG4gIHJlYWRvbmx5IGR5bmFtb0RiU2V0dGluZ3M/OiBEbXNFbmRwb2ludFByb3BzWydkeW5hbW9EYlNldHRpbmdzJ107XG4gIHJlYWRvbmx5IHJlZHNoaWZ0U2V0dGluZ3M/OiBEbXNFbmRwb2ludFByb3BzWydyZWRzaGlmdFNldHRpbmdzJ107XG4gIHJlYWRvbmx5IGtpbmVzaXNTZXR0aW5ncz86IERtc0VuZHBvaW50UHJvcHNbJ2tpbmVzaXNTZXR0aW5ncyddO1xuICByZWFkb25seSBrYWZrYVNldHRpbmdzPzogRG1zRW5kcG9pbnRQcm9wc1sna2Fma2FTZXR0aW5ncyddO1xuICByZWFkb25seSBvcGVuU2VhcmNoU2V0dGluZ3M/OiBEbXNFbmRwb2ludFByb3BzWydvcGVuU2VhcmNoU2V0dGluZ3MnXTtcbiAgcmVhZG9ubHkgbmVwdHVuZVNldHRpbmdzPzogRG1zRW5kcG9pbnRQcm9wc1snbmVwdHVuZVNldHRpbmdzJ107XG4gIHJlYWRvbmx5IHJlZGlzU2V0dGluZ3M/OiBEbXNFbmRwb2ludFByb3BzWydyZWRpc1NldHRpbmdzJ107XG59XG5cbi8qKiBUb3AtbGV2ZWwgcHJvcHMgZm9yIHtAbGluayBEbXNNaWdyYXRpb25QaXBlbGluZX0uICovXG5leHBvcnQgaW50ZXJmYWNlIERtc01pZ3JhdGlvblBpcGVsaW5lUHJvcHMge1xuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIFJlcGxpY2F0aW9uIGluc3RhbmNlXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICAvKipcbiAgICogVlBDIGluIHdoaWNoIHRvIHBsYWNlIHRoZSByZXBsaWNhdGlvbiBpbnN0YW5jZS5cbiAgICogVGhlIGluc3RhbmNlIGlzIHBsYWNlZCBpbiBwcml2YXRlIHN1Ym5ldHMuXG4gICAqL1xuICByZWFkb25seSB2cGM6IGVjMi5JVnBjO1xuXG4gIC8qKlxuICAgKiBTdWJuZXQgc2VsZWN0aW9uIGZvciB0aGUgcmVwbGljYXRpb24gaW5zdGFuY2UuXG4gICAqIEBkZWZhdWx0IHByaXZhdGUgc3VibmV0cyB3aXRoIGVncmVzc1xuICAgKi9cbiAgcmVhZG9ubHkgdnBjU3VibmV0cz86IGVjMi5TdWJuZXRTZWxlY3Rpb247XG5cbiAgLyoqXG4gICAqIFJlcGxpY2F0aW9uIGluc3RhbmNlIGNsYXNzLlxuICAgKiBAZGVmYXVsdCBSZXBsaWNhdGlvbkluc3RhbmNlQ2xhc3MuUjZJX0xBUkdFXG4gICAqL1xuICByZWFkb25seSByZXBsaWNhdGlvbkluc3RhbmNlQ2xhc3M/OiBSZXBsaWNhdGlvbkluc3RhbmNlQ2xhc3M7XG5cbiAgLyoqXG4gICAqIEFsbG9jYXRlZCBzdG9yYWdlIGZvciB0aGUgcmVwbGljYXRpb24gaW5zdGFuY2UgaW4gR0IuXG4gICAqIEBkZWZhdWx0IDEwMFxuICAgKi9cbiAgcmVhZG9ubHkgYWxsb2NhdGVkU3RvcmFnZT86IG51bWJlcjtcblxuICAvKipcbiAgICogV2hldGhlciB0aGUgcmVwbGljYXRpb24gaW5zdGFuY2UgaXMgTXVsdGktQVouXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBtdWx0aUF6PzogYm9vbGVhbjtcblxuICAvKipcbiAgICogRW5naW5lIHZlcnNpb24gZm9yIHRoZSByZXBsaWNhdGlvbiBpbnN0YW5jZS5cbiAgICogQGRlZmF1bHQgbGF0ZXN0IHZlcnNpb24gYXZhaWxhYmxlIGluIHRoZSByZWdpb24gKGNob3NlbiBieSBETVMpXG4gICAqL1xuICByZWFkb25seSBlbmdpbmVWZXJzaW9uPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBLTVMga2V5IGZvciBlbmNyeXB0aW5nIHRoZSByZXBsaWNhdGlvbiBpbnN0YW5jZSBzdG9yYWdlIGF0IHJlc3QuXG4gICAqIEEgbmV3IGtleSBpcyBjcmVhdGVkIGlmIG5vdCBwcm92aWRlZC5cbiAgICovXG4gIHJlYWRvbmx5IGVuY3J5cHRpb25LZXk/OiBrbXMuSUtleTtcblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIEVuZHBvaW50c1xuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgLyoqXG4gICAqIFNvdXJjZSBlbmRwb2ludCBjb25maWd1cmF0aW9uLlxuICAgKiBQcm92aWRlIHRoaXMgT1IgYGV4aXN0aW5nU291cmNlRW5kcG9pbnRgIOKAlCBub3QgYm90aC5cbiAgICovXG4gIHJlYWRvbmx5IHNvdXJjZUVuZHBvaW50PzogU291cmNlRW5kcG9pbnRPcHRpb25zO1xuXG4gIC8qKlxuICAgKiBBbiBleGlzdGluZyB7QGxpbmsgSURtc0VuZHBvaW50fSB0byB1c2UgYXMgdGhlIHNvdXJjZS5cbiAgICogUHJvdmlkZSB0aGlzIE9SIGBzb3VyY2VFbmRwb2ludGAg4oCUIG5vdCBib3RoLlxuICAgKi9cbiAgcmVhZG9ubHkgZXhpc3RpbmdTb3VyY2VFbmRwb2ludD86IElEbXNFbmRwb2ludDtcblxuICAvKipcbiAgICogVGFyZ2V0IGVuZHBvaW50IGNvbmZpZ3VyYXRpb24uXG4gICAqIFByb3ZpZGUgdGhpcyBPUiBgZXhpc3RpbmdUYXJnZXRFbmRwb2ludGAg4oCUIG5vdCBib3RoLlxuICAgKi9cbiAgcmVhZG9ubHkgdGFyZ2V0RW5kcG9pbnQ/OiBUYXJnZXRFbmRwb2ludE9wdGlvbnM7XG5cbiAgLyoqXG4gICAqIEFuIGV4aXN0aW5nIHtAbGluayBJRG1zRW5kcG9pbnR9IHRvIHVzZSBhcyB0aGUgdGFyZ2V0LlxuICAgKiBQcm92aWRlIHRoaXMgT1IgYHRhcmdldEVuZHBvaW50YCDigJQgbm90IGJvdGguXG4gICAqL1xuICByZWFkb25seSBleGlzdGluZ1RhcmdldEVuZHBvaW50PzogSURtc0VuZHBvaW50O1xuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gUmVwbGljYXRpb24gdGFza1xuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgLyoqIFRoZSB0eXBlIG9mIG1pZ3JhdGlvbiB0byBwZXJmb3JtLiAqL1xuICByZWFkb25seSBtaWdyYXRpb25UeXBlOiBNaWdyYXRpb25UeXBlO1xuXG4gIC8qKlxuICAgKiBUYWJsZSBtYXBwaW5ncyBKU09OIHN0cmluZy5cbiAgICogVXNlIHtAbGluayBUYWJsZU1hcHBpbmdzfSB0byBidWlsZCB0aGlzLlxuICAgKiBEZWZhdWx0cyB0byBcImluY2x1ZGUgYWxsIHRhYmxlcyBpbiBhbGwgc2NoZW1hc1wiIGlmIG5vdCBwcm92aWRlZC5cbiAgICovXG4gIHJlYWRvbmx5IHRhYmxlTWFwcGluZ3M/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRhc2sgc2V0dGluZ3MgSlNPTiBzdHJpbmcuXG4gICAqIFVzZSB7QGxpbmsgVGFza1NldHRpbmdzfSB0byBidWlsZCB0aGlzLlxuICAgKiBTZW5zaWJsZSBkZWZhdWx0cyBhcmUgYXBwbGllZCBpZiBub3QgcHJvdmlkZWQuXG4gICAqL1xuICByZWFkb25seSB0YXNrU2V0dGluZ3M/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIENEQyBzdGFydCB0aW1lIChJU08tODYwMSBzdHJpbmcgb3IgVW5peCBlcG9jaCBzZWNvbmRzKS5cbiAgICogT25seSB1c2VkIHdoZW4gbWlncmF0aW9uVHlwZSBpbmNsdWRlcyBDREMuXG4gICAqL1xuICByZWFkb25seSBjZGNTdGFydFRpbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIENEQyBzdGFydCBwb3NpdGlvbiAoTFNOIG9yIGVxdWl2YWxlbnQpLlxuICAgKiBPbmx5IHVzZWQgd2hlbiBtaWdyYXRpb25UeXBlIGluY2x1ZGVzIENEQy5cbiAgICovXG4gIHJlYWRvbmx5IGNkY1N0YXJ0UG9zaXRpb24/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIENEQyBzdG9wIHBvc2l0aW9uLlxuICAgKiBPbmx5IHVzZWQgd2hlbiBtaWdyYXRpb25UeXBlIGluY2x1ZGVzIENEQy5cbiAgICovXG4gIHJlYWRvbmx5IGNkY1N0b3BQb3NpdGlvbj86IHN0cmluZztcblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIE9ic2VydmFiaWxpdHlcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGNyZWF0ZSBhIENsb3VkV2F0Y2ggbG9nIGdyb3VwIGZvciB0aGUgdGFzay5cbiAgICogQGRlZmF1bHQgdHJ1ZVxuICAgKi9cbiAgcmVhZG9ubHkgZW5hYmxlQ2xvdWRXYXRjaExvZ3M/OiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBSZXRlbnRpb24gcGVyaW9kIGZvciB0aGUgQ2xvdWRXYXRjaCBsb2cgZ3JvdXAuXG4gICAqIEBkZWZhdWx0IGxvZ3MuUmV0ZW50aW9uRGF5cy5PTkVfTU9OVEhcbiAgICovXG4gIHJlYWRvbmx5IGxvZ1JldGVudGlvbj86IGxvZ3MuUmV0ZW50aW9uRGF5cztcblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIElBTSAvIHNlcnZpY2Ugcm9sZXNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIC8qKlxuICAgKiBXaGV0aGVyIHRvIGNyZWF0ZSB0aGUgdHdvIGFjY291bnQtbGV2ZWwgRE1TIHNlcnZpY2Ugcm9sZXMgKGBkbXMtdnBjLXJvbGVgXG4gICAqIGFuZCBgZG1zLWNsb3Vkd2F0Y2gtbG9ncy1yb2xlYCkgcmVxdWlyZWQgYnkgRE1TLlxuICAgKlxuICAgKiBTZXQgdGhpcyB0byBgZmFsc2VgIGlmIHRoZSByb2xlcyBhbHJlYWR5IGV4aXN0IGluIHRoZSBBV1MgYWNjb3VudCDigJQgZm9yXG4gICAqIGV4YW1wbGUsIGJlY2F1c2UgYW5vdGhlciBDREsgc3RhY2sgKG9yIGEgbWFudWFsIGRlcGxveW1lbnQpIGFscmVhZHlcbiAgICogY3JlYXRlZCB0aGVtLiBBdHRlbXB0aW5nIHRvIGNyZWF0ZSByb2xlcyB3aXRoIHRoZSBzYW1lIG5hbWUgdHdpY2UgaW4gdGhlXG4gICAqIHNhbWUgYWNjb3VudCBjYXVzZXMgYSBDbG91ZEZvcm1hdGlvbiBgRW50aXR5QWxyZWFkeUV4aXN0c2AgZXJyb3IuXG4gICAqXG4gICAqIFdoZW4gYGZhbHNlYCwgdGhlIGNvbnN0cnVjdCBleHBlY3RzIHRoZSByb2xlcyB0byBhbHJlYWR5IGJlIHByZXNlbnQgYW5kXG4gICAqIHNraXBzIGNyZWF0aW5nIHRoZW0uIFRoZSBgZG1zVnBjUm9sZWAgYW5kIGBkbXNDbG91ZFdhdGNoUm9sZWAgcHJvcGVydGllc1xuICAgKiB3aWxsIGJlIGB1bmRlZmluZWRgLlxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBjcmVhdGVEbXNTZXJ2aWNlUm9sZXM/OiBib29sZWFuO1xuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gTGlmZWN5Y2xlXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICAvKipcbiAgICogUmVtb3ZhbCBwb2xpY3kgYXBwbGllZCB0byBhbGwgcmVzb3VyY2VzIGluIHRoZSBwaXBlbGluZS5cbiAgICogQGRlZmF1bHQgY2RrLlJlbW92YWxQb2xpY3kuREVTVFJPWVxuICAgKi9cbiAgcmVhZG9ubHkgcmVtb3ZhbFBvbGljeT86IGNkay5SZW1vdmFsUG9saWN5O1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIENvbnN0cnVjdFxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogQW4gTDMgQ0RLIHBhdHRlcm4gY29uc3RydWN0IHRoYXQgcHJvdmlzaW9ucyBhIGNvbXBsZXRlIERNUyBtaWdyYXRpb24gcGlwZWxpbmU6XG4gKlxuICogLSAqKlJlcGxpY2F0aW9uIGluc3RhbmNlKiog4oCUIHBsYWNlZCBpbiBwcml2YXRlIHN1Ym5ldHMgd2l0aCBLTVMgZW5jcnlwdGlvblxuICogICBhbmQgYSBkZWRpY2F0ZWQgc2VjdXJpdHkgZ3JvdXAuXG4gKiAtICoqU291cmNlIGVuZHBvaW50Kiog4oCUIHN1cHBvcnRzIGV2ZXJ5IGVuZ2luZSBETVMgc3VwcG9ydHMuXG4gKiAtICoqVGFyZ2V0IGVuZHBvaW50Kiog4oCUIHN1cHBvcnRzIGV2ZXJ5IGVuZ2luZSBETVMgc3VwcG9ydHMuXG4gKiAtICoqUmVwbGljYXRpb24gdGFzayoqIOKAlCB3aXJlcyB0aGUgaW5zdGFuY2UsIGVuZHBvaW50cywgdGFibGUgbWFwcGluZ3MgYW5kXG4gKiAgIHRhc2sgc2V0dGluZ3MgdG9nZXRoZXIuXG4gKiAtICoqSUFNIHJvbGUqKiDigJQgZ3JhbnRzIERNUyBwZXJtaXNzaW9uIHRvIHdyaXRlIHRvIENsb3VkV2F0Y2ggTG9ncy5cbiAqIC0gKipDbG91ZFdhdGNoIGxvZyBncm91cCoqIOKAlCAob3B0aW9uYWwpIHJldGFpbnMgdGFzayBsb2dzLlxuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBNeVNRTCDihpIgQXVyb3JhIFBvc3RncmVTUUwsIGZ1bGwtbG9hZC1hbmQtQ0RDXG4gKiBjb25zdCBwaXBlbGluZSA9IG5ldyBEbXNNaWdyYXRpb25QaXBlbGluZSh0aGlzLCAnTWlncmF0aW9uUGlwZWxpbmUnLCB7XG4gKiAgIHZwYyxcbiAqICAgbWlncmF0aW9uVHlwZTogTWlncmF0aW9uVHlwZS5GVUxMX0xPQURfQU5EX0NEQyxcbiAqICAgc291cmNlRW5kcG9pbnQ6IHtcbiAqICAgICBlbmdpbmU6IEVuZHBvaW50RW5naW5lLk1ZU1FMLFxuICogICAgIHNlcnZlck5hbWU6ICdteXNxbC5leGFtcGxlLmNvbScsXG4gKiAgICAgcG9ydDogMzMwNixcbiAqICAgICB1c2VybmFtZTogJ2Rtc191c2VyJyxcbiAqICAgICBwYXNzd29yZDogY2RrLlNlY3JldFZhbHVlLnNlY3JldHNNYW5hZ2VyKCdteXNxbC1kbXMtc2VjcmV0JyksXG4gKiAgICAgZGF0YWJhc2VOYW1lOiAnbXlkYicsXG4gKiAgIH0sXG4gKiAgIHRhcmdldEVuZHBvaW50OiB7XG4gKiAgICAgZW5naW5lOiBFbmRwb2ludEVuZ2luZS5BVVJPUkFfUE9TVEdSRVNRTCxcbiAqICAgICBzZXJ2ZXJOYW1lOiBjbHVzdGVyLmNsdXN0ZXJFbmRwb2ludC5ob3N0bmFtZSxcbiAqICAgICBwb3J0OiA1NDMyLFxuICogICAgIHVzZXJuYW1lOiAnZG1zX3VzZXInLFxuICogICAgIHBhc3N3b3JkOiBjZGsuU2VjcmV0VmFsdWUuc2VjcmV0c01hbmFnZXIoJ2F1cm9yYS1kbXMtc2VjcmV0JyksXG4gKiAgICAgZGF0YWJhc2VOYW1lOiAnbXlkYicsXG4gKiAgIH0sXG4gKiAgIHRhYmxlTWFwcGluZ3M6IG5ldyBUYWJsZU1hcHBpbmdzKCkuaW5jbHVkZVNjaGVtYSgncHVibGljJykudG9Kc29uKCksXG4gKiB9KTtcbiAqL1xuZXhwb3J0IGNsYXNzIERtc01pZ3JhdGlvblBpcGVsaW5lIGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIEluc3RhbmNlIGZpZWxkc1xuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICAvKiogVGhlIHJlcGxpY2F0aW9uIGluc3RhbmNlIHByb3Zpc2lvbmVkIGJ5IHRoaXMgcGlwZWxpbmUuICovXG4gIHJlYWRvbmx5IHJlcGxpY2F0aW9uSW5zdGFuY2U6IERtc1JlcGxpY2F0aW9uSW5zdGFuY2U7XG5cbiAgLyoqIFRoZSBzb3VyY2UgZW5kcG9pbnQgdXNlZCBieSB0aGlzIHBpcGVsaW5lLiAqL1xuICByZWFkb25seSBzb3VyY2U6IElEbXNFbmRwb2ludDtcblxuICAvKiogVGhlIHRhcmdldCBlbmRwb2ludCB1c2VkIGJ5IHRoaXMgcGlwZWxpbmUuICovXG4gIHJlYWRvbmx5IHRhcmdldDogSURtc0VuZHBvaW50O1xuXG4gIC8qKiBUaGUgcmVwbGljYXRpb24gdGFzayB0aGF0IGRyaXZlcyB0aGUgbWlncmF0aW9uLiAqL1xuICByZWFkb25seSByZXBsaWNhdGlvblRhc2s6IERtc1JlcGxpY2F0aW9uVGFzaztcblxuICAvKiogQ2xvdWRXYXRjaCBsb2cgZ3JvdXAgZm9yIHRoZSB0YXNrIChpZiBlbmFibGVDbG91ZFdhdGNoTG9ncyBpcyB0cnVlKS4gKi9cbiAgcmVhZG9ubHkgbG9nR3JvdXA/OiBsb2dzLkxvZ0dyb3VwO1xuXG4gIC8qKlxuICAgKiBJQU0gcm9sZSB0aGF0IGFsbG93cyBETVMgdG8gd3JpdGUgdG8gQ2xvdWRXYXRjaCBMb2dzLlxuICAgKiBgdW5kZWZpbmVkYCB3aGVuIGBjcmVhdGVEbXNTZXJ2aWNlUm9sZXNgIGlzIGBmYWxzZWAuXG4gICAqL1xuICByZWFkb25seSBkbXNDbG91ZFdhdGNoUm9sZT86IGlhbS5Sb2xlO1xuXG4gIC8qKlxuICAgKiBJQU0gcm9sZSB0aGF0IGFsbG93cyBETVMgdG8gbWFuYWdlIFZQQyByZXNvdXJjZXMgKGRtcy12cGMtcm9sZSkuXG4gICAqIGB1bmRlZmluZWRgIHdoZW4gYGNyZWF0ZURtc1NlcnZpY2VSb2xlc2AgaXMgYGZhbHNlYC5cbiAgICovXG4gIHJlYWRvbmx5IGRtc1ZwY1JvbGU/OiBpYW0uUm9sZTtcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogRG1zTWlncmF0aW9uUGlwZWxpbmVQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICB0aGlzLnZhbGlkYXRlUHJvcHMocHJvcHMpO1xuXG4gICAgY29uc3QgcmVtb3ZhbFBvbGljeSA9IHByb3BzLnJlbW92YWxQb2xpY3kgPz8gY2RrLlJlbW92YWxQb2xpY3kuREVTVFJPWTtcbiAgICBjb25zdCBjcmVhdGVSb2xlcyA9IHByb3BzLmNyZWF0ZURtc1NlcnZpY2VSb2xlcyA/PyB0cnVlO1xuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBkbXMtdnBjLXJvbGUg4oCUIGFjY291bnQtbGV2ZWwgc2luZ2xldG9uIHJlcXVpcmVkIGJ5IERNUyB0byBwbGFjZVxuICAgIC8vIHJlcGxpY2F0aW9uIGluc3RhbmNlcyBpbnNpZGUgYSBWUEMuIE11c3QgZXhpc3QgYmVmb3JlIHRoZSBmaXJzdFxuICAgIC8vIENmblJlcGxpY2F0aW9uSW5zdGFuY2UgaXMgY3JlYXRlZCBpbiB0aGUgYWNjb3VudC5cbiAgICAvLyBTa2lwIHdoZW4gY3JlYXRlRG1zU2VydmljZVJvbGVzIGlzIGZhbHNlIChyb2xlcyBhbHJlYWR5IGV4aXN0KS5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIGlmIChjcmVhdGVSb2xlcykge1xuICAgICAgdGhpcy5kbXNWcGNSb2xlID0gZW5zdXJlRG1zVnBjUm9sZShjZGsuU3RhY2sub2YodGhpcykpO1xuICAgIH1cblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gQ2xvdWRXYXRjaCBsb2cgZ3JvdXAgJiBJQU0gcm9sZVxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgY29uc3QgZW5hYmxlTG9ncyA9IHByb3BzLmVuYWJsZUNsb3VkV2F0Y2hMb2dzID8/IHRydWU7XG5cbiAgICBpZiAoZW5hYmxlTG9ncykge1xuICAgICAgdGhpcy5sb2dHcm91cCA9IG5ldyBsb2dzLkxvZ0dyb3VwKHRoaXMsICdUYXNrTG9nR3JvdXAnLCB7XG4gICAgICAgIGxvZ0dyb3VwTmFtZTogYC9hd3MvZG1zL3Rhc2tzLyR7aWR9YCxcbiAgICAgICAgcmV0ZW50aW9uOiBwcm9wcy5sb2dSZXRlbnRpb24gPz8gbG9ncy5SZXRlbnRpb25EYXlzLk9ORV9NT05USCxcbiAgICAgICAgcmVtb3ZhbFBvbGljeSxcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoY3JlYXRlUm9sZXMpIHtcbiAgICAgICAgLy8gZG1zLWNsb3Vkd2F0Y2gtbG9ncy1yb2xlIGlzIGFuIGFjY291bnQtbGV2ZWwgc2luZ2xldG9uIOKAlCBETVMgcmVxdWlyZXNcbiAgICAgICAgLy8gdGhpcyBleGFjdCBuYW1lLiBHdWFyZCB3aXRoIGEgc3RhY2stbGV2ZWwgc2luZ2xldG9uIHNvIGRlcGxveWluZyBtdWx0aXBsZVxuICAgICAgICAvLyBwaXBlbGluZXMgaW4gdGhlIHNhbWUgc3RhY2sgZG9lc24ndCBjcmVhdGUgZHVwbGljYXRlIHJvbGVzLlxuICAgICAgICB0aGlzLmRtc0Nsb3VkV2F0Y2hSb2xlID0gZW5zdXJlRG1zQ2xvdWRXYXRjaFJvbGUoY2RrLlN0YWNrLm9mKHRoaXMpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIFJlcGxpY2F0aW9uIGluc3RhbmNlXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICB0aGlzLnJlcGxpY2F0aW9uSW5zdGFuY2UgPSBuZXcgRG1zUmVwbGljYXRpb25JbnN0YW5jZSh0aGlzLCAnUmVwbGljYXRpb25JbnN0YW5jZScsIHtcbiAgICAgIHZwYzogcHJvcHMudnBjLFxuICAgICAgdnBjU3VibmV0czogcHJvcHMudnBjU3VibmV0cyxcbiAgICAgIHJlcGxpY2F0aW9uSW5zdGFuY2VDbGFzczogcHJvcHMucmVwbGljYXRpb25JbnN0YW5jZUNsYXNzLFxuICAgICAgYWxsb2NhdGVkU3RvcmFnZTogcHJvcHMuYWxsb2NhdGVkU3RvcmFnZSxcbiAgICAgIG11bHRpQXo6IHByb3BzLm11bHRpQXosXG4gICAgICBlbmdpbmVWZXJzaW9uOiBwcm9wcy5lbmdpbmVWZXJzaW9uLFxuICAgICAga21zS2V5OiBwcm9wcy5lbmNyeXB0aW9uS2V5LFxuICAgICAgcmVtb3ZhbFBvbGljeSxcbiAgICB9KTtcbiAgICAvLyBUaGUgcmVwbGljYXRpb24gaW5zdGFuY2UgY2Fubm90IGJlIHBsYWNlZCBpbiBhIFZQQyB1bnRpbCBkbXMtdnBjLXJvbGUgZXhpc3RzLlxuICAgIC8vIE9ubHkgYWRkIHRoZSBkZXBlbmRlbmN5IHdoZW4gd2UgY3JlYXRlZCB0aGUgcm9sZSBvdXJzZWx2ZXMuXG4gICAgaWYgKHRoaXMuZG1zVnBjUm9sZSkge1xuICAgICAgdGhpcy5yZXBsaWNhdGlvbkluc3RhbmNlLmNmblJlcGxpY2F0aW9uSW5zdGFuY2UuYWRkRGVwZW5kZW5jeShcbiAgICAgICAgdGhpcy5kbXNWcGNSb2xlLm5vZGUuZGVmYXVsdENoaWxkIGFzIGNkay5DZm5SZXNvdXJjZSxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBTb3VyY2UgZW5kcG9pbnRcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIGlmIChwcm9wcy5leGlzdGluZ1NvdXJjZUVuZHBvaW50KSB7XG4gICAgICB0aGlzLnNvdXJjZSA9IHByb3BzLmV4aXN0aW5nU291cmNlRW5kcG9pbnQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHNvdXJjZU9wdHMgPSBwcm9wcy5zb3VyY2VFbmRwb2ludCE7XG4gICAgICB0aGlzLnNvdXJjZSA9IG5ldyBEbXNFbmRwb2ludCh0aGlzLCAnU291cmNlRW5kcG9pbnQnLCB7XG4gICAgICAgIGVuZHBvaW50VHlwZTogRW5kcG9pbnRUeXBlLlNPVVJDRSxcbiAgICAgICAgZW5naW5lOiBzb3VyY2VPcHRzLmVuZ2luZSxcbiAgICAgICAgZW5kcG9pbnRJZGVudGlmaWVyOiBzb3VyY2VPcHRzLmVuZHBvaW50SWRlbnRpZmllcixcbiAgICAgICAgc2VydmVyTmFtZTogc291cmNlT3B0cy5zZXJ2ZXJOYW1lLFxuICAgICAgICBwb3J0OiBzb3VyY2VPcHRzLnBvcnQsXG4gICAgICAgIHVzZXJuYW1lOiBzb3VyY2VPcHRzLnVzZXJuYW1lLFxuICAgICAgICBwYXNzd29yZDogc291cmNlT3B0cy5wYXNzd29yZCxcbiAgICAgICAgZGF0YWJhc2VOYW1lOiBzb3VyY2VPcHRzLmRhdGFiYXNlTmFtZSxcbiAgICAgICAgZXh0cmFDb25uZWN0aW9uQXR0cmlidXRlczogc291cmNlT3B0cy5leHRyYUNvbm5lY3Rpb25BdHRyaWJ1dGVzLFxuICAgICAgICBjZXJ0aWZpY2F0ZUFybjogc291cmNlT3B0cy5jZXJ0aWZpY2F0ZUFybixcbiAgICAgICAgc3NsTW9kZTogc291cmNlT3B0cy5zc2xNb2RlLFxuICAgICAgICBteVNxbFNldHRpbmdzOiBzb3VyY2VPcHRzLm15U3FsU2V0dGluZ3MsXG4gICAgICAgIHBvc3RncmVTcWxTZXR0aW5nczogc291cmNlT3B0cy5wb3N0Z3JlU3FsU2V0dGluZ3MsXG4gICAgICAgIG9yYWNsZVNldHRpbmdzOiBzb3VyY2VPcHRzLm9yYWNsZVNldHRpbmdzLFxuICAgICAgICBzcWxTZXJ2ZXJTZXR0aW5nczogc291cmNlT3B0cy5zcWxTZXJ2ZXJTZXR0aW5ncyxcbiAgICAgICAgc2FwQXNlU2V0dGluZ3M6IHNvdXJjZU9wdHMuc2FwQXNlU2V0dGluZ3MsXG4gICAgICAgIGRiMlNldHRpbmdzOiBzb3VyY2VPcHRzLmRiMlNldHRpbmdzLFxuICAgICAgICBtb25nb0RiU2V0dGluZ3M6IHNvdXJjZU9wdHMubW9uZ29EYlNldHRpbmdzLFxuICAgICAgICBzM1NldHRpbmdzOiBzb3VyY2VPcHRzLnMzU2V0dGluZ3MsXG4gICAgICAgIHJlbW92YWxQb2xpY3ksXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIFRhcmdldCBlbmRwb2ludFxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgaWYgKHByb3BzLmV4aXN0aW5nVGFyZ2V0RW5kcG9pbnQpIHtcbiAgICAgIHRoaXMudGFyZ2V0ID0gcHJvcHMuZXhpc3RpbmdUYXJnZXRFbmRwb2ludDtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgdGFyZ2V0T3B0cyA9IHByb3BzLnRhcmdldEVuZHBvaW50ITtcbiAgICAgIHRoaXMudGFyZ2V0ID0gbmV3IERtc0VuZHBvaW50KHRoaXMsICdUYXJnZXRFbmRwb2ludCcsIHtcbiAgICAgICAgZW5kcG9pbnRUeXBlOiBFbmRwb2ludFR5cGUuVEFSR0VULFxuICAgICAgICBlbmdpbmU6IHRhcmdldE9wdHMuZW5naW5lLFxuICAgICAgICBlbmRwb2ludElkZW50aWZpZXI6IHRhcmdldE9wdHMuZW5kcG9pbnRJZGVudGlmaWVyLFxuICAgICAgICBzZXJ2ZXJOYW1lOiB0YXJnZXRPcHRzLnNlcnZlck5hbWUsXG4gICAgICAgIHBvcnQ6IHRhcmdldE9wdHMucG9ydCxcbiAgICAgICAgdXNlcm5hbWU6IHRhcmdldE9wdHMudXNlcm5hbWUsXG4gICAgICAgIHBhc3N3b3JkOiB0YXJnZXRPcHRzLnBhc3N3b3JkLFxuICAgICAgICBkYXRhYmFzZU5hbWU6IHRhcmdldE9wdHMuZGF0YWJhc2VOYW1lLFxuICAgICAgICBleHRyYUNvbm5lY3Rpb25BdHRyaWJ1dGVzOiB0YXJnZXRPcHRzLmV4dHJhQ29ubmVjdGlvbkF0dHJpYnV0ZXMsXG4gICAgICAgIGNlcnRpZmljYXRlQXJuOiB0YXJnZXRPcHRzLmNlcnRpZmljYXRlQXJuLFxuICAgICAgICBzc2xNb2RlOiB0YXJnZXRPcHRzLnNzbE1vZGUsXG4gICAgICAgIG15U3FsU2V0dGluZ3M6IHRhcmdldE9wdHMubXlTcWxTZXR0aW5ncyxcbiAgICAgICAgcG9zdGdyZVNxbFNldHRpbmdzOiB0YXJnZXRPcHRzLnBvc3RncmVTcWxTZXR0aW5ncyxcbiAgICAgICAgb3JhY2xlU2V0dGluZ3M6IHRhcmdldE9wdHMub3JhY2xlU2V0dGluZ3MsXG4gICAgICAgIHNxbFNlcnZlclNldHRpbmdzOiB0YXJnZXRPcHRzLnNxbFNlcnZlclNldHRpbmdzLFxuICAgICAgICBzYXBBc2VTZXR0aW5nczogdGFyZ2V0T3B0cy5zYXBBc2VTZXR0aW5ncyxcbiAgICAgICAgZGIyU2V0dGluZ3M6IHRhcmdldE9wdHMuZGIyU2V0dGluZ3MsXG4gICAgICAgIG1vbmdvRGJTZXR0aW5nczogdGFyZ2V0T3B0cy5tb25nb0RiU2V0dGluZ3MsXG4gICAgICAgIHMzU2V0dGluZ3M6IHRhcmdldE9wdHMuczNTZXR0aW5ncyxcbiAgICAgICAgZHluYW1vRGJTZXR0aW5nczogdGFyZ2V0T3B0cy5keW5hbW9EYlNldHRpbmdzLFxuICAgICAgICByZWRzaGlmdFNldHRpbmdzOiB0YXJnZXRPcHRzLnJlZHNoaWZ0U2V0dGluZ3MsXG4gICAgICAgIGtpbmVzaXNTZXR0aW5nczogdGFyZ2V0T3B0cy5raW5lc2lzU2V0dGluZ3MsXG4gICAgICAgIGthZmthU2V0dGluZ3M6IHRhcmdldE9wdHMua2Fma2FTZXR0aW5ncyxcbiAgICAgICAgb3BlblNlYXJjaFNldHRpbmdzOiB0YXJnZXRPcHRzLm9wZW5TZWFyY2hTZXR0aW5ncyxcbiAgICAgICAgbmVwdHVuZVNldHRpbmdzOiB0YXJnZXRPcHRzLm5lcHR1bmVTZXR0aW5ncyxcbiAgICAgICAgcmVkaXNTZXR0aW5nczogdGFyZ2V0T3B0cy5yZWRpc1NldHRpbmdzLFxuICAgICAgICByZW1vdmFsUG9saWN5LFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBUYWJsZSBtYXBwaW5ncyDigJQgZGVmYXVsdCB0byBcImluY2x1ZGUgZXZlcnl0aGluZ1wiXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBjb25zdCB0YWJsZU1hcHBpbmdzID1cbiAgICAgIHByb3BzLnRhYmxlTWFwcGluZ3MgPz8gbmV3IFRhYmxlTWFwcGluZ3MoKS5pbmNsdWRlU2NoZW1hKCclJykudG9Kc29uKCk7XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIFJlcGxpY2F0aW9uIHRhc2tcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIHRoaXMucmVwbGljYXRpb25UYXNrID0gbmV3IERtc1JlcGxpY2F0aW9uVGFzayh0aGlzLCAnUmVwbGljYXRpb25UYXNrJywge1xuICAgICAgcmVwbGljYXRpb25JbnN0YW5jZUFybjogdGhpcy5yZXBsaWNhdGlvbkluc3RhbmNlLnJlcGxpY2F0aW9uSW5zdGFuY2VBcm4sXG4gICAgICBzb3VyY2VFbmRwb2ludDogdGhpcy5zb3VyY2UsXG4gICAgICB0YXJnZXRFbmRwb2ludDogdGhpcy50YXJnZXQsXG4gICAgICBtaWdyYXRpb25UeXBlOiBwcm9wcy5taWdyYXRpb25UeXBlLFxuICAgICAgdGFibGVNYXBwaW5ncyxcbiAgICAgIHRhc2tTZXR0aW5nczogcHJvcHMudGFza1NldHRpbmdzLFxuICAgICAgY2RjU3RhcnRUaW1lOiBwcm9wcy5jZGNTdGFydFRpbWUsXG4gICAgICBjZGNTdGFydFBvc2l0aW9uOiBwcm9wcy5jZGNTdGFydFBvc2l0aW9uLFxuICAgICAgY2RjU3RvcFBvc2l0aW9uOiBwcm9wcy5jZGNTdG9wUG9zaXRpb24sXG4gICAgICByZW1vdmFsUG9saWN5LFxuICAgIH0pO1xuXG4gIH1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gUHJpdmF0ZSBoZWxwZXJzXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIHByaXZhdGUgdmFsaWRhdGVQcm9wcyhwcm9wczogRG1zTWlncmF0aW9uUGlwZWxpbmVQcm9wcyk6IHZvaWQge1xuICAgIGNvbnN0IGhhc1NvdXJjZSA9ICEhcHJvcHMuc291cmNlRW5kcG9pbnQ7XG4gICAgY29uc3QgaGFzRXhpc3RpbmdTb3VyY2UgPSAhIXByb3BzLmV4aXN0aW5nU291cmNlRW5kcG9pbnQ7XG4gICAgaWYgKGhhc1NvdXJjZSAmJiBoYXNFeGlzdGluZ1NvdXJjZSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnUHJvdmlkZSBlaXRoZXIgYHNvdXJjZUVuZHBvaW50YCBvciBgZXhpc3RpbmdTb3VyY2VFbmRwb2ludGAsIG5vdCBib3RoLicsXG4gICAgICApO1xuICAgIH1cbiAgICBpZiAoIWhhc1NvdXJjZSAmJiAhaGFzRXhpc3RpbmdTb3VyY2UpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgJ09uZSBvZiBgc291cmNlRW5kcG9pbnRgIG9yIGBleGlzdGluZ1NvdXJjZUVuZHBvaW50YCBpcyByZXF1aXJlZC4nLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBjb25zdCBoYXNUYXJnZXQgPSAhIXByb3BzLnRhcmdldEVuZHBvaW50O1xuICAgIGNvbnN0IGhhc0V4aXN0aW5nVGFyZ2V0ID0gISFwcm9wcy5leGlzdGluZ1RhcmdldEVuZHBvaW50O1xuICAgIGlmIChoYXNUYXJnZXQgJiYgaGFzRXhpc3RpbmdUYXJnZXQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgJ1Byb3ZpZGUgZWl0aGVyIGB0YXJnZXRFbmRwb2ludGAgb3IgYGV4aXN0aW5nVGFyZ2V0RW5kcG9pbnRgLCBub3QgYm90aC4nLFxuICAgICAgKTtcbiAgICB9XG4gICAgaWYgKCFoYXNUYXJnZXQgJiYgIWhhc0V4aXN0aW5nVGFyZ2V0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICdPbmUgb2YgYHRhcmdldEVuZHBvaW50YCBvciBgZXhpc3RpbmdUYXJnZXRFbmRwb2ludGAgaXMgcmVxdWlyZWQuJyxcbiAgICAgICk7XG4gICAgfVxuICB9XG59XG4iXX0=
@@ -0,0 +1,99 @@
1
+ import * as cdk from 'aws-cdk-lib';
2
+ import * as dms from 'aws-cdk-lib/aws-dms';
3
+ import * as ec2 from 'aws-cdk-lib/aws-ec2';
4
+ import * as kms from 'aws-cdk-lib/aws-kms';
5
+ import { Construct } from 'constructs';
6
+ import { ReplicationInstanceClass } from './enums';
7
+ /** Props for {@link DmsReplicationInstance}. */
8
+ export interface DmsReplicationInstanceProps {
9
+ /**
10
+ * Instance class for the replication instance.
11
+ * @default ReplicationInstanceClass.R6I_LARGE
12
+ */
13
+ readonly replicationInstanceClass?: ReplicationInstanceClass;
14
+ /**
15
+ * VPC in which to place the replication instance.
16
+ * The construct creates a dedicated subnet group from the private subnets.
17
+ */
18
+ readonly vpc: ec2.IVpc;
19
+ /**
20
+ * Specific subnets to use for the replication subnet group.
21
+ * Defaults to all private subnets in the VPC.
22
+ */
23
+ readonly vpcSubnets?: ec2.SubnetSelection;
24
+ /**
25
+ * Security groups to attach to the replication instance.
26
+ * A new security group is created if none are provided.
27
+ */
28
+ readonly securityGroups?: ec2.ISecurityGroup[];
29
+ /**
30
+ * KMS key used to encrypt the replication instance storage at rest.
31
+ * A new key is created if not provided.
32
+ */
33
+ readonly kmsKey?: kms.IKey;
34
+ /**
35
+ * Allocated storage in GB.
36
+ * @default 100
37
+ */
38
+ readonly allocatedStorage?: number;
39
+ /**
40
+ * Whether the replication instance is Multi-AZ.
41
+ * @default false
42
+ */
43
+ readonly multiAz?: boolean;
44
+ /**
45
+ * Whether the replication instance is publicly accessible.
46
+ * Setting this to true is strongly discouraged for production workloads.
47
+ * @default false
48
+ */
49
+ readonly publiclyAccessible?: boolean;
50
+ /**
51
+ * Whether to allow minor version upgrades to be applied automatically during maintenance.
52
+ * @default true
53
+ */
54
+ readonly autoMinorVersionUpgrade?: boolean;
55
+ /**
56
+ * Preferred maintenance window, e.g. "sun:04:00-sun:04:30".
57
+ */
58
+ readonly preferredMaintenanceWindow?: string;
59
+ /**
60
+ * Replication engine version.
61
+ * @default latest version available in the region (chosen by DMS)
62
+ */
63
+ readonly engineVersion?: string;
64
+ /**
65
+ * Logical name of the replication instance.
66
+ * Used in the replication instance identifier and resource naming.
67
+ * @default id of the construct
68
+ */
69
+ readonly replicationInstanceIdentifier?: string;
70
+ /**
71
+ * Removal policy applied to the replication instance.
72
+ * @default cdk.RemovalPolicy.DESTROY
73
+ */
74
+ readonly removalPolicy?: cdk.RemovalPolicy;
75
+ }
76
+ /**
77
+ * An L2-style construct that provisions a DMS replication instance with:
78
+ * - Private subnet placement via a dedicated subnet group
79
+ * - KMS encryption at rest (key created if not provided)
80
+ * - A dedicated security group (created if not provided)
81
+ */
82
+ export declare class DmsReplicationInstance extends Construct {
83
+ /** The underlying CloudFormation replication instance resource. */
84
+ readonly cfnReplicationInstance: dms.CfnReplicationInstance;
85
+ /** The replication subnet group created for this instance. */
86
+ readonly subnetGroup: dms.CfnReplicationSubnetGroup;
87
+ /** The KMS key used for storage encryption. */
88
+ readonly encryptionKey: kms.IKey;
89
+ /** The security group attached to this instance. */
90
+ readonly securityGroup: ec2.ISecurityGroup;
91
+ /** The replication instance ARN. */
92
+ readonly replicationInstanceArn: string;
93
+ constructor(scope: Construct, id: string, props: DmsReplicationInstanceProps);
94
+ /**
95
+ * Allow inbound access to the replication instance on a given port from a peer.
96
+ * Useful when the source or target database security group needs to trust the instance.
97
+ */
98
+ allowInboundFrom(peer: ec2.IPeer, port: ec2.Port, description?: string): void;
99
+ }