@aws-solutions-constructs/core 2.24.0 → 2.26.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,394 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
6
+ * with the License. A copy of the License is located at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES
11
+ * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
12
+ * and limitations under the License.
13
+ */
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
16
+ const defaults = require("../index");
17
+ require("@aws-cdk/assert/jest");
18
+ const ec2 = require("aws-cdk-lib/aws-ec2");
19
+ function deployOpenSearch(stack, openSearchDomainName, clientDomainProps, lambdaRoleARN, vpc) {
20
+ const userpool = defaults.buildUserPool(stack);
21
+ const userpoolclient = defaults.buildUserPoolClient(stack, userpool, {
22
+ userPoolClientName: 'test',
23
+ userPool: userpool
24
+ });
25
+ const identitypool = defaults.buildIdentityPool(stack, userpool, userpoolclient);
26
+ const cognitoAuthorizedRole = defaults.setupCognitoForSearchService(stack, 'test-domain', {
27
+ userpool,
28
+ userpoolclient,
29
+ identitypool
30
+ });
31
+ return defaults.buildOpenSearch(stack, {
32
+ userpool,
33
+ identitypool,
34
+ cognitoAuthorizedRoleARN: cognitoAuthorizedRole.roleArn,
35
+ serviceRoleARN: lambdaRoleARN ? lambdaRoleARN : undefined,
36
+ vpc,
37
+ openSearchDomainName,
38
+ clientDomainProps
39
+ });
40
+ }
41
+ function deployStack() {
42
+ return new aws_cdk_lib_1.Stack(undefined, undefined, {
43
+ env: { account: "123456789012", region: 'us-east-1' },
44
+ });
45
+ }
46
+ test('Test override SnapshotOptions for buildOpenSearch', () => {
47
+ const stack = deployStack();
48
+ deployOpenSearch(stack, 'test-domain', {
49
+ snapshotOptions: {
50
+ automatedSnapshotStartHour: 5
51
+ }
52
+ });
53
+ expect(stack).toHaveResource('AWS::OpenSearchService::Domain', {
54
+ AccessPolicies: {
55
+ Statement: [
56
+ {
57
+ Action: "es:ESHttp*",
58
+ Effect: "Allow",
59
+ Principal: {
60
+ AWS: {
61
+ "Fn::GetAtt": [
62
+ "CognitoAuthorizedRole14E74FE0",
63
+ "Arn"
64
+ ]
65
+ }
66
+ },
67
+ Resource: {
68
+ "Fn::Join": [
69
+ "",
70
+ [
71
+ "arn:aws:es:",
72
+ {
73
+ Ref: "AWS::Region"
74
+ },
75
+ ":",
76
+ {
77
+ Ref: "AWS::AccountId"
78
+ },
79
+ ":domain/test-domain/*"
80
+ ]
81
+ ]
82
+ }
83
+ }
84
+ ],
85
+ Version: "2012-10-17"
86
+ },
87
+ CognitoOptions: {
88
+ Enabled: true,
89
+ IdentityPoolId: {
90
+ Ref: "CognitoIdentityPool"
91
+ },
92
+ RoleArn: {
93
+ "Fn::GetAtt": [
94
+ "CognitoDashboardConfigureRoleEC5F4809",
95
+ "Arn"
96
+ ]
97
+ },
98
+ UserPoolId: {
99
+ Ref: "CognitoUserPool53E37E69"
100
+ }
101
+ },
102
+ DomainName: "test-domain",
103
+ EBSOptions: {
104
+ EBSEnabled: true,
105
+ VolumeSize: 10
106
+ },
107
+ ClusterConfig: {
108
+ DedicatedMasterCount: 3,
109
+ DedicatedMasterEnabled: true,
110
+ InstanceCount: 3,
111
+ ZoneAwarenessConfig: {
112
+ AvailabilityZoneCount: 3
113
+ },
114
+ ZoneAwarenessEnabled: true
115
+ },
116
+ EngineVersion: "OpenSearch_1.3",
117
+ EncryptionAtRestOptions: {
118
+ Enabled: true
119
+ },
120
+ NodeToNodeEncryptionOptions: {
121
+ Enabled: true
122
+ },
123
+ SnapshotOptions: {
124
+ AutomatedSnapshotStartHour: 5
125
+ }
126
+ });
127
+ });
128
+ test('Test VPC with 1 AZ, Zone Awareness Disabled', () => {
129
+ const stack = deployStack();
130
+ const vpc = defaults.getTestVpc(stack, false);
131
+ deployOpenSearch(stack, 'test-domain', {
132
+ clusterConfig: {
133
+ dedicatedMasterEnabled: true,
134
+ dedicatedMasterCount: 3,
135
+ instanceCount: 3,
136
+ zoneAwarenessEnabled: false
137
+ }
138
+ }, undefined, vpc);
139
+ expect(stack).toHaveResourceLike('AWS::OpenSearchService::Domain', {
140
+ DomainName: "test-domain",
141
+ ClusterConfig: {
142
+ DedicatedMasterCount: 3,
143
+ DedicatedMasterEnabled: true,
144
+ InstanceCount: 3,
145
+ ZoneAwarenessEnabled: false
146
+ }
147
+ });
148
+ });
149
+ test('Test VPC with 2 AZ, Zone Awareness Enabled', () => {
150
+ // If no environment is specified, a VPC will use 2 AZs by default.
151
+ // If an environment is specified, a VPC will use 3 AZs by default.
152
+ const stack = new aws_cdk_lib_1.Stack(undefined, undefined, {});
153
+ const vpc = defaults.getTestVpc(stack, false);
154
+ deployOpenSearch(stack, 'test-domain', {}, undefined, vpc);
155
+ expect(stack).toHaveResourceLike('AWS::OpenSearchService::Domain', {
156
+ DomainName: "test-domain",
157
+ ClusterConfig: {
158
+ DedicatedMasterCount: 3,
159
+ DedicatedMasterEnabled: true,
160
+ InstanceCount: 2,
161
+ ZoneAwarenessEnabled: true
162
+ }
163
+ });
164
+ });
165
+ test('Test VPC with 3 AZ, Zone Awareness Enabled', () => {
166
+ // If no environment is specified, a VPC will use 2 AZs by default.
167
+ // If an environment is specified, a VPC will use 3 AZs by default.
168
+ const stack = deployStack();
169
+ const vpc = defaults.getTestVpc(stack);
170
+ deployOpenSearch(stack, 'test-domain', {}, undefined, vpc);
171
+ expect(stack).toHaveResourceLike('AWS::OpenSearchService::Domain', {
172
+ DomainName: "test-domain",
173
+ ClusterConfig: {
174
+ DedicatedMasterCount: 3,
175
+ DedicatedMasterEnabled: true,
176
+ InstanceCount: 3,
177
+ ZoneAwarenessEnabled: true
178
+ }
179
+ });
180
+ });
181
+ test('Test deployment with an existing private VPC', () => {
182
+ const stack = deployStack();
183
+ const vpc = new ec2.Vpc(stack, 'existing-private-vpc-test', {
184
+ natGateways: 1,
185
+ subnetConfiguration: [
186
+ {
187
+ cidrMask: 24,
188
+ name: 'application',
189
+ subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
190
+ },
191
+ {
192
+ cidrMask: 24,
193
+ name: "public",
194
+ subnetType: ec2.SubnetType.PUBLIC,
195
+ }
196
+ ]
197
+ });
198
+ deployOpenSearch(stack, 'test-domain', {}, undefined, vpc);
199
+ expect(stack).toHaveResourceLike('AWS::OpenSearchService::Domain', {
200
+ DomainName: "test-domain",
201
+ ClusterConfig: {
202
+ DedicatedMasterCount: 3,
203
+ DedicatedMasterEnabled: true,
204
+ InstanceCount: 3,
205
+ ZoneAwarenessEnabled: true
206
+ }
207
+ });
208
+ });
209
+ test('Test error thrown with no private subnet configurations', () => {
210
+ const stack = deployStack();
211
+ const vpc = defaults.buildVpc(stack, {
212
+ defaultVpcProps: {
213
+ subnetConfiguration: [
214
+ {
215
+ cidrMask: 18,
216
+ name: "public",
217
+ subnetType: ec2.SubnetType.PUBLIC,
218
+ }
219
+ ]
220
+ }
221
+ });
222
+ const app = () => {
223
+ deployOpenSearch(stack, 'test-domain', {}, undefined, vpc);
224
+ };
225
+ expect(app).toThrowError('Error - No isolated or private subnets available in VPC');
226
+ });
227
+ test('Test engine version override for buildOpenSearch', () => {
228
+ const stack = deployStack();
229
+ deployOpenSearch(stack, 'test-domain', {
230
+ engineVersion: 'OpenSearch_1.0'
231
+ });
232
+ expect(stack).toHaveResource('AWS::OpenSearchService::Domain', {
233
+ AccessPolicies: {
234
+ Statement: [
235
+ {
236
+ Action: "es:ESHttp*",
237
+ Effect: "Allow",
238
+ Principal: {
239
+ AWS: {
240
+ "Fn::GetAtt": [
241
+ "CognitoAuthorizedRole14E74FE0",
242
+ "Arn"
243
+ ]
244
+ }
245
+ },
246
+ Resource: {
247
+ "Fn::Join": [
248
+ "",
249
+ [
250
+ "arn:aws:es:",
251
+ {
252
+ Ref: "AWS::Region"
253
+ },
254
+ ":",
255
+ {
256
+ Ref: "AWS::AccountId"
257
+ },
258
+ ":domain/test-domain/*"
259
+ ]
260
+ ]
261
+ }
262
+ }
263
+ ],
264
+ Version: "2012-10-17"
265
+ },
266
+ CognitoOptions: {
267
+ Enabled: true,
268
+ IdentityPoolId: {
269
+ Ref: "CognitoIdentityPool"
270
+ },
271
+ RoleArn: {
272
+ "Fn::GetAtt": [
273
+ "CognitoDashboardConfigureRoleEC5F4809",
274
+ "Arn"
275
+ ]
276
+ },
277
+ UserPoolId: {
278
+ Ref: "CognitoUserPool53E37E69"
279
+ }
280
+ },
281
+ DomainName: "test-domain",
282
+ EBSOptions: {
283
+ EBSEnabled: true,
284
+ VolumeSize: 10
285
+ },
286
+ ClusterConfig: {
287
+ DedicatedMasterCount: 3,
288
+ DedicatedMasterEnabled: true,
289
+ InstanceCount: 3,
290
+ ZoneAwarenessConfig: {
291
+ AvailabilityZoneCount: 3
292
+ },
293
+ ZoneAwarenessEnabled: true
294
+ },
295
+ EngineVersion: "OpenSearch_1.0",
296
+ EncryptionAtRestOptions: {
297
+ Enabled: true
298
+ },
299
+ NodeToNodeEncryptionOptions: {
300
+ Enabled: true
301
+ },
302
+ SnapshotOptions: {
303
+ AutomatedSnapshotStartHour: 1
304
+ }
305
+ });
306
+ });
307
+ test('Test deployment with lambdaRoleARN', () => {
308
+ const stack = deployStack();
309
+ deployOpenSearch(stack, 'test-domain', {}, 'arn:aws:us-east-1:mylambdaRoleARN');
310
+ expect(stack).toHaveResource('AWS::OpenSearchService::Domain', {
311
+ AccessPolicies: {
312
+ Statement: [
313
+ {
314
+ Action: "es:ESHttp*",
315
+ Effect: "Allow",
316
+ Principal: {
317
+ AWS: [
318
+ {
319
+ "Fn::GetAtt": [
320
+ "CognitoAuthorizedRole14E74FE0",
321
+ "Arn"
322
+ ]
323
+ },
324
+ "arn:aws:us-east-1:mylambdaRoleARN"
325
+ ]
326
+ },
327
+ Resource: {
328
+ "Fn::Join": [
329
+ "",
330
+ [
331
+ "arn:aws:es:",
332
+ {
333
+ Ref: "AWS::Region"
334
+ },
335
+ ":",
336
+ {
337
+ Ref: "AWS::AccountId"
338
+ },
339
+ ":domain/test-domain/*"
340
+ ]
341
+ ]
342
+ }
343
+ }
344
+ ],
345
+ Version: "2012-10-17"
346
+ },
347
+ CognitoOptions: {
348
+ Enabled: true,
349
+ IdentityPoolId: {
350
+ Ref: "CognitoIdentityPool"
351
+ },
352
+ RoleArn: {
353
+ "Fn::GetAtt": [
354
+ "CognitoDashboardConfigureRoleEC5F4809",
355
+ "Arn"
356
+ ]
357
+ },
358
+ UserPoolId: {
359
+ Ref: "CognitoUserPool53E37E69"
360
+ }
361
+ },
362
+ DomainName: "test-domain",
363
+ EBSOptions: {
364
+ EBSEnabled: true,
365
+ VolumeSize: 10
366
+ },
367
+ ClusterConfig: {
368
+ DedicatedMasterCount: 3,
369
+ DedicatedMasterEnabled: true,
370
+ InstanceCount: 3,
371
+ ZoneAwarenessConfig: {
372
+ AvailabilityZoneCount: 3
373
+ },
374
+ ZoneAwarenessEnabled: true
375
+ },
376
+ EngineVersion: "OpenSearch_1.3",
377
+ EncryptionAtRestOptions: {
378
+ Enabled: true
379
+ },
380
+ NodeToNodeEncryptionOptions: {
381
+ Enabled: true
382
+ },
383
+ SnapshotOptions: {
384
+ AutomatedSnapshotStartHour: 1
385
+ }
386
+ });
387
+ });
388
+ test('Count OpenSearch CloudWatch alarms', () => {
389
+ const stack = new aws_cdk_lib_1.Stack();
390
+ deployOpenSearch(stack, 'test-domain');
391
+ const cwList = defaults.buildOpenSearchCWAlarms(stack);
392
+ expect(cwList.length).toEqual(9);
393
+ });
394
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlbnNlYXJjaC1oZWxwZXIudGVzdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIm9wZW5zZWFyY2gtaGVscGVyLnRlc3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7OztHQVdHOztBQUVILDZDQUFvQztBQUVwQyxxQ0FBcUM7QUFDckMsZ0NBQThCO0FBRTlCLDJDQUEyQztBQUUzQyxTQUFTLGdCQUFnQixDQUFDLEtBQVksRUFBRSxvQkFBNEIsRUFBRSxpQkFBNkMsRUFDakgsYUFBc0IsRUFBRSxHQUFjO0lBQ3RDLE1BQU0sUUFBUSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDL0MsTUFBTSxjQUFjLEdBQUcsUUFBUSxDQUFDLG1CQUFtQixDQUFDLEtBQUssRUFBRSxRQUFRLEVBQUU7UUFDbkUsa0JBQWtCLEVBQUUsTUFBTTtRQUMxQixRQUFRLEVBQUUsUUFBUTtLQUNuQixDQUFDLENBQUM7SUFFSCxNQUFNLFlBQVksR0FBRyxRQUFRLENBQUMsaUJBQWlCLENBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRSxjQUFjLENBQUMsQ0FBQztJQUNqRixNQUFNLHFCQUFxQixHQUFHLFFBQVEsQ0FBQyw0QkFBNEIsQ0FBQyxLQUFLLEVBQUUsYUFBYSxFQUFFO1FBQ3hGLFFBQVE7UUFDUixjQUFjO1FBQ2QsWUFBWTtLQUNiLENBQUMsQ0FBQztJQUVILE9BQU8sUUFBUSxDQUFDLGVBQWUsQ0FBQyxLQUFLLEVBQUU7UUFDckMsUUFBUTtRQUNSLFlBQVk7UUFDWix3QkFBd0IsRUFBRSxxQkFBcUIsQ0FBQyxPQUFPO1FBQ3ZELGNBQWMsRUFBRSxhQUFhLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsU0FBUztRQUN6RCxHQUFHO1FBQ0gsb0JBQW9CO1FBQ3BCLGlCQUFpQjtLQUNsQixDQUFDLENBQUM7QUFDTCxDQUFDO0FBRUQsU0FBUyxXQUFXO0lBQ2xCLE9BQU8sSUFBSSxtQkFBSyxDQUFD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RTtZQUMzQixPQUFPLEVBQUUsSUFBSTtTQUNkO1FBQ0QsZUFBZSxFQUFFO1lBQ2YsMEJBQTBCLEVBQUUsQ0FBQztTQUM5QjtLQUNGLENBQUMsQ0FBQztBQUVMLENBQUMsQ0FBQyxDQUFDO0FBRUgsSUFBSSxDQUFDLG9DQUFvQyxFQUFFLEdBQUcsRUFBRTtJQUM5QyxNQUFNLEtBQUssR0FBRyxJQUFJLG1CQUFLLEVBQUUsQ0FBQztJQUMxQixnQkFBZ0IsQ0FBQyxLQUFLLEVBQUUsYUFBYSxDQUFDLENBQUM7SUFDdkMsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLHVCQUF1QixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRXZELE1BQU0sQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ25DLENBQUMsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiAgQ29weXJpZ2h0IDIwMjIgQW1hem9uLmNvbSwgSW5jLiBvciBpdHMgYWZmaWxpYXRlcy4gQWxsIFJpZ2h0cyBSZXNlcnZlZC5cbiAqXG4gKiAgTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKS4gWW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZVxuICogIHdpdGggdGhlIExpY2Vuc2UuIEEgY29weSBvZiB0aGUgTGljZW5zZSBpcyBsb2NhdGVkIGF0XG4gKlxuICogICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcbiAqXG4gKiAgb3IgaW4gdGhlICdsaWNlbnNlJyBmaWxlIGFjY29tcGFueWluZyB0aGlzIGZpbGUuIFRoaXMgZmlsZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAnQVMgSVMnIEJBU0lTLCBXSVRIT1VUIFdBUlJBTlRJRVNcbiAqICBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBleHByZXNzIG9yIGltcGxpZWQuIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9uc1xuICogIGFuZCBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgeyBTdGFjayB9IGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCAqIGFzIG9wZW5zZWFyY2ggZnJvbSAnYXdzLWNkay1saWIvYXdzLW9wZW5zZWFyY2hzZXJ2aWNlJztcbmltcG9ydCAqIGFzIGRlZmF1bHRzIGZyb20gJy4uL2luZGV4JztcbmltcG9ydCAnQGF3cy1jZGsvYXNzZXJ0L2plc3QnO1xuaW1wb3J0ICogYXMgaWFtIGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuaW1wb3J0ICogYXMgZWMyIGZyb20gJ2F3cy1jZGstbGliL2F3cy1lYzInO1xuXG5mdW5jdGlvbiBkZXBsb3lPcGVuU2VhcmNoKHN0YWNrOiBTdGFjaywgb3BlblNlYXJjaERvbWFpbk5hbWU6IHN0cmluZywgY2xpZW50RG9tYWluUHJvcHM/OiBvcGVuc2VhcmNoLkNmbkRvbWFpblByb3BzLFxuICBsYW1iZGFSb2xlQVJOPzogc3RyaW5nLCB2cGM/OiBlYzIuSVZwYyk6IFtvcGVuc2VhcmNoLkNmbkRvbWFpbiwgaWFtLlJvbGVdIHtcbiAgY29uc3QgdXNlcnBvb2wgPSBkZWZhdWx0cy5idWlsZFVzZXJQb29sKHN0YWNrKTtcbiAgY29uc3QgdXNlcnBvb2xjbGllbnQgPSBkZWZhdWx0cy5idWlsZFVzZXJQb29sQ2xpZW50KHN0YWNrLCB1c2VycG9vbCwge1xuICAgIHVzZXJQb29sQ2xpZW50TmFtZTogJ3Rlc3QnLFxuICAgIHVzZXJQb29sOiB1c2VycG9vbFxuICB9KTtcblxuICBjb25zdCBpZGVudGl0eXBvb2wgPSBkZWZhdWx0cy5idWlsZElkZW50aXR5UG9vbChzdGFjaywgdXNlcnBvb2wsIHVzZXJwb29sY2xpZW50KTtcbiAgY29uc3QgY29nbml0b0F1dGhvcml6ZWRSb2xlID0gZGVmYXVsdHMuc2V0dXBDb2duaXRvRm9yU2VhcmNoU2VydmljZShzdGFjaywgJ3Rlc3QtZG9tYWluJywge1xuICAgIHVzZXJwb29sLFxuICAgIHVzZXJwb29sY2xpZW50LFxuICAgIGlkZW50aXR5cG9vbFxuICB9KTtcblxuICByZXR1cm4gZGVmYXVsdHMuYnVpbGRPcGVuU2VhcmNoKHN0YWNrLCB7XG4gICAgdXNlcnBvb2wsXG4gICAgaWRlbnRpdHlwb29sLFxuICAgIGNvZ25pdG9BdXRob3JpemVkUm9sZUFSTjogY29nbml0b0F1dGhvcml6ZWRSb2xlLnJvbGVBcm4sXG4gICAgc2VydmljZVJvbGVBUk46IGxhbWJkYVJvbGVBUk4gPyBsYW1iZGFSb2xlQVJOIDogdW5kZWZpbmVkLFxuICAgIHZwYyxcbiAgICBvcGVuU2VhcmNoRG9tYWluTmFtZSxcbiAgICBjbGllbnREb21haW5Qcm9wc1xuICB9KTtcbn1cblxuZnVuY3Rpb24gZGVwbG95U3RhY2soKSB7XG4gIHJldHVybiBuZXcgU3RhY2sodW5kZWZpbmVkLCB1bmRlZmluZWQsIHtcbiAgICBlbnY6IHsgYWNjb3VudDogXCIxMjM0NTY3ODkwMTJcIiwgcmVnaW9uOiAndXMtZWFzdC0xJyB9LFxuICB9KTtcbn1cblxudGVzdCgnVGVzdCBvdmVycmlkZSBTbmFwc2hvdE9wdGlvbnMgZm9yIGJ1aWxkT3BlblNlYXJjaCcsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBkZXBsb3lTdGFjaygpO1xuXG4gIGRlcGxveU9wZW5TZWFyY2goc3RhY2ssICd0ZXN0LWRvbWFpbicsIHtcbiAgICBzbmFwc2hvdE9wdGlvbnM6IHtcbiAgICAgIGF1dG9tYXRlZFNuYXBzaG90U3RhcnRIb3VyOiA1XG4gICAgfVxuICB9KTtcblxuICBleHBlY3Qoc3RhY2spLnRvSGF2ZVJlc291cmNlKCdBV1M6Ok9wZW5TZWFyY2hTZXJ2aWNlOjpEb21haW4nLCB7XG4gICAgQWNjZXNzUG9saWNpZXM6IHtcbiAgICAgIFN0YXRlbWVudDogW1xuICAgICAgICB7XG4gICAgICAgICAgQWN0aW9uOiBcImVzOkVTSHR0cCpcIixcbiAgICAgICAgICBFZmZlY3Q6IFwiQWxsb3dcIixcbiAgICAgICAgICBQcmluY2lwYWw6IHtcbiAgICAgICAgICAgIEFXUzoge1xuICAgICAgICAgICAgICBcIkZuOjpHZXRBdHRcIjogW1xuICAgICAgICAgICAgICAgIFwiQ29nbml0b0F1dGhvcml6ZWRSb2xlMTRFNzRGRTBcIixcbiAgICAgICAgICAgICAgICBcIkFyblwiXG4gICAgICAgICAgICAgIF1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFJlc291cmNlOiB7XG4gICAgICAgICAgICBcIkZuOjpKb2luXCI6IFtcbiAgICAgICAgICAgICAgXCJcIixcbiAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgIFwiYXJuOmF3czplczpcIixcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBSZWY6IFwiQVdTOjpSZWdpb25cIlxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgXCI6XCIsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgUmVmOiBcIkFXUzo6QWNjb3VudElkXCJcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIFwiOmRvbWFpbi90ZXN0LWRvbWFpbi8qXCJcbiAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgXVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgXSxcbiAgICAgIFZlcnNpb246IFwiMjAxMi0xMC0xN1wiXG4gICAgfSxcbiAgICBDb2duaXRvT3B0aW9uczoge1xuICAgICAgRW5hYmxlZDogdHJ1ZSxcbiAgICAgIElkZW50aXR5UG9vbElkOiB7XG4gICAgICAgIFJlZjogXCJDb2duaXRvSWRlbnRpdHlQb29sXCJcbiAgICAgIH0sXG4gICAgICBSb2xlQXJuOiB7XG4gICAgICAgIFwiRm46OkdldEF0dFwiOiBbXG4gICAgICAgICAgXCJDb2duaXRvRGFzaGJvYXJkQ29uZmlndXJlUm9sZUVDNUY0ODA5XCIsXG4gICAgICAgICAgXCJBcm5cIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgVXNlclBvb2xJZDoge1xuICAgICAgICBSZWY6IFwiQ29nbml0b1VzZXJQb29sNTNFMzdFNjlcIlxuICAgICAgfVxuICAgIH0sXG4gICAgRG9tYWluTmFtZTogXCJ0ZXN0LWRvbWFpblwiLFxuICAgIEVCU09wdGlvbnM6IHtcbiAgICAgIEVCU0VuYWJsZWQ6IHRydWUsXG4gICAgICBWb2x1bWVTaXplOiAxMFxuICAgIH0sXG4gICAgQ2x1c3RlckNvbmZpZzoge1xuICAgICAgRGVkaWNhdGVkTWFzdGVyQ291bnQ6IDMsXG4gICAgICBEZWRpY2F0ZWRNYXN0ZXJFbmFibGVkOiB0cnVlLFxuICAgICAgSW5zdGFuY2VDb3VudDogMyxcbiAgICAgIFpvbmVBd2FyZW5lc3NDb25maWc6IHtcbiAgICAgICAgQXZhaWxhYmlsaXR5Wm9uZUNvdW50OiAzXG4gICAgICB9LFxuICAgICAgWm9uZUF3YXJlbmVzc0VuYWJsZWQ6IHRydWVcbiAgICB9LFxuICAgIEVuZ2luZVZlcnNpb246IFwiT3BlblNlYXJjaF8xLjNcIixcbiAgICBFbmNyeXB0aW9uQXRSZXN0T3B0aW9uczoge1xuICAgICAgRW5hYmxlZDogdHJ1ZVxuICAgIH0sXG4gICAgTm9kZVRvTm9kZUVuY3J5cHRpb25PcHRpb25zOiB7XG4gICAgICBFbmFibGVkOiB0cnVlXG4gICAgfSxcbiAgICBTbmFwc2hvdE9wdGlvbnM6IHtcbiAgICAgIEF1dG9tYXRlZFNuYXBzaG90U3RhcnRIb3VyOiA1XG4gICAgfVxuICB9KTtcbn0pO1xuXG50ZXN0KCdUZXN0IFZQQyB3aXRoIDEgQVosIFpvbmUgQXdhcmVuZXNzIERpc2FibGVkJywgKCkgPT4ge1xuICBjb25zdCBzdGFjayA9IGRlcGxveVN0YWNrKCk7XG5cbiAgY29uc3QgdnBjID0gZGVmYXVsdHMuZ2V0VGVzdFZwYyhzdGFjaywgZmFsc2UpO1xuXG4gIGRlcGxveU9wZW5TZWFyY2goc3RhY2ssICd0ZXN0LWRvbWFpbicsIHtcbiAgICBjbHVzdGVyQ29uZmlnOiB7XG4gICAgICBkZWRpY2F0ZWRNYXN0ZXJFbmFibGVkOiB0cnVlLFxuICAgICAgZGVkaWNhdGVkTWFzdGVyQ291bnQ6IDMsXG4gICAgICBpbnN0YW5jZUNvdW50OiAzLFxuICAgICAgem9uZUF3YXJlbmVzc0VuYWJsZWQ6IGZhbHNlXG4gICAgfVxuICB9LCB1bmRlZmluZWQsIHZwYyk7XG5cbiAgZXhwZWN0KHN0YWNrKS50b0hhdmVSZXNvdXJjZUxpa2UoJ0FXUzo6T3BlblNlYXJjaFNlcnZpY2U6OkRvbWFpbicsIHtcbiAgICBEb21haW5OYW1lOiBcInRlc3QtZG9tYWluXCIsXG4gICAgQ2x1c3RlckNvbmZpZzoge1xuICAgICAgRGVkaWNhdGVkTWFzdGVyQ291bnQ6IDMsXG4gICAgICBEZWRpY2F0ZWRNYXN0ZXJFbmFibGVkOiB0cnVlLFxuICAgICAgSW5zdGFuY2VDb3VudDogMyxcbiAgICAgIFpvbmVBd2FyZW5lc3NFbmFibGVkOiBmYWxzZVxuICAgIH1cbiAgfSk7XG59KTtcblxudGVzdCgnVGVzdCBWUEMgd2l0aCAyIEFaLCBab25lIEF3YXJlbmVzcyBFbmFibGVkJywgKCkgPT4ge1xuICAvLyBJZiBubyBlbnZpcm9ubWVudCBpcyBzcGVjaWZpZWQsIGEgVlBDIHdpbGwgdXNlIDIgQVpzIGJ5IGRlZmF1bHQuXG4gIC8vIElmIGFuIGVudmlyb25tZW50IGlzIHNwZWNpZmllZCwgYSBWUEMgd2lsbCB1c2UgMyBBWnMgYnkgZGVmYXVsdC5cbiAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2sodW5kZWZpbmVkLCB1bmRlZmluZWQsIHt9KTtcblxuICBjb25zdCB2cGM6IGVjMi5JVnBjID0gZGVmYXVsdHMuZ2V0VGVzdFZwYyhzdGFjaywgZmFsc2UpO1xuXG4gIGRlcGxveU9wZW5TZWFyY2goc3RhY2ssICd0ZXN0LWRvbWFpbicsIHt9LCB1bmRlZmluZWQsIHZwYyk7XG5cbiAgZXhwZWN0KHN0YWNrKS50b0hhdmVSZXNvdXJjZUxpa2UoJ0FXUzo6T3BlblNlYXJjaFNlcnZpY2U6OkRvbWFpbicsIHtcbiAgICBEb21haW5OYW1lOiBcInRlc3QtZG9tYWluXCIsXG4gICAgQ2x1c3RlckNvbmZpZzoge1xuICAgICAgRGVkaWNhdGVkTWFzdGVyQ291bnQ6IDMsXG4gICAgICBEZWRpY2F0ZWRNYXN0ZXJFbmFibGVkOiB0cnVlLFxuICAgICAgSW5zdGFuY2VDb3VudDogMixcbiAgICAgIFpvbmVBd2FyZW5lc3NFbmFibGVkOiB0cnVlXG4gICAgfVxuICB9KTtcbn0pO1xuXG50ZXN0KCdUZXN0IFZQQyB3aXRoIDMgQVosIFpvbmUgQXdhcmVuZXNzIEVuYWJsZWQnLCAoKSA9PiB7XG4gIC8vIElmIG5vIGVudmlyb25tZW50IGlzIHNwZWNpZmllZCwgYSBWUEMgd2lsbCB1c2UgMiBBWnMgYnkgZGVmYXVsdC5cbiAgLy8gSWYgYW4gZW52aXJvbm1lbnQgaXMgc3BlY2lmaWVkLCBhIFZQQyB3aWxsIHVzZSAzIEFacyBieSBkZWZhdWx0LlxuICBjb25zdCBzdGFjayA9IGRlcGxveVN0YWNrKCk7XG5cbiAgY29uc3QgdnBjOiBlYzIuSVZwYyA9IGRlZmF1bHRzLmdldFRlc3RWcGMoc3RhY2spO1xuXG4gIGRlcGxveU9wZW5TZWFyY2goc3RhY2ssICd0ZXN0LWRvbWFpbicsIHt9LCB1bmRlZmluZWQsIHZwYyk7XG5cbiAgZXhwZWN0KHN0YWNrKS50b0hhdmVSZXNvdXJjZUxpa2UoJ0FXUzo6T3BlblNlYXJjaFNlcnZpY2U6OkRvbWFpbicsIHtcbiAgICBEb21haW5OYW1lOiBcInRlc3QtZG9tYWluXCIsXG4gICAgQ2x1c3RlckNvbmZpZzoge1xuICAgICAgRGVkaWNhdGVkTWFzdGVyQ291bnQ6IDMsXG4gICAgICBEZWRpY2F0ZWRNYXN0ZXJFbmFibGVkOiB0cnVlLFxuICAgICAgSW5zdGFuY2VDb3VudDogMyxcbiAgICAgIFpvbmVBd2FyZW5lc3NFbmFibGVkOiB0cnVlXG4gICAgfVxuICB9KTtcbn0pO1xuXG50ZXN0KCdUZXN0IGRlcGxveW1lbnQgd2l0aCBhbiBleGlzdGluZyBwcml2YXRlIFZQQycsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBkZXBsb3lTdGFjaygpO1xuXG4gIGNvbnN0IHZwYyA9IG5ldyBlYzIuVnBjKHN0YWNrLCAnZXhpc3RpbmctcHJpdmF0ZS12cGMtdGVzdCcsIHtcbiAgICBuYXRHYXRld2F5czogMSxcbiAgICBzdWJuZXRDb25maWd1cmF0aW9uOiBbXG4gICAgICB7XG4gICAgICAgIGNpZHJNYXNrOiAyNCxcbiAgICAgICAgbmFtZTogJ2FwcGxpY2F0aW9uJyxcbiAgICAgICAgc3VibmV0VHlwZTogZWMyLlN1Ym5ldFR5cGUuUFJJVkFURV9XSVRIX0VHUkVTUyxcbiAgICAgIH0sXG4gICAgICB7XG4gICAgICAgIGNpZHJNYXNrOiAyNCxcbiAgICAgICAgbmFtZTogXCJwdWJsaWNcIixcbiAgICAgICAgc3VibmV0VHlwZTogZWMyLlN1Ym5ldFR5cGUuUFVCTElDLFxuICAgICAgfVxuICAgIF1cbiAgfSk7XG5cbiAgZGVwbG95T3BlblNlYXJjaChzdGFjaywgJ3Rlc3QtZG9tYWluJywge30sIHVuZGVmaW5lZCwgdnBjKTtcblxuICBleHBlY3Qoc3RhY2spLnRvSGF2ZVJlc291cmNlTGlrZSgnQVdTOjpPcGVuU2VhcmNoU2VydmljZTo6RG9tYWluJywge1xuICAgIERvbWFpbk5hbWU6IFwidGVzdC1kb21haW5cIixcbiAgICBDbHVzdGVyQ29uZmlnOiB7XG4gICAgICBEZWRpY2F0ZWRNYXN0ZXJDb3VudDogMyxcbiAgICAgIERlZGljYXRlZE1hc3RlckVuYWJsZWQ6IHRydWUsXG4gICAgICBJbnN0YW5jZUNvdW50OiAzLFxuICAgICAgWm9uZUF3YXJlbmVzc0VuYWJsZWQ6IHRydWVcbiAgICB9XG4gIH0pO1xufSk7XG5cbnRlc3QoJ1Rlc3QgZXJyb3IgdGhyb3duIHdpdGggbm8gcHJpdmF0ZSBzdWJuZXQgY29uZmlndXJhdGlvbnMnLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gZGVwbG95U3RhY2soKTtcblxuICBjb25zdCB2cGMgPSBkZWZhdWx0cy5idWlsZFZwYyhzdGFjaywge1xuICAgIGRlZmF1bHRWcGNQcm9wczoge1xuICAgICAgc3VibmV0Q29uZmlndXJhdGlvbjogW1xuICAgICAgICB7XG4gICAgICAgICAgY2lkck1hc2s6IDE4LFxuICAgICAgICAgIG5hbWU6IFwicHVibGljXCIsXG4gICAgICAgICAgc3VibmV0VHlwZTogZWMyLlN1Ym5ldFR5cGUuUFVCTElDLFxuICAgICAgICB9XG4gICAgICBdXG4gICAgfVxuICB9KTtcblxuICBjb25zdCBhcHAgPSAoKSA9PiB7XG4gICAgZGVwbG95T3BlblNlYXJjaChzdGFjaywgJ3Rlc3QtZG9tYWluJywge30sIHVuZGVmaW5lZCwgdnBjKTtcbiAgfTtcblxuICBleHBlY3QoYXBwKS50b1Rocm93RXJyb3IoJ0Vycm9yIC0gTm8gaXNvbGF0ZWQgb3IgcHJpdmF0ZSBzdWJuZXRzIGF2YWlsYWJsZSBpbiBWUEMnKTtcbn0pO1xuXG50ZXN0KCdUZXN0IGVuZ2luZSB2ZXJzaW9uIG92ZXJyaWRlIGZvciBidWlsZE9wZW5TZWFyY2gnLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gZGVwbG95U3RhY2soKTtcblxuICBkZXBsb3lPcGVuU2VhcmNoKHN0YWNrLCAndGVzdC1kb21haW4nLCB7XG4gICAgZW5naW5lVmVyc2lvbjogJ09wZW5TZWFyY2hfMS4wJ1xuICB9KTtcblxuICBleHBlY3Qoc3RhY2spLnRvSGF2ZVJlc291cmNlKCdBV1M6Ok9wZW5TZWFyY2hTZXJ2aWNlOjpEb21haW4nLCB7XG4gICAgQWNjZXNzUG9saWNpZXM6IHtcbiAgICAgIFN0YXRlbWVudDogW1xuICAgICAgICB7XG4gICAgICAgICAgQWN0aW9uOiBcImVzOkVTSHR0cCpcIixcbiAgICAgICAgICBFZmZlY3Q6IFwiQWxsb3dcIixcbiAgICAgICAgICBQcmluY2lwYWw6IHtcbiAgICAgICAgICAgIEFXUzoge1xuICAgICAgICAgICAgICBcIkZuOjpHZXRBdHRcIjogW1xuICAgICAgICAgICAgICAgIFwiQ29nbml0b0F1dGhvcml6ZWRSb2xlMTRFNzRGRTBcIixcbiAgICAgICAgICAgICAgICBcIkFyblwiXG4gICAgICAgICAgICAgIF1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9LFxuICAgICAgICAgIFJlc291cmNlOiB7XG4gICAgICAgICAgICBcIkZuOjpKb2luXCI6IFtcbiAgICAgICAgICAgICAgXCJcIixcbiAgICAgICAgICAgICAgW1xuICAgICAgICAgICAgICAgIFwiYXJuOmF3czplczpcIixcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBSZWY6IFwiQVdTOjpSZWdpb25cIlxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgXCI6XCIsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgUmVmOiBcIkFXUzo6QWNjb3VudElkXCJcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIFwiOmRvbWFpbi90ZXN0LWRvbWFpbi8qXCJcbiAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgXVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgXSxcbiAgICAgIFZlcnNpb246IFwiMjAxMi0xMC0xN1wiXG4gICAgfSxcbiAgICBDb2duaXRvT3B0aW9uczoge1xuICAgICAgRW5hYmxlZDogdHJ1ZSxcbiAgICAgIElkZW50aXR5UG9vbElkOiB7XG4gICAgICAgIFJlZjogXCJDb2duaXRvSWRlbnRpdHlQb29sXCJcbiAgICAgIH0sXG4gICAgICBSb2xlQXJuOiB7XG4gICAgICAgIFwiRm46OkdldEF0dFwiOiBbXG4gICAgICAgICAgXCJDb2duaXRvRGFzaGJvYXJkQ29uZmlndXJlUm9sZUVDNUY0ODA5XCIsXG4gICAgICAgICAgXCJBcm5cIlxuICAgICAgICBdXG4gICAgICB9LFxuICAgICAgVXNlclBvb2xJZDoge1xuICAgICAgICBSZWY6IFwiQ29nbml0b1VzZXJQb29sNTNFMzdFNjlcIlxuICAgICAgfVxuICAgIH0sXG4gICAgRG9tYWluTmFtZTogXCJ0ZXN0LWRvbWFpblwiLFxuICAgIEVCU09wdGlvbnM6IHtcbiAgICAgIEVCU0VuYWJsZWQ6IHRydWUsXG4gICAgICBWb2x1bWVTaXplOiAxMFxuICAgIH0sXG4gICAgQ2x1c3RlckNvbmZpZzoge1xuICAgICAgRGVkaWNhdGVkTWFzdGVyQ291bnQ6IDMsXG4gICAgICBEZWRpY2F0ZWRNYXN0ZXJFbmFibGVkOiB0cnVlLFxuICAgICAgSW5zdGFuY2VDb3VudDogMyxcbiAgICAgIFpvbmVBd2FyZW5lc3NDb25maWc6IHtcbiAgICAgICAgQXZhaWxhYmlsaXR5Wm9uZUNvdW50OiAzXG4gICAgICB9LFxuICAgICAgWm9uZUF3YXJlbmVzc0VuYWJsZWQ6IHRydWVcbiAgICB9LFxuICAgIEVuZ2luZVZlcnNpb246IFwiT3BlblNlYXJjaF8xLjBcIixcbiAgICBFbmNyeXB0aW9uQXRSZXN0T3B0aW9uczoge1xuICAgICAgRW5hYmxlZDogdHJ1ZVxuICAgIH0sXG4gICAgTm9kZVRvTm9kZUVuY3J5cHRpb25PcHRpb25zOiB7XG4gICAgICBFbmFibGVkOiB0cnVlXG4gICAgfSxcbiAgICBTbmFwc2hvdE9wdGlvbnM6IHtcbiAgICAgIEF1dG9tYXRlZFNuYXBzaG90U3RhcnRIb3VyOiAxXG4gICAgfVxuICB9KTtcblxufSk7XG5cbnRlc3QoJ1Rlc3QgZGVwbG95bWVudCB3aXRoIGxhbWJkYVJvbGVBUk4nLCAoKSA9PiB7XG4gIGNvbnN0IHN0YWNrID0gZGVwbG95U3RhY2soKTtcblxuICBkZXBsb3lPcGVuU2VhcmNoKHN0YWNrLCAndGVzdC1kb21haW4nLCB7fSwgJ2Fybjphd3M6dXMtZWFzdC0xOm15bGFtYmRhUm9sZUFSTicpO1xuXG4gIGV4cGVjdChzdGFjaykudG9IYXZlUmVzb3VyY2UoJ0FXUzo6T3BlblNlYXJjaFNlcnZpY2U6OkRvbWFpbicsIHtcbiAgICBBY2Nlc3NQb2xpY2llczoge1xuICAgICAgU3RhdGVtZW50OiBbXG4gICAgICAgIHtcbiAgICAgICAgICBBY3Rpb246IFwiZXM6RVNIdHRwKlwiLFxuICAgICAgICAgIEVmZmVjdDogXCJBbGxvd1wiLFxuICAgICAgICAgIFByaW5jaXBhbDoge1xuICAgICAgICAgICAgQVdTOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBcIkZuOjpHZXRBdHRcIjogW1xuICAgICAgICAgICAgICAgICAgXCJDb2duaXRvQXV0aG9yaXplZFJvbGUxNEU3NEZFMFwiLFxuICAgICAgICAgICAgICAgICAgXCJBcm5cIlxuICAgICAgICAgICAgICAgIF1cbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgXCJhcm46YXdzOnVzLWVhc3QtMTpteWxhbWJkYVJvbGVBUk5cIlxuICAgICAgICAgICAgXVxuICAgICAgICAgIH0sXG4gICAgICAgICAgUmVzb3VyY2U6IHtcbiAgICAgICAgICAgIFwiRm46OkpvaW5cIjogW1xuICAgICAgICAgICAgICBcIlwiLFxuICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgXCJhcm46YXdzOmVzOlwiLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgIFJlZjogXCJBV1M6OlJlZ2lvblwiXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBcIjpcIixcbiAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICBSZWY6IFwiQVdTOjpBY2NvdW50SWRcIlxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgXCI6ZG9tYWluL3Rlc3QtZG9tYWluLypcIlxuICAgICAgICAgICAgICBdXG4gICAgICAgICAgICBdXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICBdLFxuICAgICAgVmVyc2lvbjogXCIyMDEyLTEwLTE3XCJcbiAgICB9LFxuICAgIENvZ25pdG9PcHRpb25zOiB7XG4gICAgICBFbmFibGVkOiB0cnVlLFxuICAgICAgSWRlbnRpdHlQb29sSWQ6IHtcbiAgICAgICAgUmVmOiBcIkNvZ25pdG9JZGVudGl0eVBvb2xcIlxuICAgICAgfSxcbiAgICAgIFJvbGVBcm46IHtcbiAgICAgICAgXCJGbjo6R2V0QXR0XCI6IFtcbiAgICAgICAgICBcIkNvZ25pdG9EYXNoYm9hcmRDb25maWd1cmVSb2xlRUM1RjQ4MDlcIixcbiAgICAgICAgICBcIkFyblwiXG4gICAgICAgIF1cbiAgICAgIH0sXG4gICAgICBVc2VyUG9vbElkOiB7XG4gICAgICAgIFJlZjogXCJDb2duaXRvVXNlclBvb2w1M0UzN0U2OVwiXG4gICAgICB9XG4gICAgfSxcbiAgICBEb21haW5OYW1lOiBcInRlc3QtZG9tYWluXCIsXG4gICAgRUJTT3B0aW9uczoge1xuICAgICAgRUJTRW5hYmxlZDogdHJ1ZSxcbiAgICAgIFZvbHVtZVNpemU6IDEwXG4gICAgfSxcbiAgICBDbHVzdGVyQ29uZmlnOiB7XG4gICAgICBEZWRpY2F0ZWRNYXN0ZXJDb3VudDogMyxcbiAgICAgIERlZGljYXRlZE1hc3RlckVuYWJsZWQ6IHRydWUsXG4gICAgICBJbnN0YW5jZUNvdW50OiAzLFxuICAgICAgWm9uZUF3YXJlbmVzc0NvbmZpZzoge1xuICAgICAgICBBdmFpbGFiaWxpdHlab25lQ291bnQ6IDNcbiAgICAgIH0sXG4gICAgICBab25lQXdhcmVuZXNzRW5hYmxlZDogdHJ1ZVxuICAgIH0sXG4gICAgRW5naW5lVmVyc2lvbjogXCJPcGVuU2VhcmNoXzEuM1wiLFxuICAgIEVuY3J5cHRpb25BdFJlc3RPcHRpb25zOiB7XG4gICAgICBFbmFibGVkOiB0cnVlXG4gICAgfSxcbiAgICBOb2RlVG9Ob2RlRW5jcnlwdGlvbk9wdGlvbnM6IHtcbiAgICAgIEVuYWJsZWQ6IHRydWVcbiAgICB9LFxuICAgIFNuYXBzaG90T3B0aW9uczoge1xuICAgICAgQXV0b21hdGVkU25hcHNob3RTdGFydEhvdXI6IDFcbiAgICB9XG4gIH0pO1xuXG59KTtcblxudGVzdCgnQ291bnQgT3BlblNlYXJjaCBDbG91ZFdhdGNoIGFsYXJtcycsICgpID0+IHtcbiAgY29uc3Qgc3RhY2sgPSBuZXcgU3RhY2soKTtcbiAgZGVwbG95T3BlblNlYXJjaChzdGFjaywgJ3Rlc3QtZG9tYWluJyk7XG4gIGNvbnN0IGN3TGlzdCA9IGRlZmF1bHRzLmJ1aWxkT3BlblNlYXJjaENXQWxhcm1zKHN0YWNrKTtcblxuICBleHBlY3QoY3dMaXN0Lmxlbmd0aCkudG9FcXVhbCg5KTtcbn0pO1xuIl19