@mikarinneoracle/oci-cdk-code-only-preview 0.0.1 → 0.0.2

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.
Files changed (46) hide show
  1. package/package.json +1 -1
  2. package/lib/.gen/providers/oci/identity-dynamic-group/index.d.ts +0 -166
  3. package/lib/.gen/providers/oci/identity-dynamic-group/index.js +0 -408
  4. package/lib/bin/deploy-with-build.js +0 -132
  5. package/lib/test/java-function/aws-cdk/bin/app.d.ts +0 -2
  6. package/lib/test/java-function/aws-cdk/bin/app.js +0 -51
  7. package/lib/test/java-function/aws-cdk/lib/function-stack.d.ts +0 -11
  8. package/lib/test/java-function/aws-cdk/lib/function-stack.js +0 -159
  9. package/lib/test/java-function/aws-cdk/lib/test-function-stack.d.ts +0 -5
  10. package/lib/test/java-function/aws-cdk/lib/test-function-stack.js +0 -94
  11. package/lib/test/java-function/oci-cdk/.gen/providers/oci/apigateway-deployment/index.d.ts +0 -5356
  12. package/lib/test/java-function/oci-cdk/.gen/providers/oci/apigateway-deployment/index.js +0 -14972
  13. package/lib/test/java-function/oci-cdk/.gen/providers/oci/apigateway-gateway/index.d.ts +0 -449
  14. package/lib/test/java-function/oci-cdk/.gen/providers/oci/apigateway-gateway/index.js +0 -1149
  15. package/lib/test/java-function/oci-cdk/.gen/providers/oci/artifacts-container-repository/index.d.ts +0 -217
  16. package/lib/test/java-function/oci-cdk/.gen/providers/oci/artifacts-container-repository/index.js +0 -563
  17. package/lib/test/java-function/oci-cdk/.gen/providers/oci/core-internet-gateway/index.d.ts +0 -176
  18. package/lib/test/java-function/oci-cdk/.gen/providers/oci/core-internet-gateway/index.js +0 -431
  19. package/lib/test/java-function/oci-cdk/.gen/providers/oci/core-route-table/index.d.ts +0 -255
  20. package/lib/test/java-function/oci-cdk/.gen/providers/oci/core-route-table/index.js +0 -644
  21. package/lib/test/java-function/oci-cdk/.gen/providers/oci/core-security-list/index.d.ts +0 -752
  22. package/lib/test/java-function/oci-cdk/.gen/providers/oci/core-security-list/index.js +0 -2091
  23. package/lib/test/java-function/oci-cdk/.gen/providers/oci/core-service-gateway/index.d.ts +0 -220
  24. package/lib/test/java-function/oci-cdk/.gen/providers/oci/core-service-gateway/index.js +0 -543
  25. package/lib/test/java-function/oci-cdk/.gen/providers/oci/core-subnet/index.d.ts +0 -251
  26. package/lib/test/java-function/oci-cdk/.gen/providers/oci/core-subnet/index.js +0 -612
  27. package/lib/test/java-function/oci-cdk/.gen/providers/oci/core-vcn/index.d.ts +0 -270
  28. package/lib/test/java-function/oci-cdk/.gen/providers/oci/core-vcn/index.js +0 -672
  29. package/lib/test/java-function/oci-cdk/.gen/providers/oci/data-oci-core-services/index.d.ts +0 -150
  30. package/lib/test/java-function/oci-cdk/.gen/providers/oci/data-oci-core-services/index.js +0 -386
  31. package/lib/test/java-function/oci-cdk/.gen/providers/oci/functions-application/index.d.ts +0 -330
  32. package/lib/test/java-function/oci-cdk/.gen/providers/oci/functions-application/index.js +0 -821
  33. package/lib/test/java-function/oci-cdk/.gen/providers/oci/functions-function/index.d.ts +0 -322
  34. package/lib/test/java-function/oci-cdk/.gen/providers/oci/functions-function/index.js +0 -820
  35. package/lib/test/java-function/oci-cdk/.gen/providers/oci/provider/index.d.ts +0 -190
  36. package/lib/test/java-function/oci-cdk/.gen/providers/oci/provider/index.js +0 -391
  37. package/lib/test/java-function/oci-cdk/.gen/providers/oci/vault-secret/index.d.ts +0 -439
  38. package/lib/test/java-function/oci-cdk/.gen/providers/oci/vault-secret/index.js +0 -1146
  39. package/lib/test/java-function/oci-cdk/bin/app.d.ts +0 -2
  40. package/lib/test/java-function/oci-cdk/bin/app.js +0 -34
  41. package/lib/test/java-function/oci-cdk/config/oci-config.d.ts +0 -68
  42. package/lib/test/java-function/oci-cdk/config/oci-config.js +0 -202
  43. package/lib/test/java-function/oci-cdk/lib/function-stack.d.ts +0 -31
  44. package/lib/test/java-function/oci-cdk/lib/function-stack.js +0 -549
  45. package/lib/test/java-function/oci-cdk/lib/test-function-stack.d.ts +0 -17
  46. package/lib/test/java-function/oci-cdk/lib/test-function-stack.js +0 -99
@@ -1,549 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.FunctionStack = void 0;
37
- const cdktf_1 = require("cdktf");
38
- const provider_1 = require("../.gen/providers/oci/provider");
39
- const artifacts_container_repository_1 = require("../.gen/providers/oci/artifacts-container-repository");
40
- const core_vcn_1 = require("../.gen/providers/oci/core-vcn");
41
- const core_subnet_1 = require("../.gen/providers/oci/core-subnet");
42
- const core_security_list_1 = require("../.gen/providers/oci/core-security-list");
43
- const core_service_gateway_1 = require("../.gen/providers/oci/core-service-gateway");
44
- const data_oci_core_services_1 = require("../.gen/providers/oci/data-oci-core-services");
45
- const core_route_table_1 = require("../.gen/providers/oci/core-route-table");
46
- const core_internet_gateway_1 = require("../.gen/providers/oci/core-internet-gateway");
47
- const apigateway_gateway_1 = require("../.gen/providers/oci/apigateway-gateway");
48
- const apigateway_deployment_1 = require("../.gen/providers/oci/apigateway-deployment");
49
- const functions_application_1 = require("../.gen/providers/oci/functions-application");
50
- const functions_function_1 = require("../.gen/providers/oci/functions-function");
51
- const vault_secret_1 = require("../.gen/providers/oci/vault-secret");
52
- const crypto = __importStar(require("crypto"));
53
- const path = __importStar(require("path"));
54
- class FunctionStack extends cdktf_1.TerraformStack {
55
- constructor(scope, id, config) {
56
- super(scope, id);
57
- // -------------------------------------------------------------------------
58
- // Backend & Provider
59
- // -------------------------------------------------------------------------
60
- if (config.backend && config.backend.type !== 'local') {
61
- if (config.backend.type === 'oci') {
62
- this.addOverride('terraform.backend', {
63
- oci: {
64
- bucket: config.backend.bucket,
65
- namespace: config.namespace,
66
- key: config.backend.key || `${id}/terraform.tfstate`,
67
- region: config.region,
68
- },
69
- });
70
- }
71
- else if (config.backend.type === 'http') {
72
- const httpBackend = {
73
- address: config.backend.address,
74
- update_method: config.backend.updateMethod || 'PUT',
75
- };
76
- if (config.backend.lockAddress)
77
- httpBackend.lock_address = config.backend.lockAddress;
78
- if (config.backend.unlockAddress)
79
- httpBackend.unlock_address = config.backend.unlockAddress;
80
- this.addOverride('terraform.backend', { http: httpBackend });
81
- }
82
- }
83
- new provider_1.OciProvider(this, 'oci', {
84
- region: config.region,
85
- tenancyOcid: config.tenancyId,
86
- });
87
- // Add null provider using addOverride (avoids needing to generate types)
88
- this.addOverride('terraform.required_providers.null', {
89
- source: 'hashicorp/null',
90
- version: '~> 3.0',
91
- });
92
- const ocirCompartmentId = config.ocirCompartmentId || config.compartmentId;
93
- const ocirRepoName = config.ocirRepositoryName || config.functionName;
94
- if (ocirCompartmentId.includes('root')) {
95
- throw new Error('OCIR repository cannot be created in root compartment. ' +
96
- 'Please set OCI_OCIR_COMPARTMENT_ID to your home compartment OCID.');
97
- }
98
- // -------------------------------------------------------------------------
99
- // OCIR Container Repository
100
- // -------------------------------------------------------------------------
101
- const ocirRepository = new artifacts_container_repository_1.ArtifactsContainerRepository(this, 'OcirRepository', {
102
- compartmentId: ocirCompartmentId,
103
- displayName: ocirRepoName,
104
- isPublic: false,
105
- isImmutable: false,
106
- });
107
- // -------------------------------------------------------------------------
108
- // Build and Push Docker Image to OCIR (after repository is created)
109
- // -------------------------------------------------------------------------
110
- const imageUrl = `${config.region}.ocir.io/${config.namespace}/${ocirRepoName}:latest`;
111
- // Get OCIR login username from env or try to get from OCI CLI
112
- // Format: <tenancy-namespace>/<username> (e.g., frsxwtjslf35/oracleidentitycloudservice/user@example.com)
113
- // Default will be constructed in the script if not provided
114
- const ocirUsername = process.env.OCI_OCIR_USERNAME || 'AUTO_DETECT';
115
- // function-code is at java-function/function-code (sibling of oci-cdk)
116
- // Resolve path relative to this file's location
117
- // Compiled JS is at lib/lib/function-stack.js, so __dirname is lib/lib/
118
- // From lib/lib/: ../ goes to lib/, ../ goes to oci-cdk/, ../ goes to java-function/, then function-code/
119
- const functionCodePath = path.resolve(__dirname, '..', '..', '..', 'function-code');
120
- // Create null_resource using addOverride (since we can't generate types due to network issues)
121
- // This creates a Terraform null_resource that builds and pushes the Docker image
122
- const buildAndPushImageId = 'BuildAndPushImage';
123
- // Use the Terraform resource reference directly (not interpolated string)
124
- // depends_on expects resource references, not attribute references
125
- this.addOverride(`resource.null_resource.${buildAndPushImageId}.depends_on`, [
126
- 'oci_artifacts_container_repository.OcirRepository',
127
- ]);
128
- this.addOverride(`resource.null_resource.${buildAndPushImageId}.triggers`, {
129
- repo_name: ocirRepoName,
130
- image_url: imageUrl,
131
- namespace: config.namespace,
132
- region: config.region,
133
- });
134
- // Generate auth token and login script
135
- // If OCI_AUTH_TOKEN is set, use it; otherwise generate one via OCI CLI
136
- const regionPlaceholder = config.region;
137
- const namespacePlaceholder = config.namespace;
138
- const ocirUsernameValue = ocirUsername; // Capture value for template string
139
- // Use string concatenation to avoid TypeScript parsing issues with ${} in shell scripts
140
- const dollarSign = '$';
141
- const dollarDollar = '$$';
142
- // Use backticks for command substitution to avoid complex $() escaping
143
- // In TypeScript template strings, backticks need to be escaped as \`
144
- const cmdSubStart = '\`';
145
- const cmdSubEnd = '\`';
146
- const loginScript = process.env.OCI_AUTH_TOKEN
147
- ? `# Using provided OCI_AUTH_TOKEN
148
- export OCIR_AUTH_TOKEN="${process.env.OCI_AUTH_TOKEN}"
149
- if [ -z "${dollarDollar}OCIR_AUTH_TOKEN" ]; then
150
- echo "Error: OCI_AUTH_TOKEN is empty. Please set a valid token."
151
- exit 1
152
- fi
153
- # Use provided username or auto-detect
154
- OCIR_USERNAME="${ocirUsernameValue}"
155
- if [ "${dollarDollar}OCIR_USERNAME" == "AUTO_DETECT" ]; then
156
- USER_OCID=${cmdSubStart}oci iam user list --query "data[0].id" --raw-output 2>/dev/null${cmdSubEnd}
157
- if [ -n "${dollarDollar}USER_OCID" ] && [ "${dollarDollar}USER_OCID" != "null" ]; then
158
- USER_NAME=${cmdSubStart}oci iam user get --user-id "${dollarDollar}USER_OCID" --query 'data.name' --raw-output 2>/dev/null || echo ""${cmdSubEnd}
159
- if [ -n "${dollarDollar}USER_NAME" ]; then
160
- OCIR_USERNAME="${namespacePlaceholder}/${dollarDollar}USER_NAME"
161
- else
162
- echo "Warning: Could not auto-detect username. Using default format."
163
- OCIR_USERNAME="${namespacePlaceholder}/user"
164
- fi
165
- else
166
- OCIR_USERNAME="${namespacePlaceholder}/user"
167
- fi
168
- fi
169
- echo "${dollarDollar}OCIR_AUTH_TOKEN" | docker login ${regionPlaceholder}.ocir.io -u "${dollarDollar}OCIR_USERNAME" --password-stdin >/dev/null 2>&1 || {
170
- echo "Error: Docker login failed. Check your OCI_AUTH_TOKEN and username format." >&2
171
- echo "Username used: ${dollarDollar}OCIR_USERNAME" >&2
172
- echo "Username format should be: <tenancy-namespace>/<username>" >&2
173
- echo "Set manually: export OCI_OCIR_USERNAME=\\"${namespacePlaceholder}/your-actual-username\\"" >&2
174
- exit 1
175
- }`
176
- : `# Generate OCIR auth token via OCI CLI and login to OCIR
177
- # Try raw-request method first (uses default OCI CLI auth from config)
178
- OCIR_HOST="${regionPlaceholder}.ocir.io"
179
- if oci raw-request --region ${regionPlaceholder} --http-method GET --target-uri "https://${regionPlaceholder}.ocir.io/20180419/docker/token" >/dev/null 2>&1; then
180
- if command -v jq >/dev/null 2>&1; then
181
- oci raw-request --region ${regionPlaceholder} --http-method GET --target-uri "https://${regionPlaceholder}.ocir.io/20180419/docker/token" 2>/dev/null | jq -r .data.token 2>/dev/null | docker login -u BEARER_TOKEN --password-stdin ${regionPlaceholder}.ocir.io >/dev/null 2>&1 || {
182
- echo "Error: Docker login with raw-request failed." >&2
183
- exit 1
184
- }
185
- else
186
- oci raw-request --region ${regionPlaceholder} --http-method GET --target-uri "https://${regionPlaceholder}.ocir.io/20180419/docker/token" 2>/dev/null | grep -o '"token":"[^"]*"' | cut -d'"' -f4 | docker login -u BEARER_TOKEN --password-stdin ${regionPlaceholder}.ocir.io >/dev/null 2>&1 || {
187
- echo "Error: Docker login with raw-request failed." >&2
188
- exit 1
189
- }
190
- fi
191
- else
192
- # Fallback to auth token method (for localhost)
193
- # Get user OCID from CLI config (same approach as reference script)
194
- OCI_CONFIG="${dollarDollar}{OCI_CLI_CONFIG_FILE:-${dollarDollar}HOME/.oci/config}"
195
- OCI_PROFILE="${dollarDollar}{OCI_CLI_PROFILE:-DEFAULT}"
196
- USER_OCID=""
197
- if [ -f "${dollarDollar}OCI_CONFIG" ]; then
198
- USER_OCID=${cmdSubStart}awk -v prof="[${dollarDollar}OCI_PROFILE]" '${dollarDollar}0 == prof { in_profile=1; next } /^\\[/ { in_profile=0 } in_profile && ${dollarDollar}0 ~ /^[[:space:]]*user[[:space:]]*=/ { split(${dollarDollar}0, a, "="); gsub(/^[[:space:]]+|[[:space:]]+${dollarDollar}/, "", a[2]); print a[2]; exit }' "${dollarDollar}OCI_CONFIG" 2>/dev/null || echo ""${cmdSubEnd}
199
- fi
200
-
201
- # Fallback to user list if not in config
202
- if [ -z "${dollarDollar}USER_OCID" ] || [ "${dollarDollar}USER_OCID" != ocid1.* ]; then
203
- USER_OCID=${cmdSubStart}oci iam user list --query "data[0].id" --raw-output 2>/dev/null || echo ""${cmdSubEnd}
204
- fi
205
-
206
- if [ -z "${dollarDollar}USER_OCID" ] || [ "${dollarDollar}USER_OCID" == "null" ] || [ "${dollarDollar}USER_OCID" != ocid1.* ]; then
207
- echo "Error: Could not get user OCID. Set OCI_AUTH_TOKEN manually or ensure OCI CLI is configured." >&2
208
- echo "Run: oci iam user list" >&2
209
- echo "Or check your OCI config: ${dollarDollar}OCI_CONFIG" >&2
210
- exit 1
211
- fi
212
-
213
- # Verify user exists before trying to create token
214
- if ! oci iam user get --user-id "${dollarDollar}USER_OCID" >/dev/null 2>&1; then
215
- echo "Error: User OCID '${dollarDollar}USER_OCID' not found or not accessible." >&2
216
- echo "Please verify your OCI CLI configuration or set OCI_AUTH_TOKEN manually." >&2
217
- exit 1
218
- fi
219
-
220
- # Get username for OCIR login
221
- OCIR_USERNAME_VAR="${ocirUsernameValue}"
222
- if [ "${dollarDollar}OCIR_USERNAME_VAR" == "AUTO_DETECT" ]; then
223
- USER_NAME=${cmdSubStart}oci iam user get --user-id "${dollarDollar}USER_OCID" --query 'data.name' --raw-output 2>/dev/null || echo ""${cmdSubEnd}
224
- if [ -z "${dollarDollar}USER_NAME" ] || [ "${dollarDollar}USER_NAME" == "null" ]; then
225
- echo "Error: Could not get username for user ${dollarDollar}USER_OCID." >&2
226
- echo "Please set OCI_OCIR_USERNAME manually." >&2
227
- echo "Format: export OCI_OCIR_USERNAME=\\"${namespacePlaceholder}/your-username\\"" >&2
228
- exit 1
229
- fi
230
- # Extract username part if it contains domain (e.g., "oracleidentitycloudservice/user@example.com" -> "user@example.com")
231
- USER_NAME="${dollarDollar}{USER_NAME##*/}"
232
- OCIR_USERNAME="${namespacePlaceholder}/oracleidentitycloudservice/${dollarDollar}USER_NAME"
233
- else
234
- OCIR_USERNAME="${dollarDollar}OCIR_USERNAME_VAR"
235
- fi
236
-
237
- DESC="OCIR Docker login token - ${cmdSubStart}date +%Y%m%d-%H%M%S${cmdSubEnd}"
238
- TOKEN=${cmdSubStart}oci iam auth-token create --user-id "${dollarDollar}USER_OCID" --description "${dollarDollar}DESC" --query 'data.token' --raw-output 2>/dev/null || true${cmdSubEnd}
239
-
240
- if [ -z "${dollarDollar}TOKEN" ] || [ "${dollarDollar}TOKEN" == "null" ]; then
241
- echo "Error: Failed to create auth token via OCI CLI." >&2
242
- echo "This might be due to:" >&2
243
- echo " - Missing IAM permissions (need: manage auth-tokens)" >&2
244
- echo " - User OCID '${dollarDollar}USER_OCID' is incorrect or user doesn't exist" >&2
245
- echo " - OCI CLI not properly configured" >&2
246
- echo "" >&2
247
- echo "Solution: Set OCI_AUTH_TOKEN manually:" >&2
248
- echo " 1. Get token from: https://cloud.oracle.com/identity/tokens" >&2
249
- echo " 2. Export: export OCI_AUTH_TOKEN=\\"your-token\\"" >&2
250
- echo " 3. Also set: export OCI_OCIR_USERNAME=\\"${dollarDollar}OCIR_USERNAME\\"" >&2
251
- echo " 4. Then re-run: npm run deploy" >&2
252
- exit 1
253
- fi
254
-
255
- export OCIR_AUTH_TOKEN="${dollarDollar}TOKEN"
256
- echo "${dollarDollar}OCIR_AUTH_TOKEN" | docker login ${regionPlaceholder}.ocir.io -u "${dollarDollar}OCIR_USERNAME" --password-stdin >/dev/null 2>&1 || {
257
- echo "Error: Docker login failed with generated token." >&2
258
- echo "Username used: ${dollarDollar}OCIR_USERNAME" >&2
259
- echo "Check that the username format is correct: <tenancy-namespace>/<domain>/<username>" >&2
260
- echo "If incorrect, set: export OCI_OCIR_USERNAME=\\"${namespacePlaceholder}/oracleidentitycloudservice/your-username\\"" >&2
261
- exit 1
262
- }
263
- fi`;
264
- this.addOverride(`resource.null_resource.${buildAndPushImageId}.provisioner`, [
265
- {
266
- 'local-exec': {
267
- command: `cd ${functionCodePath} && docker build --platform linux/amd64 -t ${imageUrl} .`,
268
- },
269
- },
270
- {
271
- 'local-exec': {
272
- command: loginScript,
273
- on_failure: 'continue',
274
- },
275
- },
276
- {
277
- 'local-exec': {
278
- command: `docker push ${imageUrl}`,
279
- },
280
- },
281
- ]);
282
- // Create a reference to the null_resource for dependency tracking
283
- // We'll use a TerraformData source as a proxy to reference it
284
- const buildAndPushImageRef = `\${null_resource.${buildAndPushImageId}.id}`;
285
- // -------------------------------------------------------------------------
286
- // VCN and Subnets
287
- // -------------------------------------------------------------------------
288
- const vcn = new core_vcn_1.CoreVcn(this, 'Vcn', {
289
- compartmentId: config.compartmentId,
290
- displayName: `${id}-vcn`,
291
- cidrBlocks: ['10.0.0.0/16'],
292
- dnsLabel: 'appfn',
293
- });
294
- const publicSubnet = new core_subnet_1.CoreSubnet(this, 'PublicSubnet', {
295
- compartmentId: config.compartmentId,
296
- vcnId: vcn.id,
297
- displayName: `${id}-public`,
298
- cidrBlock: '10.0.1.0/24',
299
- dnsLabel: 'public',
300
- prohibitPublicIpOnVnic: false,
301
- });
302
- const privateSubnet = new core_subnet_1.CoreSubnet(this, 'PrivateSubnet', {
303
- compartmentId: config.compartmentId,
304
- vcnId: vcn.id,
305
- displayName: `${id}-private`,
306
- cidrBlock: '10.0.2.0/24',
307
- dnsLabel: 'private',
308
- prohibitPublicIpOnVnic: true,
309
- });
310
- // -------------------------------------------------------------------------
311
- // Security List for Public Subnet (API Gateway)
312
- // -------------------------------------------------------------------------
313
- const publicSecurityList = new core_security_list_1.CoreSecurityList(this, 'PublicSecurityList', {
314
- compartmentId: config.compartmentId,
315
- vcnId: vcn.id,
316
- displayName: `${id}-public-sl`,
317
- ingressSecurityRules: [
318
- {
319
- protocol: '6', // TCP
320
- source: '0.0.0.0/0',
321
- description: 'Allow HTTP (80) from internet',
322
- tcpOptions: {
323
- min: 80,
324
- max: 80,
325
- },
326
- },
327
- {
328
- protocol: '6', // TCP
329
- source: '0.0.0.0/0',
330
- description: 'Allow HTTPS (443) from internet',
331
- tcpOptions: {
332
- min: 443,
333
- max: 443,
334
- },
335
- },
336
- ],
337
- egressSecurityRules: [
338
- {
339
- protocol: 'all',
340
- destination: '0.0.0.0/0',
341
- description: 'Allow all outbound traffic',
342
- },
343
- ],
344
- });
345
- // Associate security list with public subnet
346
- publicSubnet.addOverride('security_list_ids', [publicSecurityList.id]);
347
- // -------------------------------------------------------------------------
348
- // Security List for Private Subnet (Function + PG in same subnet)
349
- // -------------------------------------------------------------------------
350
- const privateSubnetCidr = '10.0.2.0/24';
351
- const privateSecurityList = new core_security_list_1.CoreSecurityList(this, 'PrivateSecurityList', {
352
- compartmentId: config.compartmentId,
353
- vcnId: vcn.id,
354
- displayName: `${id}-private-sl`,
355
- ingressSecurityRules: [
356
- {
357
- protocol: '6', // TCP
358
- source: privateSubnetCidr,
359
- description: 'TCP traffic for ports: 5432 (PostgreSQL from private subnet)',
360
- tcpOptions: {
361
- min: 5432,
362
- max: 5432,
363
- },
364
- },
365
- ],
366
- egressSecurityRules: [
367
- {
368
- protocol: 'all',
369
- destination: '0.0.0.0/0',
370
- description: 'Allow all outbound traffic',
371
- },
372
- ],
373
- });
374
- // Associate security list with private subnet
375
- privateSubnet.addOverride('security_list_ids', [privateSecurityList.id]);
376
- // -------------------------------------------------------------------------
377
- // Service Gateway (for OCIR access from private subnet)
378
- // -------------------------------------------------------------------------
379
- // Get Object Storage service ID (OCIR uses Object Storage)
380
- // Get all services - the first service is typically "All <region> Services in Oracle Services Network"
381
- // This service includes Object Storage and other OCI services
382
- const allServices = new data_oci_core_services_1.DataOciCoreServices(this, 'AllServices', {});
383
- const serviceGateway = new core_service_gateway_1.CoreServiceGateway(this, 'ServiceGateway', {
384
- compartmentId: config.compartmentId,
385
- vcnId: vcn.id,
386
- displayName: `${id}-service-gateway`,
387
- services: [
388
- {
389
- serviceId: allServices.services.get(0).id,
390
- },
391
- ],
392
- });
393
- // Route table for private subnet to route Object Storage traffic via Service Gateway
394
- const privateRouteTable = new core_route_table_1.CoreRouteTable(this, 'PrivateRouteTable', {
395
- compartmentId: config.compartmentId,
396
- vcnId: vcn.id,
397
- displayName: `${id}-private-rt`,
398
- routeRules: [
399
- {
400
- networkEntityId: serviceGateway.id,
401
- destination: allServices.services.get(0).cidrBlock,
402
- destinationType: 'SERVICE_CIDR_BLOCK',
403
- description: 'Route Object Storage/OCIR traffic via Service Gateway',
404
- },
405
- ],
406
- });
407
- // Associate route table with private subnet
408
- privateSubnet.addOverride('route_table_id', privateRouteTable.id);
409
- // -------------------------------------------------------------------------
410
- // Internet Gateway (for public subnet internet access)
411
- // -------------------------------------------------------------------------
412
- const internetGateway = new core_internet_gateway_1.CoreInternetGateway(this, 'InternetGateway', {
413
- compartmentId: config.compartmentId,
414
- vcnId: vcn.id,
415
- displayName: `${id}-igw`,
416
- enabled: true,
417
- });
418
- // Route table for public subnet to route internet traffic via Internet Gateway
419
- const publicRouteTable = new core_route_table_1.CoreRouteTable(this, 'PublicRouteTable', {
420
- compartmentId: config.compartmentId,
421
- vcnId: vcn.id,
422
- displayName: `${id}-public-rt`,
423
- routeRules: [
424
- {
425
- networkEntityId: internetGateway.id,
426
- destination: '0.0.0.0/0',
427
- destinationType: 'CIDR_BLOCK',
428
- description: 'Route all internet traffic via Internet Gateway',
429
- },
430
- ],
431
- });
432
- // Associate route table with public subnet
433
- publicSubnet.addOverride('route_table_id', publicRouteTable.id);
434
- // -------------------------------------------------------------------------
435
- // PG connection: either pass PG_URL as function config, or create Vault secret and pass PG_SECRET_OCID
436
- // -------------------------------------------------------------------------
437
- const functionConfig = {};
438
- if (config.pgUrl && config.pgUrl.trim()) {
439
- if (config.vaultOcid?.trim()) {
440
- // Vault path: require keyOcid and create pg-url secret
441
- if (!config.keyOcid?.trim()) {
442
- throw new Error('When OCI_VAULT_OCID is set, OCI_KEY_OCID is required to create the pg-url secret. ' +
443
- 'Set OCI_KEY_OCID to your Vault encryption Key OCID.');
444
- }
445
- // Append random suffix to avoid "name already exists" when a secret with the same base name exists in the Vault.
446
- // Set PG_SECRET_SUFFIX env var to pin the name across synths (e.g. PG_SECRET_SUFFIX=abc12345).
447
- const pgUrlSecretSuffix = process.env.PG_SECRET_SUFFIX || crypto.randomBytes(4).toString('hex');
448
- const pgUrlSecretName = `${id}-pg-url-${pgUrlSecretSuffix}`;
449
- const pgUrlSecret = new vault_secret_1.VaultSecret(this, 'PgUrlSecret', {
450
- compartmentId: config.compartmentId,
451
- vaultId: config.vaultOcid,
452
- keyId: config.keyOcid,
453
- secretName: pgUrlSecretName,
454
- description: 'PostgreSQL connection URL for function (from PG_URL)',
455
- secretContent: {
456
- contentType: 'BASE64',
457
- content: Buffer.from(config.pgUrl.trim(), 'utf-8').toString('base64'),
458
- },
459
- });
460
- functionConfig.PG_SECRET_OCID = pgUrlSecret.id;
461
- }
462
- else {
463
- // No Vault: pass PG_URL directly as function config (clear-text)
464
- console.warn('[OCI Function] WARNING: PG_URL is being passed to the function as plain config (clear-text). ' +
465
- 'Credentials are visible in function configuration. For production, store the connection string in OCI Vault and set ' +
466
- 'OCI_VAULT_OCID and OCI_KEY_OCID so the stack creates a Vault secret; the function will then receive only PG_SECRET_OCID.');
467
- functionConfig.PG_URL = config.pgUrl.trim();
468
- }
469
- }
470
- else if (config.pgSecretOcid?.trim()) {
471
- functionConfig.PG_SECRET_OCID = config.pgSecretOcid.trim();
472
- }
473
- // -------------------------------------------------------------------------
474
- // API Gateway (public subnet)
475
- // -------------------------------------------------------------------------
476
- const apiGateway = new apigateway_gateway_1.ApigatewayGateway(this, 'ApiGateway', {
477
- compartmentId: config.compartmentId,
478
- subnetId: publicSubnet.id,
479
- endpointType: 'PUBLIC',
480
- displayName: `${id}-api-gateway`,
481
- });
482
- // -------------------------------------------------------------------------
483
- // Functions Application (private subnet) and Function
484
- // -------------------------------------------------------------------------
485
- const functionApp = new functions_application_1.FunctionsApplication(this, 'FunctionApp', {
486
- compartmentId: config.compartmentId,
487
- displayName: config.functionAppName,
488
- subnetIds: [privateSubnet.id],
489
- });
490
- // Function depends on image being pushed to OCIR
491
- const ociFunction = new functions_function_1.FunctionsFunction(this, 'Function', {
492
- applicationId: functionApp.id,
493
- displayName: config.functionName,
494
- image: imageUrl,
495
- memoryInMbs: '256',
496
- timeoutInSeconds: 30,
497
- config: Object.keys(functionConfig).length > 0 ? functionConfig : undefined,
498
- });
499
- // Add dependency on null_resource using addOverride
500
- // This ensures the image is built and pushed before the Function is created
501
- ociFunction.addOverride('depends_on', [`null_resource.${buildAndPushImageId}`]);
502
- // -------------------------------------------------------------------------
503
- // API Gateway Deployment – route to function (only after function exists)
504
- // -------------------------------------------------------------------------
505
- const pathPrefix = config.apiGwPathPrefix ?? '/';
506
- const routePath = config.apiGwRoutePath ?? '/{path*}';
507
- const methods = config.apiGwMethods?.length ? config.apiGwMethods : ['GET', 'POST', 'OPTIONS'];
508
- const apiDeployment = new apigateway_deployment_1.ApigatewayDeployment(this, 'ApiDeployment', {
509
- compartmentId: config.compartmentId,
510
- gatewayId: apiGateway.id,
511
- pathPrefix,
512
- displayName: `${id}-deployment`,
513
- specification: {
514
- routes: [
515
- {
516
- path: routePath,
517
- methods,
518
- backend: {
519
- type: 'ORACLE_FUNCTIONS_BACKEND',
520
- functionId: ociFunction.id,
521
- },
522
- },
523
- ],
524
- },
525
- });
526
- apiDeployment.node.addDependency(ociFunction);
527
- // -------------------------------------------------------------------------
528
- // Outputs
529
- // -------------------------------------------------------------------------
530
- new cdktf_1.TerraformOutput(this, 'ocir_repository_name', {
531
- value: ocirRepository.displayName,
532
- description: 'OCIR repository display name',
533
- });
534
- new cdktf_1.TerraformOutput(this, 'api_gateway_host', {
535
- value: apiGateway.hostname,
536
- description: 'API Gateway hostname for invoking the function',
537
- });
538
- new cdktf_1.TerraformOutput(this, 'function_invoke_url', {
539
- value: `https://${apiGateway.hostname}`,
540
- description: 'Base URL to invoke the function (use ?action=hello|echo|info)',
541
- });
542
- new cdktf_1.TerraformOutput(this, 'function_id', {
543
- value: ociFunction.id,
544
- description: 'OCI Function OCID (for deploy-function.sh or oci fn function update)',
545
- });
546
- }
547
- }
548
- exports.FunctionStack = FunctionStack;
549
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnVuY3Rpb24tc3RhY2suanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi90ZXN0L2phdmEtZnVuY3Rpb24vb2NpLWNkay9saWIvZnVuY3Rpb24tc3RhY2sudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQ0EsaUNBQXdEO0FBQ3hELDZEQUE2RDtBQUM3RCx5R0FBb0c7QUFDcEcsNkRBQXlEO0FBQ3pELG1FQUErRDtBQUMvRCxpRkFBNEU7QUFDNUUscUZBQWdGO0FBQ2hGLHlGQUFtRjtBQUNuRiw2RUFBd0U7QUFDeEUsdUZBQWtGO0FBQ2xGLGlGQUE2RTtBQUM3RSx1RkFBbUY7QUFDbkYsdUZBQW1GO0FBQ25GLGlGQUE2RTtBQUM3RSxxRUFBaUU7QUFFakUsK0NBQWlDO0FBQ2pDLDJDQUE2QjtBQTRCN0IsTUFBYSxhQUFjLFNBQVEsc0JBQWM7SUFDL0MsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxNQUFzQjtRQUM5RCxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLDRFQUE0RTtRQUM1RSxxQkFBcUI7UUFDckIsNEVBQTRFO1FBQzVFLElBQUksTUFBTSxDQUFDLE9BQU8sSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksS0FBSyxPQUFPLEVBQUUsQ0FBQztZQUN0RCxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxLQUFLLEtBQUssRUFBRSxDQUFDO2dCQUNsQyxJQUFJLENBQUMsV0FBVyxDQUFDLG1CQUFtQixFQUFFO29CQUNwQyxHQUFHLEVBQUU7d0JBQ0gsTUFBTSxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsTUFBTTt3QkFDN0IsU0FBUyxFQUFFLE1BQU0sQ0FBQyxTQUFTO3dCQUMzQixHQUFHLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxHQUFHLElBQUksR0FBRyxFQUFFLG9CQUFvQjt3QkFDcEQsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNO3FCQUN0QjtpQkFDRixDQUFDLENBQUM7WUFDTCxDQUFDO2lCQUFNLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEtBQUssTUFBTSxFQUFFLENBQUM7Z0JBQzFDLE1BQU0sV0FBVyxHQUE0QjtvQkFDM0MsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsT0FBTztvQkFDL0IsYUFBYSxFQUFFLE1BQU0sQ0FBQyxPQUFPLENBQUMsWUFBWSxJQUFJLEtBQUs7aUJBQ3BELENBQUM7Z0JBQ0YsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLFdBQVc7b0JBQUUsV0FBVyxDQUFDLFlBQVksR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQztnQkFDdEYsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLGFBQWE7b0JBQUUsV0FBVyxDQUFDLGNBQWMsR0FBRyxNQUFNLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQztnQkFDNUYsSUFBSSxDQUFDLFdBQVcsQ0FBQyxtQkFBbUIsRUFBRSxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsQ0FBQyxDQUFDO1lBQy9ELENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxzQkFBVyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUU7WUFDM0IsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNO1lBQ3JCLFdBQVcsRUFBRSxNQUFNLENBQUMsU0FBUztTQUM5QixDQUFDLENBQUM7UUFFSCx5RUFBeUU7UUFDekUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxtQ0FBbUMsRUFBRTtZQUNwRCxNQUFNLEVBQUUsZ0JBQWdCO1lBQ3hCLE9BQU8sRUFBRSxRQUFRO1NBQ2xCLENBQUMsQ0FBQztRQUVILE1BQU0saUJBQWlCLEdBQUcsTUFBTSxDQUFDLGlCQUFpQixJQUFJLE1BQU0sQ0FBQyxhQUFhLENBQUM7UUFDM0UsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLGtCQUFrQixJQUFJLE1BQU0sQ0FBQyxZQUFZLENBQUM7UUFFdEUsSUFBSSxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztZQUN2QyxNQUFNLElBQUksS0FBSyxDQUNiLHlEQUF5RDtnQkFDdkQsbUVBQW1FLENBQ3RFLENBQUM7UUFDSixDQUFDO1FBRUQsNEVBQTRFO1FBQzVFLDRCQUE0QjtRQUM1Qiw0RUFBNEU7UUFDNUUsTUFBTSxjQUFjLEdBQUcsSUFBSSw2REFBNEIsQ0FBQyxJQUFJLEVBQUUsZ0JBQWdCLEVBQUU7WUFDOUUsYUFBYSxFQUFFLGlCQUFpQjtZQUNoQyxXQUFXLEVBQUUsWUFBWTtZQUN6QixRQUFRLEVBQUUsS0FBSztZQUNmLFdBQVcsRUFBRSxLQUFLO1NBQ25CLENBQUMsQ0FBQztRQUVILDRFQUE0RTtRQUM1RSxvRUFBb0U7UUFDcEUsNEVBQTRFO1FBQzVFLE1BQU0sUUFBUSxHQUFHLEdBQUcsTUFBTSxDQUFDLE1BQU0sWUFBWSxNQUFNLENBQUMsU0FBUyxJQUFJLFlBQVksU0FBUyxDQUFDO1FBRXZGLDhEQUE4RDtRQUM5RCwwR0FBMEc7UUFDMUcsNERBQTREO1FBQzVELE1BQU0sWUFBWSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsaUJBQWlCLElBQUksYUFBYSxDQUFDO1FBRXBFLHVFQUF1RTtRQUN2RSxnREFBZ0Q7UUFDaEQsd0VBQXdFO1FBQ3hFLHlHQUF5RztRQUN6RyxNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBRXBGLCtGQUErRjtRQUMvRixpRkFBaUY7UUFDakYsTUFBTSxtQkFBbUIsR0FBRyxtQkFBbUIsQ0FBQztRQUNoRCwwRUFBMEU7UUFDMUUsbUVBQW1FO1FBQ25FLElBQUksQ0FBQyxXQUFXLENBQUMsMEJBQTBCLG1CQUFtQixhQUFhLEVBQUU7WUFDM0UsbURBQW1EO1NBQ3BELENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxXQUFXLENBQUMsMEJBQTBCLG1CQUFtQixXQUFXLEVBQUU7WUFDekUsU0FBUyxFQUFFLFlBQVk7WUFDdkIsU0FBUyxFQUFFLFFBQVE7WUFDbkIsU0FBUyxFQUFFLE1BQU0sQ0FBQyxTQUFTO1lBQzNCLE1BQU0sRUFBRSxNQUFNLENBQUMsTUFBTTtTQUN0QixDQUFDLENBQUM7UUFFSCx1Q0FBdUM7UUFDdkMsdUVBQXVFO1FBQ3ZFLE1BQU0saUJBQWlCLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztRQUN4QyxNQUFNLG9CQUFvQixHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUM7UUFDOUMsTUFBTSxpQkFBaUIsR0FBRyxZQUFZLENBQUMsQ0FBQyxvQ0FBb0M7UUFDNUUsd0ZBQXdGO1FBQ3hGLE1BQU0sVUFBVSxHQUFHLEdBQUcsQ0FBQztRQUN2QixNQUFNLFlBQVksR0FBRyxJQUFJLENBQUM7UUFDMUIsdUVBQXVFO1FBQ3ZFLHFFQUFxRTtRQUNyRSxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUM7UUFDekIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDO1FBQ3ZCLE1BQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYztZQUM1QyxDQUFDLENBQUM7MEJBQ2tCLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYztXQUN6QyxZQUFZOzs7OztpQkFLTixpQkFBaUI7UUFDMUIsWUFBWTtjQUNOLFdBQVcsa0VBQWtFLFNBQVM7YUFDdkYsWUFBWSxzQkFBc0IsWUFBWTtnQkFDM0MsV0FBVywrQkFBK0IsWUFBWSxxRUFBcUUsU0FBUztlQUNySSxZQUFZO3VCQUNKLG9CQUFvQixJQUFJLFlBQVk7Ozt1QkFHcEMsb0JBQW9COzs7cUJBR3RCLG9CQUFvQjs7O1FBR2pDLFlBQVksbUNBQW1DLGlCQUFpQixnQkFBZ0IsWUFBWTs7eUJBRTNFLFlBQVk7O29EQUVlLG9CQUFvQjs7RUFFdEU7WUFDSSxDQUFDLENBQUM7O2FBRUssaUJBQWlCOzhCQUNBLGlCQUFpQiw0Q0FBNEMsaUJBQWlCOzsrQkFFN0UsaUJBQWlCLDRDQUE0QyxpQkFBaUIsK0hBQStILGlCQUFpQjs7Ozs7K0JBSzlOLGlCQUFpQiw0Q0FBNEMsaUJBQWlCLDJJQUEySSxpQkFBaUI7Ozs7Ozs7O2dCQVF6UCxZQUFZLHlCQUF5QixZQUFZO2lCQUNoRCxZQUFZOzthQUVoQixZQUFZO2dCQUNULFdBQVcsaUJBQWlCLFlBQVksa0JBQWtCLFlBQVksMEVBQTBFLFlBQVksZ0RBQWdELFlBQVksK0NBQStDLFlBQVksc0NBQXNDLFlBQVkscUNBQXFDLFNBQVM7Ozs7YUFJdFgsWUFBWSxzQkFBc0IsWUFBWTtnQkFDM0MsV0FBVyw2RUFBNkUsU0FBUzs7O2FBR3BHLFlBQVksc0JBQXNCLFlBQVksZ0NBQWdDLFlBQVk7OztzQ0FHakUsWUFBWTs7Ozs7cUNBS2IsWUFBWTs4QkFDbkIsWUFBWTs7Ozs7O3VCQU1uQixpQkFBaUI7VUFDOUIsWUFBWTtnQkFDTixXQUFXLCtCQUErQixZQUFZLHFFQUFxRSxTQUFTO2VBQ3JJLFlBQVksc0JBQXNCLFlBQVk7cURBQ1IsWUFBWTs7a0RBRWYsb0JBQW9COzs7O2lCQUlyRCxZQUFZO3FCQUNSLG9CQUFvQiwrQkFBK0IsWUFBWTs7cUJBRS9ELFlBQVk7OztvQ0FHRyxXQUFXLHNCQUFzQixTQUFTO1VBQ3BFLFdBQVcsd0NBQXdDLFlBQVksNkJBQTZCLFlBQVksOERBQThELFNBQVM7O2FBRTVLLFlBQVksa0JBQWtCLFlBQVk7Ozs7MkJBSTVCLFlBQVk7Ozs7Ozt1REFNZ0IsWUFBWTs7Ozs7NEJBS3ZDLFlBQVk7VUFDOUIsWUFBWSxtQ0FBbUMsaUJBQWlCLGdCQUFnQixZQUFZOzsyQkFFM0UsWUFBWTs7MkRBRW9CLG9CQUFvQjs7O0dBRzVFLENBQUM7UUFFQSxJQUFJLENBQUMsV0FBVyxDQUFDLDBCQUEwQixtQkFBbUIsY0FBYyxFQUFFO1lBQzVFO2dCQUNFLFlBQVksRUFBRTtvQkFDWixPQUFPLEVBQUUsTUFBTSxnQkFBZ0IsOENBQThDLFFBQVEsSUFBSTtpQkFDMUY7YUFDRjtZQUNEO2dCQUNFLFlBQVksRUFBRTtvQkFDWixPQUFPLEVBQUUsV0FBVztvQkFDcEIsVUFBVSxFQUFFLFVBQVU7aUJBQ3ZCO2FBQ0Y7WUFDRDtnQkFDRSxZQUFZLEVBQUU7b0JBQ1osT0FBTyxFQUFFLGVBQWUsUUFBUSxFQUFFO2lCQUNuQzthQUNGO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsa0VBQWtFO1FBQ2xFLDhEQUE4RDtRQUM5RCxNQUFNLG9CQUFvQixHQUFHLG9CQUFvQixtQkFBbUIsTUFBTSxDQUFDO1FBRTNFLDRFQUE0RTtRQUM1RSxrQkFBa0I7UUFDbEIsNEVBQTRFO1FBQzVFLE1BQU0sR0FBRyxHQUFHLElBQUksa0JBQU8sQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFO1lBQ25DLGFBQWEsRUFBRSxNQUFNLENBQUMsYUFBYTtZQUNuQyxXQUFXLEVBQUUsR0FBRyxFQUFFLE1BQU07WUFDeEIsVUFBVSxFQUFFLENBQUMsYUFBYSxDQUFDO1lBQzNCLFFBQVEsRUFBRSxPQUFPO1NBQ2xCLENBQUMsQ0FBQztRQUVILE1BQU0sWUFBWSxHQUFHLElBQUksd0JBQVUsQ0FBQyxJQUFJLEVBQUUsY0FBYyxFQUFFO1lBQ3hELGFBQWEsRUFBRSxNQUFNLENBQUMsYUFBYTtZQUNuQyxLQUFLLEVBQUUsR0FBRyxDQUFDLEVBQUU7WUFDYixXQUFXLEVBQUUsR0FBRyxFQUFFLFNBQVM7WUFDM0IsU0FBUyxFQUFFLGFBQWE7WUFDeEIsUUFBUSxFQUFFLFFBQVE7WUFDbEIsc0JBQXNCLEVBQUUsS0FBSztTQUM5QixDQUFDLENBQUM7UUFFSCxNQUFNLGFBQWEsR0FBRyxJQUFJLHdCQUFVLENBQUMsSUFBSSxFQUFFLGVBQWUsRUFBRTtZQUMxRCxhQUFhLEVBQUUsTUFBTSxDQUFDLGFBQWE7WUFDbkMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxFQUFFO1lBQ2IsV0FBVyxFQUFFLEdBQUcsRUFBRSxVQUFVO1lBQzVCLFNBQVMsRUFBRSxhQUFhO1lBQ3hCLFFBQVEsRUFBRSxTQUFTO1lBQ25CLHNCQUFzQixFQUFFLElBQUk7U0FDN0IsQ0FBQyxDQUFDO1FBRUgsNEVBQTRFO1FBQzVFLGdEQUFnRDtRQUNoRCw0RUFBNEU7UUFDNUUsTUFBTSxrQkFBa0IsR0FBRyxJQUFJLHFDQUFnQixDQUFDLElBQUksRUFBRSxvQkFBb0IsRUFBRTtZQUMxRSxhQUFhLEVBQUUsTUFBTSxDQUFDLGFBQWE7WUFDbkMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxFQUFFO1lBQ2IsV0FBVyxFQUFFLEdBQUcsRUFBRSxZQUFZO1lBQzlCLG9CQUFvQixFQUFFO2dCQUNwQjtvQkFDRSxRQUFRLEVBQUUsR0FBRyxFQUFFLE1BQU07b0JBQ3JCLE1BQU0sRUFBRSxXQUFXO29CQUNuQixXQUFXLEVBQUUsK0JBQStCO29CQUM1QyxVQUFVLEVBQUU7d0JBQ1YsR0FBRyxFQUFFLEVBQUU7d0JBQ1AsR0FBRyxFQUFFLEVBQUU7cUJBQ1I7aUJBQ0Y7Z0JBQ0Q7b0JBQ0UsUUFBUSxFQUFFLEdBQUcsRUFBRSxNQUFNO29CQUNyQixNQUFNLEVBQUUsV0FBVztvQkFDbkIsV0FBVyxFQUFFLGlDQUFpQztvQkFDOUMsVUFBVSxFQUFFO3dCQUNWLEdBQUcsRUFBRSxHQUFHO3dCQUNSLEdBQUcsRUFBRSxHQUFHO3FCQUNUO2lCQUNGO2FBQ0Y7WUFDRCxtQkFBbUIsRUFBRTtnQkFDbkI7b0JBQ0UsUUFBUSxFQUFFLEtBQUs7b0JBQ2YsV0FBVyxFQUFFLFdBQVc7b0JBQ3hCLFdBQVcsRUFBRSw0QkFBNEI7aUJBQzFDO2FBQ0Y7U0FDRixDQUFDLENBQUM7UUFFSCw2Q0FBNkM7UUFDN0MsWUFBWSxDQUFDLFdBQVcsQ0FBQyxtQkFBbUIsRUFBRSxDQUFDLGtCQUFrQixDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFFdkUsNEVBQTRFO1FBQzVFLGtFQUFrRTtRQUNsRSw0RUFBNEU7UUFDNUUsTUFBTSxpQkFBaUIsR0FBRyxhQUFhLENBQUM7UUFDeEMsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLHFDQUFnQixDQUFDLElBQUksRUFBRSxxQkFBcUIsRUFBRTtZQUM1RSxhQUFhLEVBQUUsTUFBTSxDQUFDLGFBQWE7WUFDbkMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxFQUFFO1lBQ2IsV0FBVyxFQUFFLEdBQUcsRUFBRSxhQUFhO1lBQy9CLG9CQUFvQixFQUFFO2dCQUNwQjtvQkFDRSxRQUFRLEVBQUUsR0FBRyxFQUFFLE1BQU07b0JBQ3JCLE1BQU0sRUFBRSxpQkFBaUI7b0JBQ3pCLFdBQVcsRUFBRSw4REFBOEQ7b0JBQzNFLFVBQVUsRUFBRTt3QkFDVixHQUFHLEVBQUUsSUFBSTt3QkFDVCxHQUFHLEVBQUUsSUFBSTtxQkFDVjtpQkFDRjthQUNGO1lBQ0QsbUJBQW1CLEVBQUU7Z0JBQ25CO29CQUNFLFFBQVEsRUFBRSxLQUFLO29CQUNmLFdBQVcsRUFBRSxXQUFXO29CQUN4QixXQUFXLEVBQUUsNEJBQTRCO2lCQUMxQzthQUNGO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsOENBQThDO1FBQzlDLGFBQWEsQ0FBQyxXQUFXLENBQUMsbUJBQW1CLEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBRXpFLDRFQUE0RTtRQUM1RSx3REFBd0Q7UUFDeEQsNEVBQTRFO1FBQzVFLDJEQUEyRDtRQUMzRCx1R0FBdUc7UUFDdkcsOERBQThEO1FBQzlELE1BQU0sV0FBVyxHQUFHLElBQUksNENBQW1CLENBQUMsSUFBSSxFQUFFLGFBQWEsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUVyRSxNQUFNLGNBQWMsR0FBRyxJQUFJLHlDQUFrQixDQUFDLElBQUksRUFBRSxnQkFBZ0IsRUFBRTtZQUNwRSxhQUFhLEVBQUUsTUFBTSxDQUFDLGFBQWE7WUFDbkMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxFQUFFO1lBQ2IsV0FBVyxFQUFFLEdBQUcsRUFBRSxrQkFBa0I7WUFDcEMsUUFBUSxFQUFFO2dCQUNSO29CQUNFLFNBQVMsRUFBRSxXQUFXLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO2lCQUMxQzthQUNGO1NBQ0YsQ0FBQyxDQUFDO1FBRUgscUZBQXFGO1FBQ3JGLE1BQU0saUJBQWlCLEdBQUcsSUFBSSxpQ0FBYyxDQUFDLElBQUksRUFBRSxtQkFBbUIsRUFBRTtZQUN0RSxhQUFhLEVBQUUsTUFBTSxDQUFDLGFBQWE7WUFDbkMsS0FBSyxFQUFFLEdBQUcsQ0FBQyxFQUFFO1lBQ2IsV0FBVyxFQUFFLEdBQUcsRUFBRSxhQUFhO1lBQy9CLFVBQVUsRUFBRTtnQkFDVjtvQkFDRSxlQUFlLEVBQUUsY0FBYyxDQUFDLEVBQUU7b0JBQ2xDLFdBQVcsRUFBRSxXQUFXLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTO29CQUNsRCxlQUFlLEVBQUUsb0JBQW9CO29CQUNyQyxXQUFXLEVBQUUsdURBQXVEO2lCQUNyRTthQUNGO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsNENBQTRDO1FBQzVDLGFBQWEsQ0FBQyxXQUFXLENBQUMsZ0JBQWdCLEVBQUUsaUJBQWlCLENBQUMsRUFBRSxDQUFDLENBQUM7UUFFbEUsNEVBQTRFO1FBQzVFLHVEQUF1RDtRQUN2RCw0RUFBNEU7UUFDNUUsTUFBTSxlQUFlLEdBQUcsSUFBSSwyQ0FBbUIsQ0FBQyxJQUFJLEVBQUUsaUJBQWlCLEVBQUU7WUFDdkUsYUFBYSxFQUFFLE1BQU0sQ0FBQyxhQUFhO1lBQ25DLEtBQUssRUFBRSxHQUFHLENBQUMsRUFBRTtZQUNiLFdBQVcsRUFBRSxHQUFHLEVBQUUsTUFBTTtZQUN4QixPQUFPLEVBQUUsSUFBSTtTQUNkLENBQUMsQ0FBQztRQUVILCtFQUErRTtRQUMvRSxNQUFNLGdCQUFnQixHQUFHLElBQUksaUNBQWMsQ0FBQyxJQUFJLEVBQUUsa0JBQWtCLEVBQUU7WUFDcEUsYUFBYSxFQUFFLE1BQU0sQ0FBQyxhQUFhO1lBQ25DLEtBQUssRUFBRSxHQUFHLENBQUMsRUFBRTtZQUNiLFdBQVcsRUFBRSxHQUFHLEVBQUUsWUFBWTtZQUM5QixVQUFVLEVBQUU7Z0JBQ1Y7b0JBQ0UsZUFBZSxFQUFFLGVBQWUsQ0FBQyxFQUFFO29CQUNuQyxXQUFXLEVBQUUsV0FBVztvQkFDeEIsZUFBZSxFQUFFLFlBQVk7b0JBQzdCLFdBQVcsRUFBRSxpREFBaUQ7aUJBQy9EO2FBQ0Y7U0FDRixDQUFDLENBQUM7UUFFSCwyQ0FBMkM7UUFDM0MsWUFBWSxDQUFDLFdBQVcsQ0FBQyxnQkFBZ0IsRUFBRSxnQkFBZ0IsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUVoRSw0RUFBNEU7UUFDNUUsdUdBQXVHO1FBQ3ZHLDRFQUE0RTtRQUM1RSxNQUFNLGNBQWMsR0FBMkIsRUFBRSxDQUFDO1FBQ2xELElBQUksTUFBTSxDQUFDLEtBQUssSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUM7WUFDeEMsSUFBSSxNQUFNLENBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxFQUFFLENBQUM7Z0JBQzdCLHVEQUF1RDtnQkFDdkQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQztvQkFDNUIsTUFBTSxJQUFJLEtBQUssQ0FDYixvRkFBb0Y7d0JBQ3BGLHFEQUFxRCxDQUN0RCxDQUFDO2dCQUNKLENBQUM7Z0JBQ0QsaUhBQWlIO2dCQUNqSCwrRkFBK0Y7Z0JBQy9GLE1BQU0saUJBQWlCLEdBQ3JCLE9BQU8sQ0FBQyxHQUFHLENBQUMsZ0JBQWdCLElBQUksTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUM7Z0JBQ3hFLE1BQU0sZUFBZSxHQUFHLEdBQUcsRUFBRSxXQUFXLGlCQUFpQixFQUFFLENBQUM7Z0JBQzVELE1BQU0sV0FBVyxHQUFHLElBQUksMEJBQVcsQ0FBQyxJQUFJLEVBQUUsYUFBYSxFQUFFO29CQUN2RCxhQUFhLEVBQUUsTUFBTSxDQUFDLGFBQWE7b0JBQ25DLE9BQU8sRUFBRSxNQUFNLENBQUMsU0FBUztvQkFDekIsS0FBSyxFQUFFLE1BQU0sQ0FBQyxPQUFPO29CQUNyQixVQUFVLEVBQUUsZUFBZTtvQkFDM0IsV0FBVyxFQUFFLHNEQUFzRDtvQkFDbkUsYUFBYSxFQUFFO3dCQUNiLFdBQVcsRUFBRSxRQUFRO3dCQUNyQixPQUFPLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxFQUFFLE9BQU8sQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUM7cUJBQ3RFO2lCQUNGLENBQUMsQ0FBQztnQkFDSCxjQUFjLENBQUMsY0FBYyxHQUFHLFdBQVcsQ0FBQyxFQUFFLENBQUM7WUFDakQsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLGlFQUFpRTtnQkFDakUsT0FBTyxDQUFDLElBQUksQ0FDViwrRkFBK0Y7b0JBQy9GLHNIQUFzSDtvQkFDdEgsMEhBQTBILENBQzNILENBQUM7Z0JBQ0YsY0FBYyxDQUFDLE1BQU0sR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQzlDLENBQUM7UUFDSCxDQUFDO2FBQU0sSUFBSSxNQUFNLENBQUMsWUFBWSxFQUFFLElBQUksRUFBRSxFQUFFLENBQUM7WUFDdkMsY0FBYyxDQUFDLGNBQWMsR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQzdELENBQUM7UUFFRCw0RUFBNEU7UUFDNUUsOEJBQThCO1FBQzlCLDRFQUE0RTtRQUM1RSxNQUFNLFVBQVUsR0FBRyxJQUFJLHNDQUFpQixDQUFDLElBQUksRUFBRSxZQUFZLEVBQUU7WUFDM0QsYUFBYSxFQUFFLE1BQU0sQ0FBQyxhQUFhO1lBQ25DLFFBQVEsRUFBRSxZQUFZLENBQUMsRUFBRTtZQUN6QixZQUFZLEVBQUUsUUFBUTtZQUN0QixXQUFXLEVBQUUsR0FBRyxFQUFFLGNBQWM7U0FDakMsQ0FBQyxDQUFDO1FBRUgsNEVBQTRFO1FBQzVFLHNEQUFzRDtRQUN0RCw0RUFBNEU7UUFDNUUsTUFBTSxXQUFXLEdBQUcsSUFBSSw0Q0FBb0IsQ0FBQyxJQUFJLEVBQUUsYUFBYSxFQUFFO1lBQ2hFLGFBQWEsRUFBRSxNQUFNLENBQUMsYUFBYTtZQUNuQyxXQUFXLEVBQUUsTUFBTSxDQUFDLGVBQWU7WUFDbkMsU0FBUyxFQUFFLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQztTQUM5QixDQUFDLENBQUM7UUFFSCxpREFBaUQ7UUFDakQsTUFBTSxXQUFXLEdBQUcsSUFBSSxzQ0FBaUIsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFO1lBQzFELGFBQWEsRUFBRSxXQUFXLENBQUMsRUFBRTtZQUM3QixXQUFXLEVBQUUsTUFBTSxDQUFDLFlBQVk7WUFDaEMsS0FBSyxFQUFFLFFBQVE7WUFDZixXQUFXLEVBQUUsS0FBSztZQUNsQixnQkFBZ0IsRUFBRSxFQUFFO1lBQ3BCLE1BQU0sRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsU0FBUztTQUM1RSxDQUFDLENBQUM7UUFDSCxvREFBb0Q7UUFDcEQsNEVBQTRFO1FBQzVFLFdBQVcsQ0FBQyxXQUFXLENBQUMsWUFBWSxFQUFFLENBQUMsaUJBQWlCLG1CQUFtQixFQUFFLENBQUMsQ0FBQyxDQUFDO1FBRWhGLDRFQUE0RTtRQUM1RSwwRUFBMEU7UUFDMUUsNEVBQTRFO1FBQzVFLE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxlQUFlLElBQUksR0FBRyxDQUFDO1FBQ2pELE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxjQUFjLElBQUksVUFBVSxDQUFDO1FBQ3RELE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxZQUFZLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFFL0YsTUFBTSxhQUFhLEdBQUcsSUFBSSw0Q0FBb0IsQ0FBQyxJQUFJLEVBQUUsZUFBZSxFQUFFO1lBQ3BFLGFBQWEsRUFBRSxNQUFNLENBQUMsYUFBYTtZQUNuQyxTQUFTLEVBQUUsVUFBVSxDQUFDLEVBQUU7WUFDeEIsVUFBVTtZQUNWLFdBQVcsRUFBRSxHQUFHLEVBQUUsYUFBYTtZQUMvQixhQUFhLEVBQUU7Z0JBQ2IsTUFBTSxFQUFFO29CQUNOO3dCQUNFLElBQUksRUFBRSxTQUFTO3dCQUNmLE9BQU87d0JBQ1AsT0FBTyxFQUFFOzRCQUNQLElBQUksRUFBRSwwQkFBMEI7NEJBQ2hDLFVBQVUsRUFBRSxXQUFXLENBQUMsRUFBRTt5QkFDM0I7cUJBQ0Y7aUJBQ0Y7YUFDRjtTQUNGLENBQUMsQ0FBQztRQUNILGFBQWEsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBRTlDLDRFQUE0RTtRQUM1RSxVQUFVO1FBQ1YsNEVBQTRFO1FBQzVFLElBQUksdUJBQWUsQ0FBQyxJQUFJLEVBQUUsc0JBQXNCLEVBQUU7WUFDaEQsS0FBSyxFQUFFLGNBQWMsQ0FBQyxXQUFXO1lBQ2pDLFdBQVcsRUFBRSw4QkFBOEI7U0FDNUMsQ0FBQyxDQUFDO1FBRUgsSUFBSSx1QkFBZSxDQUFDLElBQUksRUFBRSxrQkFBa0IsRUFBRTtZQUM1QyxLQUFLLEVBQUUsVUFBVSxDQUFDLFFBQVE7WUFDMUIsV0FBVyxFQUFFLGdEQUFnRDtTQUM5RCxDQUFDLENBQUM7UUFFSCxJQUFJLHVCQUFlLENBQUMsSUFBSSxFQUFFLHFCQUFxQixFQUFFO1lBQy9DLEtBQUssRUFBRSxXQUFXLFVBQVUsQ0FBQyxRQUFRLEVBQUU7WUFDdkMsV0FBVyxFQUFFLCtEQUErRDtTQUM3RSxDQUFDLENBQUM7UUFFSCxJQUFJLHVCQUFlLENBQUMsSUFBSSxFQUFFLGFBQWEsRUFBRTtZQUN2QyxLQUFLLEVBQUUsV0FBVyxDQUFDLEVBQUU7WUFDckIsV0FBVyxFQUFFLHNFQUFzRTtTQUNwRixDQUFDLENBQUM7SUFDTCxDQUFDO0NBQ0Y7QUFwaEJELHNDQW9oQkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IFRlcnJhZm9ybVN0YWNrLCBUZXJyYWZvcm1PdXRwdXQgfSBmcm9tICdjZGt0Zic7XG5pbXBvcnQgeyBPY2lQcm92aWRlciB9IGZyb20gJy4uLy5nZW4vcHJvdmlkZXJzL29jaS9wcm92aWRlcic7XG5pbXBvcnQgeyBBcnRpZmFjdHNDb250YWluZXJSZXBvc2l0b3J5IH0gZnJvbSAnLi4vLmdlbi9wcm92aWRlcnMvb2NpL2FydGlmYWN0cy1jb250YWluZXItcmVwb3NpdG9yeSc7XG5pbXBvcnQgeyBDb3JlVmNuIH0gZnJvbSAnLi4vLmdlbi9wcm92aWRlcnMvb2NpL2NvcmUtdmNuJztcbmltcG9ydCB7IENvcmVTdWJuZXQgfSBmcm9tICcuLi8uZ2VuL3Byb3ZpZGVycy9vY2kvY29yZS1zdWJuZXQnO1xuaW1wb3J0IHsgQ29yZVNlY3VyaXR5TGlzdCB9IGZyb20gJy4uLy5nZW4vcHJvdmlkZXJzL29jaS9jb3JlLXNlY3VyaXR5LWxpc3QnO1xuaW1wb3J0IHsgQ29yZVNlcnZpY2VHYXRld2F5IH0gZnJvbSAnLi4vLmdlbi9wcm92aWRlcnMvb2NpL2NvcmUtc2VydmljZS1nYXRld2F5JztcbmltcG9ydCB7IERhdGFPY2lDb3JlU2VydmljZXMgfSBmcm9tICcuLi8uZ2VuL3Byb3ZpZGVycy9vY2kvZGF0YS1vY2ktY29yZS1zZXJ2aWNlcyc7XG5pbXBvcnQgeyBDb3JlUm91dGVUYWJsZSB9IGZyb20gJy4uLy5nZW4vcHJvdmlkZXJzL29jaS9jb3JlLXJvdXRlLXRhYmxlJztcbmltcG9ydCB7IENvcmVJbnRlcm5ldEdhdGV3YXkgfSBmcm9tICcuLi8uZ2VuL3Byb3ZpZGVycy9vY2kvY29yZS1pbnRlcm5ldC1nYXRld2F5JztcbmltcG9ydCB7IEFwaWdhdGV3YXlHYXRld2F5IH0gZnJvbSAnLi4vLmdlbi9wcm92aWRlcnMvb2NpL2FwaWdhdGV3YXktZ2F0ZXdheSc7XG5pbXBvcnQgeyBBcGlnYXRld2F5RGVwbG95bWVudCB9IGZyb20gJy4uLy5nZW4vcHJvdmlkZXJzL29jaS9hcGlnYXRld2F5LWRlcGxveW1lbnQnO1xuaW1wb3J0IHsgRnVuY3Rpb25zQXBwbGljYXRpb24gfSBmcm9tICcuLi8uZ2VuL3Byb3ZpZGVycy9vY2kvZnVuY3Rpb25zLWFwcGxpY2F0aW9uJztcbmltcG9ydCB7IEZ1bmN0aW9uc0Z1bmN0aW9uIH0gZnJvbSAnLi4vLmdlbi9wcm92aWRlcnMvb2NpL2Z1bmN0aW9ucy1mdW5jdGlvbic7XG5pbXBvcnQgeyBWYXVsdFNlY3JldCB9IGZyb20gJy4uLy5nZW4vcHJvdmlkZXJzL29jaS92YXVsdC1zZWNyZXQnO1xuaW1wb3J0IHsgT2NpQmFja2VuZENvbmZpZyB9IGZyb20gJy4uL2NvbmZpZy9vY2ktY29uZmlnJztcbmltcG9ydCAqIGFzIGNyeXB0byBmcm9tICdjcnlwdG8nO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcblxuZXhwb3J0IGludGVyZmFjZSBPY2lTdGFja0NvbmZpZyB7XG4gIGNvbXBhcnRtZW50SWQ6IHN0cmluZztcbiAgb2NpckNvbXBhcnRtZW50SWQ/OiBzdHJpbmc7XG4gIHRlbmFuY3lJZDogc3RyaW5nO1xuICByZWdpb246IHN0cmluZztcbiAgbmFtZXNwYWNlOiBzdHJpbmc7XG4gIGZ1bmN0aW9uQXBwTmFtZTogc3RyaW5nO1xuICBmdW5jdGlvbk5hbWU6IHN0cmluZztcbiAgb2NpclJlcG9zaXRvcnlOYW1lPzogc3RyaW5nO1xuICAvKiogV2hlbiBzZXQgd2l0aCB2YXVsdE9jaWQgYW5kIGtleU9jaWQsIHN0YWNrIGNyZWF0ZXMgVmF1bHQgc2VjcmV0IChwZy11cmwpIGFuZCBmdW5jdGlvbiB1c2VzIGl0LiAqL1xuICBwZ1VybD86IHN0cmluZztcbiAgLyoqIFZhdWx0IE9DSUQgKHJlcXVpcmVkIHdpdGgga2V5T2NpZCB3aGVuIHBnVXJsIGlzIHNldCBhbmQgdXNpbmcgVmF1bHQpLiAqL1xuICB2YXVsdE9jaWQ/OiBzdHJpbmc7XG4gIC8qKiBLTVMgS2V5IE9DSUQgKHJlcXVpcmVkIHdoZW4gdmF1bHRPY2lkIGlzIHNldCkuICovXG4gIGtleU9jaWQ/OiBzdHJpbmc7XG4gIC8qKiBXaGVuIHBnVXJsIGlzIG5vdCBzZXQ6IGV4aXN0aW5nIE9DSSBWYXVsdCBzZWNyZXQgT0NJRCBmb3IgUEcgKGZ1bmN0aW9uIGNvbmZpZyBrZXk6IFBHX1NFQ1JFVF9PQ0lEKS4gKi9cbiAgcGdTZWNyZXRPY2lkPzogc3RyaW5nO1xuICAvKiogQVBJIEdhdGV3YXkgZGVwbG95bWVudCBwYXRoIHByZWZpeC4gRGVmYXVsdCAnLycuICovXG4gIGFwaUd3UGF0aFByZWZpeD86IHN0cmluZztcbiAgLyoqIEFQSSBHYXRld2F5IHJvdXRlIHBhdGguIERlZmF1bHQgJy97cGF0aCp9Jy4gKi9cbiAgYXBpR3dSb3V0ZVBhdGg/OiBzdHJpbmc7XG4gIC8qKiBBUEkgR2F0ZXdheSByb3V0ZSBtZXRob2RzLiBEZWZhdWx0IFsnR0VUJywgJ1BPU1QnLCAnT1BUSU9OUyddLiAqL1xuICBhcGlHd01ldGhvZHM/OiBzdHJpbmdbXTtcbiAgYmFja2VuZD86IE9jaUJhY2tlbmRDb25maWc7XG59XG5cbmV4cG9ydCBjbGFzcyBGdW5jdGlvblN0YWNrIGV4dGVuZHMgVGVycmFmb3JtU3RhY2sge1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBjb25maWc6IE9jaVN0YWNrQ29uZmlnKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBCYWNrZW5kICYgUHJvdmlkZXJcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgaWYgKGNvbmZpZy5iYWNrZW5kICYmIGNvbmZpZy5iYWNrZW5kLnR5cGUgIT09ICdsb2NhbCcpIHtcbiAgICAgIGlmIChjb25maWcuYmFja2VuZC50eXBlID09PSAnb2NpJykge1xuICAgICAgICB0aGlzLmFkZE92ZXJyaWRlKCd0ZXJyYWZvcm0uYmFja2VuZCcsIHtcbiAgICAgICAgICBvY2k6IHtcbiAgICAgICAgICAgIGJ1Y2tldDogY29uZmlnLmJhY2tlbmQuYnVja2V0LFxuICAgICAgICAgICAgbmFtZXNwYWNlOiBjb25maWcubmFtZXNwYWNlLFxuICAgICAgICAgICAga2V5OiBjb25maWcuYmFja2VuZC5rZXkgfHwgYCR7aWR9L3RlcnJhZm9ybS50ZnN0YXRlYCxcbiAgICAgICAgICAgIHJlZ2lvbjogY29uZmlnLnJlZ2lvbixcbiAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSBpZiAoY29uZmlnLmJhY2tlbmQudHlwZSA9PT0gJ2h0dHAnKSB7XG4gICAgICAgIGNvbnN0IGh0dHBCYWNrZW5kOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHtcbiAgICAgICAgICBhZGRyZXNzOiBjb25maWcuYmFja2VuZC5hZGRyZXNzLFxuICAgICAgICAgIHVwZGF0ZV9tZXRob2Q6IGNvbmZpZy5iYWNrZW5kLnVwZGF0ZU1ldGhvZCB8fCAnUFVUJyxcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKGNvbmZpZy5iYWNrZW5kLmxvY2tBZGRyZXNzKSBodHRwQmFja2VuZC5sb2NrX2FkZHJlc3MgPSBjb25maWcuYmFja2VuZC5sb2NrQWRkcmVzcztcbiAgICAgICAgaWYgKGNvbmZpZy5iYWNrZW5kLnVubG9ja0FkZHJlc3MpIGh0dHBCYWNrZW5kLnVubG9ja19hZGRyZXNzID0gY29uZmlnLmJhY2tlbmQudW5sb2NrQWRkcmVzcztcbiAgICAgICAgdGhpcy5hZGRPdmVycmlkZSgndGVycmFmb3JtLmJhY2tlbmQnLCB7IGh0dHA6IGh0dHBCYWNrZW5kIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIG5ldyBPY2lQcm92aWRlcih0aGlzLCAnb2NpJywge1xuICAgICAgcmVnaW9uOiBjb25maWcucmVnaW9uLFxuICAgICAgdGVuYW5jeU9jaWQ6IGNvbmZpZy50ZW5hbmN5SWQsXG4gICAgfSk7XG5cbiAgICAvLyBBZGQgbnVsbCBwcm92aWRlciB1c2luZyBhZGRPdmVycmlkZSAoYXZvaWRzIG5lZWRpbmcgdG8gZ2VuZXJhdGUgdHlwZXMpXG4gICAgdGhpcy5hZGRPdmVycmlkZSgndGVycmFmb3JtLnJlcXVpcmVkX3Byb3ZpZGVycy5udWxsJywge1xuICAgICAgc291cmNlOiAnaGFzaGljb3JwL251bGwnLFxuICAgICAgdmVyc2lvbjogJ34+IDMuMCcsXG4gICAgfSk7XG5cbiAgICBjb25zdCBvY2lyQ29tcGFydG1lbnRJZCA9IGNvbmZpZy5vY2lyQ29tcGFydG1lbnRJZCB8fCBjb25maWcuY29tcGFydG1lbnRJZDtcbiAgICBjb25zdCBvY2lyUmVwb05hbWUgPSBjb25maWcub2NpclJlcG9zaXRvcnlOYW1lIHx8IGNvbmZpZy5mdW5jdGlvbk5hbWU7XG5cbiAgICBpZiAob2NpckNvbXBhcnRtZW50SWQuaW5jbHVkZXMoJ3Jvb3QnKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnT0NJUiByZXBvc2l0b3J5IGNhbm5vdCBiZSBjcmVhdGVkIGluIHJvb3QgY29tcGFydG1lbnQuICcgK1xuICAgICAgICAgICdQbGVhc2Ugc2V0IE9DSV9PQ0lSX0NPTVBBUlRNRU5UX0lEIHRvIHlvdXIgaG9tZSBjb21wYXJ0bWVudCBPQ0lELidcbiAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIE9DSVIgQ29udGFpbmVyIFJlcG9zaXRvcnlcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgY29uc3Qgb2NpclJlcG9zaXRvcnkgPSBuZXcgQXJ0aWZhY3RzQ29udGFpbmVyUmVwb3NpdG9yeSh0aGlzLCAnT2NpclJlcG9zaXRvcnknLCB7XG4gICAgICBjb21wYXJ0bWVudElkOiBvY2lyQ29tcGFydG1lbnRJZCxcbiAgICAgIGRpc3BsYXlOYW1lOiBvY2lyUmVwb05hbWUsXG4gICAgICBpc1B1YmxpYzogZmFsc2UsXG4gICAgICBpc0ltbXV0YWJsZTogZmFsc2UsXG4gICAgfSk7XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gQnVpbGQgYW5kIFB1c2ggRG9ja2VyIEltYWdlIHRvIE9DSVIgKGFmdGVyIHJlcG9zaXRvcnkgaXMgY3JlYXRlZClcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgY29uc3QgaW1hZ2VVcmwgPSBgJHtjb25maWcucmVnaW9ufS5vY2lyLmlvLyR7Y29uZmlnLm5hbWVzcGFjZX0vJHtvY2lyUmVwb05hbWV9OmxhdGVzdGA7XG4gICAgXG4gICAgLy8gR2V0IE9DSVIgbG9naW4gdXNlcm5hbWUgZnJvbSBlbnYgb3IgdHJ5IHRvIGdldCBmcm9tIE9DSSBDTElcbiAgICAvLyBGb3JtYXQ6IDx0ZW5hbmN5LW5hbWVzcGFjZT4vPHVzZXJuYW1lPiAoZS5nLiwgZnJzeHd0anNsZjM1L29yYWNsZWlkZW50aXR5Y2xvdWRzZXJ2aWNlL3VzZXJAZXhhbXBsZS5jb20pXG4gICAgLy8gRGVmYXVsdCB3aWxsIGJlIGNvbnN0cnVjdGVkIGluIHRoZSBzY3JpcHQgaWYgbm90IHByb3ZpZGVkXG4gICAgY29uc3Qgb2NpclVzZXJuYW1lID0gcHJvY2Vzcy5lbnYuT0NJX09DSVJfVVNFUk5BTUUgfHwgJ0FVVE9fREVURUNUJztcbiAgICBcbiAgICAvLyBmdW5jdGlvbi1jb2RlIGlzIGF0IGphdmEtZnVuY3Rpb24vZnVuY3Rpb24tY29kZSAoc2libGluZyBvZiBvY2ktY2RrKVxuICAgIC8vIFJlc29sdmUgcGF0aCByZWxhdGl2ZSB0byB0aGlzIGZpbGUncyBsb2NhdGlvblxuICAgIC8vIENvbXBpbGVkIEpTIGlzIGF0IGxpYi9saWIvZnVuY3Rpb24tc3RhY2suanMsIHNvIF9fZGlybmFtZSBpcyBsaWIvbGliL1xuICAgIC8vIEZyb20gbGliL2xpYi86IC4uLyBnb2VzIHRvIGxpYi8sIC4uLyBnb2VzIHRvIG9jaS1jZGsvLCAuLi8gZ29lcyB0byBqYXZhLWZ1bmN0aW9uLywgdGhlbiBmdW5jdGlvbi1jb2RlL1xuICAgIGNvbnN0IGZ1bmN0aW9uQ29kZVBhdGggPSBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCAnLi4nLCAnLi4nLCAnLi4nLCAnZnVuY3Rpb24tY29kZScpO1xuICAgIFxuICAgIC8vIENyZWF0ZSBudWxsX3Jlc291cmNlIHVzaW5nIGFkZE92ZXJyaWRlIChzaW5jZSB3ZSBjYW4ndCBnZW5lcmF0ZSB0eXBlcyBkdWUgdG8gbmV0d29yayBpc3N1ZXMpXG4gICAgLy8gVGhpcyBjcmVhdGVzIGEgVGVycmFmb3JtIG51bGxfcmVzb3VyY2UgdGhhdCBidWlsZHMgYW5kIHB1c2hlcyB0aGUgRG9ja2VyIGltYWdlXG4gICAgY29uc3QgYnVpbGRBbmRQdXNoSW1hZ2VJZCA9ICdCdWlsZEFuZFB1c2hJbWFnZSc7XG4gICAgLy8gVXNlIHRoZSBUZXJyYWZvcm0gcmVzb3VyY2UgcmVmZXJlbmNlIGRpcmVjdGx5IChub3QgaW50ZXJwb2xhdGVkIHN0cmluZylcbiAgICAvLyBkZXBlbmRzX29uIGV4cGVjdHMgcmVzb3VyY2UgcmVmZXJlbmNlcywgbm90IGF0dHJpYnV0ZSByZWZlcmVuY2VzXG4gICAgdGhpcy5hZGRPdmVycmlkZShgcmVzb3VyY2UubnVsbF9yZXNvdXJjZS4ke2J1aWxkQW5kUHVzaEltYWdlSWR9LmRlcGVuZHNfb25gLCBbXG4gICAgICAnb2NpX2FydGlmYWN0c19jb250YWluZXJfcmVwb3NpdG9yeS5PY2lyUmVwb3NpdG9yeScsXG4gICAgXSk7XG4gICAgdGhpcy5hZGRPdmVycmlkZShgcmVzb3VyY2UubnVsbF9yZXNvdXJjZS4ke2J1aWxkQW5kUHVzaEltYWdlSWR9LnRyaWdnZXJzYCwge1xuICAgICAgcmVwb19uYW1lOiBvY2lyUmVwb05hbWUsXG4gICAgICBpbWFnZV91cmw6IGltYWdlVXJsLFxuICAgICAgbmFtZXNwYWNlOiBjb25maWcubmFtZXNwYWNlLFxuICAgICAgcmVnaW9uOiBjb25maWcucmVnaW9uLFxuICAgIH0pO1xuICAgIFxuICAgIC8vIEdlbmVyYXRlIGF1dGggdG9rZW4gYW5kIGxvZ2luIHNjcmlwdFxuICAgIC8vIElmIE9DSV9BVVRIX1RPS0VOIGlzIHNldCwgdXNlIGl0OyBvdGhlcndpc2UgZ2VuZXJhdGUgb25lIHZpYSBPQ0kgQ0xJXG4gICAgY29uc3QgcmVnaW9uUGxhY2Vob2xkZXIgPSBjb25maWcucmVnaW9uO1xuICAgIGNvbnN0IG5hbWVzcGFjZVBsYWNlaG9sZGVyID0gY29uZmlnLm5hbWVzcGFjZTtcbiAgICBjb25zdCBvY2lyVXNlcm5hbWVWYWx1ZSA9IG9jaXJVc2VybmFtZTsgLy8gQ2FwdHVyZSB2YWx1ZSBmb3IgdGVtcGxhdGUgc3RyaW5nXG4gICAgLy8gVXNlIHN0cmluZyBjb25jYXRlbmF0aW9uIHRvIGF2b2lkIFR5cGVTY3JpcHQgcGFyc2luZyBpc3N1ZXMgd2l0aCAke30gaW4gc2hlbGwgc2NyaXB0c1xuICAgIGNvbnN0IGRvbGxhclNpZ24gPSAnJCc7XG4gICAgY29uc3QgZG9sbGFyRG9sbGFyID0gJyQkJztcbiAgICAvLyBVc2UgYmFja3RpY2tzIGZvciBjb21tYW5kIHN1YnN0aXR1dGlvbiB0byBhdm9pZCBjb21wbGV4ICQoKSBlc2NhcGluZ1xuICAgIC8vIEluIFR5cGVTY3JpcHQgdGVtcGxhdGUgc3RyaW5ncywgYmFja3RpY2tzIG5lZWQgdG8gYmUgZXNjYXBlZCBhcyBcXGBcbiAgICBjb25zdCBjbWRTdWJTdGFydCA9ICdcXGAnO1xuICAgIGNvbnN0IGNtZFN1YkVuZCA9ICdcXGAnO1xuICAgIGNvbnN0IGxvZ2luU2NyaXB0ID0gcHJvY2Vzcy5lbnYuT0NJX0FVVEhfVE9LRU4gXG4gICAgICA/IGAjIFVzaW5nIHByb3ZpZGVkIE9DSV9BVVRIX1RPS0VOXG5leHBvcnQgT0NJUl9BVVRIX1RPS0VOPVwiJHtwcm9jZXNzLmVudi5PQ0lfQVVUSF9UT0tFTn1cIlxuaWYgWyAteiBcIiR7ZG9sbGFyRG9sbGFyfU9DSVJfQVVUSF9UT0tFTlwiIF07IHRoZW5cbiAgZWNobyBcIkVycm9yOiBPQ0lfQVVUSF9UT0tFTiBpcyBlbXB0eS4gUGxlYXNlIHNldCBhIHZhbGlkIHRva2VuLlwiXG4gIGV4aXQgMVxuZmlcbiMgVXNlIHByb3ZpZGVkIHVzZXJuYW1lIG9yIGF1dG8tZGV0ZWN0XG5PQ0lSX1VTRVJOQU1FPVwiJHtvY2lyVXNlcm5hbWVWYWx1ZX1cIlxuaWYgWyBcIiR7ZG9sbGFyRG9sbGFyfU9DSVJfVVNFUk5BTUVcIiA9PSBcIkFVVE9fREVURUNUXCIgXTsgdGhlblxuICBVU0VSX09DSUQ9JHtjbWRTdWJTdGFydH1vY2kgaWFtIHVzZXIgbGlzdCAtLXF1ZXJ5IFwiZGF0YVswXS5pZFwiIC0tcmF3LW91dHB1dCAyPi9kZXYvbnVsbCR7Y21kU3ViRW5kfVxuICBpZiBbIC1uIFwiJHtkb2xsYXJEb2xsYXJ9VVNFUl9PQ0lEXCIgXSAmJiBbIFwiJHtkb2xsYXJEb2xsYXJ9VVNFUl9PQ0lEXCIgIT0gXCJudWxsXCIgXTsgdGhlblxuICAgIFVTRVJfTkFNRT0ke2NtZFN1YlN0YXJ0fW9jaSBpYW0gdXNlciBnZXQgLS11c2VyLWlkIFwiJHtkb2xsYXJEb2xsYXJ9VVNFUl9PQ0lEXCIgLS1xdWVyeSAnZGF0YS5uYW1lJyAtLXJhdy1vdXRwdXQgMj4vZGV2L251bGwgfHwgZWNobyBcIlwiJHtjbWRTdWJFbmR9XG4gICAgaWYgWyAtbiBcIiR7ZG9sbGFyRG9sbGFyfVVTRVJfTkFNRVwiIF07IHRoZW5cbiAgICAgIE9DSVJfVVNFUk5BTUU9XCIke25hbWVzcGFjZVBsYWNlaG9sZGVyfS8ke2RvbGxhckRvbGxhcn1VU0VSX05BTUVcIlxuICAgIGVsc2VcbiAgICAgIGVjaG8gXCJXYXJuaW5nOiBDb3VsZCBub3QgYXV0by1kZXRlY3QgdXNlcm5hbWUuIFVzaW5nIGRlZmF1bHQgZm9ybWF0LlwiXG4gICAgICBPQ0lSX1VTRVJOQU1FPVwiJHtuYW1lc3BhY2VQbGFjZWhvbGRlcn0vdXNlclwiXG4gICAgZmlcbiAgZWxzZVxuICAgIE9DSVJfVVNFUk5BTUU9XCIke25hbWVzcGFjZVBsYWNlaG9sZGVyfS91c2VyXCJcbiAgZmlcbmZpXG5lY2hvIFwiJHtkb2xsYXJEb2xsYXJ9T0NJUl9BVVRIX1RPS0VOXCIgfCBkb2NrZXIgbG9naW4gJHtyZWdpb25QbGFjZWhvbGRlcn0ub2Npci5pbyAtdSBcIiR7ZG9sbGFyRG9sbGFyfU9DSVJfVVNFUk5BTUVcIiAtLXBhc3N3b3JkLXN0ZGluID4vZGV2L251bGwgMj4mMSB8fCB7XG4gIGVjaG8gXCJFcnJvcjogRG9ja2VyIGxvZ2luIGZhaWxlZC4gQ2hlY2sgeW91ciBPQ0lfQVVUSF9UT0tFTiBhbmQgdXNlcm5hbWUgZm9ybWF0LlwiID4mMlxuICBlY2hvIFwiVXNlcm5hbWUgdXNlZDogJHtkb2xsYXJEb2xsYXJ9T0NJUl9VU0VSTkFNRVwiID4mMlxuICBlY2hvIFwiVXNlcm5hbWUgZm9ybWF0IHNob3VsZCBiZTogPHRlbmFuY3ktbmFtZXNwYWNlPi88dXNlcm5hbWU+XCIgPiYyXG4gIGVjaG8gXCJTZXQgbWFudWFsbHk6IGV4cG9ydCBPQ0lfT0NJUl9VU0VSTkFNRT1cXFxcXCIke25hbWVzcGFjZVBsYWNlaG9sZGVyfS95b3VyLWFjdHVhbC11c2VybmFtZVxcXFxcIlwiID4mMlxuICBleGl0IDFcbn1gXG4gICAgICA6IGAjIEdlbmVyYXRlIE9DSVIgYXV0aCB0b2tlbiB2aWEgT0NJIENMSSBhbmQgbG9naW4gdG8gT0NJUlxuIyBUcnkgcmF3LXJlcXVlc3QgbWV0aG9kIGZpcnN0ICh1c2VzIGRlZmF1bHQgT0NJIENMSSBhdXRoIGZyb20gY29uZmlnKVxuT0NJUl9IT1NUPVwiJHtyZWdpb25QbGFjZWhvbGRlcn0ub2Npci5pb1wiXG5pZiBvY2kgcmF3LXJlcXVlc3QgLS1yZWdpb24gJHtyZWdpb25QbGFjZWhvbGRlcn0gLS1odHRwLW1ldGhvZCBHRVQgLS10YXJnZXQtdXJpIFwiaHR0cHM6Ly8ke3JlZ2lvblBsYWNlaG9sZGVyfS5vY2lyLmlvLzIwMTgwNDE5L2RvY2tlci90b2tlblwiID4vZGV2L251bGwgMj4mMTsgdGhlblxuICBpZiBjb21tYW5kIC12IGpxID4vZGV2L251bGwgMj4mMTsgdGhlblxuICAgIG9jaSByYXctcmVxdWVzdCAtLXJlZ2lvbiAke3JlZ2lvblBsYWNlaG9sZGVyfSAtLWh0dHAtbWV0aG9kIEdFVCAtLXRhcmdldC11cmkgXCJodHRwczovLyR7cmVnaW9uUGxhY2Vob2xkZXJ9Lm9jaXIuaW8vMjAxODA0MTkvZG9ja2VyL3Rva2VuXCIgMj4vZGV2L251bGwgfCBqcSAtciAuZGF0YS50b2tlbiAyPi9kZXYvbnVsbCB8IGRvY2tlciBsb2dpbiAtdSBCRUFSRVJfVE9LRU4gLS1wYXNzd29yZC1zdGRpbiAke3JlZ2lvblBsYWNlaG9sZGVyfS5vY2lyLmlvID4vZGV2L251bGwgMj4mMSB8fCB7XG4gICAgICBlY2hvIFwiRXJyb3I6IERvY2tlciBsb2dpbiB3aXRoIHJhdy1yZXF1ZXN0IGZhaWxlZC5cIiA+JjJcbiAgICAgIGV4aXQgMVxuICAgIH1cbiAgZWxzZVxuICAgIG9jaSByYXctcmVxdWVzdCAtLXJlZ2lvbiAke3JlZ2lvblBsYWNlaG9sZGVyfSAtLWh0dHAtbWV0aG9kIEdFVCAtLXRhcmdldC11cmkgXCJodHRwczovLyR7cmVnaW9uUGxhY2Vob2xkZXJ9Lm9jaXIuaW8vMjAxODA0MTkvZG9ja2VyL3Rva2VuXCIgMj4vZGV2L251bGwgfCBncmVwIC1vICdcInRva2VuXCI6XCJbXlwiXSpcIicgfCBjdXQgLWQnXCInIC1mNCB8IGRvY2tlciBsb2dpbiAtdSBCRUFSRVJfVE9LRU4gLS1wYXNzd29yZC1zdGRpbiAke3JlZ2lvblBsYWNlaG9sZGVyfS5vY2lyLmlvID4vZGV2L251bGwgMj4mMSB8fCB7XG4gICAgICBlY2hvIFwiRXJyb3I6IERvY2tlciBsb2dpbiB3aXRoIHJhdy1yZXF1ZXN0IGZhaWxlZC5cIiA+JjJcbiAgICAgIGV4aXQgMVxuICAgIH1cbiAgZmlcbmVsc2VcbiAgIyBGYWxsYmFjayB0byBhdXRoIHRva2VuIG1ldGhvZCAoZm9yIGxvY2FsaG9zdClcbiAgIyBHZXQgdXNlciBPQ0lEIGZyb20gQ0xJIGNvbmZpZyAoc2FtZSBhcHByb2FjaCBhcyByZWZlcmVuY2Ugc2NyaXB0KVxuICBPQ0lfQ09ORklHPVwiJHtkb2xsYXJEb2xsYXJ9e09DSV9DTElfQ09ORklHX0ZJTEU6LSR7ZG9sbGFyRG9sbGFyfUhPTUUvLm9jaS9jb25maWd9XCJcbiAgT0NJX1BST0ZJTEU9XCIke2RvbGxhckRvbGxhcn17T0NJX0NMSV9QUk9GSUxFOi1ERUZBVUxUfVwiXG4gIFVTRVJfT0NJRD1cIlwiXG4gIGlmIFsgLWYgXCIke2RvbGxhckRvbGxhcn1PQ0lfQ09ORklHXCIgXTsgdGhlblxuICAgIFVTRVJfT0NJRD0ke2NtZFN1YlN0YXJ0fWF3ayAtdiBwcm9mPVwiWyR7ZG9sbGFyRG9sbGFyfU9DSV9QUk9GSUxFXVwiICcke2RvbGxhckRvbGxhcn0wID09IHByb2YgeyBpbl9wcm9maWxlPTE7IG5leHQgfSAvXlxcXFxbLyB7IGluX3Byb2ZpbGU9MCB9IGluX3Byb2ZpbGUgJiYgJHtkb2xsYXJEb2xsYXJ9MCB+IC9eW1s6c3BhY2U6XV0qdXNlcltbOnNwYWNlOl1dKj0vIHsgc3BsaXQoJHtkb2xsYXJEb2xsYXJ9MCwgYSwgXCI9XCIpOyBnc3ViKC9eW1s6c3BhY2U6XV0rfFtbOnNwYWNlOl1dKyR7ZG9sbGFyRG9sbGFyfS8sIFwiXCIsIGFbMl0pOyBwcmludCBhWzJdOyBleGl0IH0nIFwiJHtkb2xsYXJEb2xsYXJ9T0NJX0NPTkZJR1wiIDI+L2Rldi9udWxsIHx8IGVjaG8gXCJcIiR7Y21kU3ViRW5kfVxuICBmaVxuXG4gICMgRmFsbGJhY2sgdG8gdXNlciBsaXN0IGlmIG5vdCBpbiBjb25maWdcbiAgaWYgWyAteiBcIiR7ZG9sbGFyRG9sbGFyfVVTRVJfT0NJRFwiIF0gfHwgWyBcIiR7ZG9sbGFyRG9sbGFyfVVTRVJfT0NJRFwiICE9IG9jaWQxLiogXTsgdGhlblxuICAgIFVTRVJfT0NJRD0ke2NtZFN1YlN0YXJ0fW9jaSBpYW0gdXNlciBsaXN0IC0tcXVlcnkgXCJkYXRhWzBdLmlkXCIgLS1yYXctb3V0cHV0IDI+L2Rldi9udWxsIHx8IGVjaG8gXCJcIiR7Y21kU3ViRW5kfVxuICBmaVxuXG4gIGlmIFsgLXogXCIke2RvbGxhckRvbGxhcn1VU0VSX09DSURcIiBdIHx8IFsgXCIke2RvbGxhckRvbGxhcn1VU0VSX09DSURcIiA9PSBcIm51bGxcIiBdIHx8IFsgXCIke2RvbGxhckRvbGxhcn1VU0VSX09DSURcIiAhPSBvY2lkMS4qIF07IHRoZW5cbiAgICBlY2hvIFwiRXJyb3I6IENvdWxkIG5vdCBnZXQgdXNlciBPQ0lELiBTZXQgT0NJX0FVVEhfVE9LRU4gbWFudWFsbHkgb3IgZW5zdXJlIE9DSSBDTEkgaXMgY29uZmlndXJlZC5cIiA+JjJcbiAgICBlY2hvIFwiUnVuOiBvY2kgaWFtIHVzZXIgbGlzdFwiID4mMlxuICAgIGVjaG8gXCJPciBjaGVjayB5b3VyIE9DSSBjb25maWc6ICR7ZG9sbGFyRG9sbGFyfU9DSV9DT05GSUdcIiA+JjJcbiAgICBleGl0IDFcbiAgZmlcblxuICAjIFZlcmlmeSB1c2VyIGV4aXN0cyBiZWZvcmUgdHJ5aW5nIHRvIGNyZWF0ZSB0b2tlblxuICBpZiAhIG9jaSBpYW0gdXNlciBnZXQgLS11c2VyLWlkIFwiJHtkb2xsYXJEb2xsYXJ9VVNFUl9PQ0lEXCIgPi9kZXYvbnVsbCAyPiYxOyB0aGVuXG4gICAgZWNobyBcIkVycm9yOiBVc2VyIE9DSUQgJyR7ZG9sbGFyRG9sbGFyfVVTRVJfT0NJRCcgbm90IGZvdW5kIG9yIG5vdCBhY2Nlc3NpYmxlLlwiID4mMlxuICAgIGVjaG8gXCJQbGVhc2UgdmVyaWZ5IHlvdXIgT0NJIENMSSBjb25maWd1cmF0aW9uIG9yIHNldCBPQ0lfQVVUSF9UT0tFTiBtYW51YWxseS5cIiA+JjJcbiAgICBleGl0IDFcbiAgZmlcblxuICAjIEdldCB1c2VybmFtZSBmb3IgT0NJUiBsb2dpblxuICBPQ0lSX1VTRVJOQU1FX1ZBUj1cIiR7b2NpclVzZXJuYW1lVmFsdWV9XCJcbiAgaWYgWyBcIiR7ZG9sbGFyRG9sbGFyfU9DSVJfVVNFUk5BTUVfVkFSXCIgPT0gXCJBVVRPX0RFVEVDVFwiIF07IHRoZW5cbiAgICBVU0VSX05BTUU9JHtjbWRTdWJTdGFydH1vY2kgaWFtIHVzZXIgZ2V0IC0tdXNlci1pZCBcIiR7ZG9sbGFyRG9sbGFyfVVTRVJfT0NJRFwiIC0tcXVlcnkgJ2RhdGEubmFtZScgLS1yYXctb3V0cHV0IDI+L2Rldi9udWxsIHx8IGVjaG8gXCJcIiR7Y21kU3ViRW5kfVxuICAgIGlmIFsgLXogXCIke2RvbGxhckRvbGxhcn1VU0VSX05BTUVcIiBdIHx8IFsgXCIke2RvbGxhckRvbGxhcn1VU0VSX05BTUVcIiA9PSBcIm51bGxcIiBdOyB0aGVuXG4gICAgICBlY2hvIFwiRXJyb3I6IENvdWxkIG5vdCBnZXQgdXNlcm5hbWUgZm9yIHVzZXIgJHtkb2xsYXJEb2xsYXJ9VVNFUl9PQ0lELlwiID4mMlxuICAgICAgZWNobyBcIlBsZWFzZSBzZXQgT0NJX09DSVJfVVNFUk5BTUUgbWFudWFsbHkuXCIgPiYyXG4gICAgICBlY2hvIFwiRm9ybWF0OiBleHBvcnQgT0NJX09DSVJfVVNFUk5BTUU9XFxcXFwiJHtuYW1lc3BhY2VQbGFjZWhvbGRlcn0veW91ci11c2VybmFtZVxcXFxcIlwiID4mMlxuICAgICAgZXhpdCAxXG4gICAgZmlcbiAgICAjIEV4dHJhY3QgdXNlcm5hbWUgcGFydCBpZiBpdCBjb250YWlucyBkb21haW4gKGUuZy4sIFwib3JhY2xlaWRlbnRpdHljbG91ZHNlcnZpY2UvdXNlckBleGFtcGxlLmNvbVwiIC0+IFwidXNlckBleGFtcGxlLmNvbVwiKVxuICAgIFVTRVJfTkFNRT1cIiR7ZG9sbGFyRG9sbGFyfXtVU0VSX05BTUUjIyovfVwiXG4gICAgT0NJUl9VU0VSTkFNRT1cIiR7bmFtZXNwYWNlUGxhY2Vob2xkZXJ9L29yYWNsZWlkZW50aXR5Y2xvdWRzZXJ2aWNlLyR7ZG9sbGFyRG9sbGFyfVVTRVJfTkFNRVwiXG4gIGVsc2VcbiAgICBPQ0lSX1VTRVJOQU1FPVwiJHtkb2xsYXJEb2xsYXJ9T0NJUl9VU0VSTkFNRV9WQVJcIlxuICBmaVxuXG4gIERFU0M9XCJPQ0lSIERvY2tlciBsb2dpbiB0b2tlbiAtICR7Y21kU3ViU3RhcnR9ZGF0ZSArJVklbSVkLSVIJU0lUyR7Y21kU3ViRW5kfVwiXG4gIFRPS0VOPSR7Y21kU3ViU3RhcnR9b2NpIGlhbSBhdXRoLXRva2VuIGNyZWF0ZSAtLXVzZXItaWQgXCIke2RvbGxhckRvbGxhcn1VU0VSX09DSURcIiAtLWRlc2NyaXB0aW9uIFwiJHtkb2xsYXJEb2xsYXJ9REVTQ1wiIC0tcXVlcnkgJ2RhdGEudG9rZW4nIC0tcmF3LW91dHB1dCAyPi9kZXYvbnVsbCB8fCB0cnVlJHtjbWRTdWJFbmR9XG5cbiAgaWYgWyAteiBcIiR7ZG9sbGFyRG9sbGFyfVRPS0VOXCIgXSB8fCBbIFwiJHtkb2xsYXJEb2xsYXJ9VE9LRU5cIiA9PSBcIm51bGxcIiBdOyB0aGVuXG4gICAgZWNobyBcIkVycm9yOiBGYWlsZWQgdG8gY3JlYXRlIGF1dGggdG9rZW4gdmlhIE9DSSBDTEkuXCIgPiYyXG4gICAgZWNobyBcIlRoaXMgbWlnaHQgYmUgZHVlIHRvOlwiID4mMlxuICAgIGVjaG8gXCIgIC0gTWlzc2luZyBJQU0gcGVybWlzc2lvbnMgKG5lZWQ6IG1hbmFnZSBhdXRoLXRva2VucylcIiA+JjJcbiAgICBlY2hvIFwiICAtIFVzZXIgT0NJRCAnJHtkb2xsYXJEb2xsYXJ9VVNFUl9PQ0lEJyBpcyBpbmNvcnJlY3Qgb3IgdXNlciBkb2Vzbid0IGV4aXN0XCIgPiYyXG4gICAgZWNobyBcIiAgLSBPQ0kgQ0xJIG5vdCBwcm9wZXJseSBjb25maWd1cmVkXCIgPiYyXG4gICAgZWNobyBcIlwiID4mMlxuICAgIGVjaG8gXCJTb2x1dGlvbjogU2V0IE9DSV9BVVRIX1RPS0VOIG1hbnVhbGx5OlwiID4mMlxuICAgIGVjaG8gXCIgIDEuIEdldCB0b2tlbiBmcm9tOiBodHRwczovL2Nsb3VkLm9yYWNsZS5jb20vaWRlbnRpdHkvdG9rZW5zXCIgPiYyXG4gICAgZWNobyBcIiAgMi4gRXhwb3J0OiBleHBvcnQgT0NJX0FVVEhfVE9LRU49XFxcXFwieW91ci10b2tlblxcXFxcIlwiID4mMlxuICAgIGVjaG8gXCIgIDMuIEFsc28gc2V0OiBleHBvcnQgT0NJX09DSVJfVVNFUk5BTUU9XFxcXFwiJHtkb2xsYXJEb2xsYXJ9T0NJUl9VU0VSTkFNRVxcXFxcIlwiID4mMlxuICAgIGVjaG8gXCIgIDQuIFRoZW4gcmUtcnVuOiBucG0gcnVuIGRlcGxveVwiID4mMlxuICAgIGV4aXQgMVxuICBmaVxuXG4gIGV4cG9ydCBPQ0lSX0FVVEhfVE9LRU49XCIke2RvbGxhckRvbGxhcn1UT0tFTlwiXG4gIGVjaG8gXCIke2RvbGxhckRvbGxhcn1PQ0lSX0FVVEhfVE9LRU5cIiB8IGRvY2tlciBsb2dpbiAke3JlZ2lvblBsYWNlaG9sZGVyfS5vY2lyLmlvIC11IFwiJHtkb2xsYXJEb2xsYXJ9T0NJUl9VU0VSTkFNRVwiIC0tcGFzc3dvcmQtc3RkaW4gPi9kZXYvbnVsbCAyPiYxIHx8IHtcbiAgICBlY2hvIFwiRXJyb3I6IERvY2tlciBsb2dpbiBmYWlsZWQgd2l0aCBnZW5lcmF0ZWQgdG9rZW4uXCIgPiYyXG4gICAgZWNobyBcIlVzZXJuYW1lIHVzZWQ6ICR7ZG9sbGFyRG9sbGFyfU9DSVJfVVNFUk5BTUVcIiA+JjJcbiAgICBlY2hvIFwiQ2hlY2sgdGhhdCB0aGUgdXNlcm5hbWUgZm9ybWF0IGlzIGNvcnJlY3Q6IDx0ZW5hbmN5LW5hbWVzcGFjZT4vPGRvbWFpbj4vPHVzZXJuYW1lPlwiID4mMlxuICAgIGVjaG8gXCJJZiBpbmNvcnJlY3QsIHNldDogZXhwb3J0IE9DSV9PQ0lSX1VTRVJOQU1FPVxcXFxcIiR7bmFtZXNwYWNlUGxhY2Vob2xkZXJ9L29yYWNsZWlkZW50aXR5Y2xvdWRzZXJ2aWNlL3lvdXItdXNlcm5hbWVcXFxcXCJcIiA+JjJcbiAgICBleGl0IDFcbiAgfVxuZmlgO1xuICAgIFxuICAgIHRoaXMuYWRkT3ZlcnJpZGUoYHJlc291cmNlLm51bGxfcmVzb3VyY2UuJHtidWlsZEFuZFB1c2hJbWFnZUlkfS5wcm92aXNpb25lcmAsIFtcbiAgICAgIHtcbiAgICAgICAgJ2xvY2FsLWV4ZWMnOiB7XG4gICAgICAgICAgY29tbWFuZDogYGNkICR7ZnVuY3Rpb25Db2RlUGF0aH0gJiYgZG9ja2VyIGJ1aWxkIC0tcGxhdGZvcm0gbGludXgvYW1kNjQgLXQgJHtpbWFnZVVybH0gLmAsXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAge1xuICAgICAgICAnbG9jYWwtZXhlYyc6IHtcbiAgICAgICAgICBjb21tYW5kOiBsb2dpblNjcmlwdCxcbiAgICAgICAgICBvbl9mYWlsdXJlOiAnY29udGludWUnLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgJ2xvY2FsLWV4ZWMnOiB7XG4gICAgICAgICAgY29tbWFuZDogYGRvY2tlciBwdXNoICR7aW1hZ2VVcmx9YCxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgXSk7XG4gICAgXG4gICAgLy8gQ3JlYXRlIGEgcmVmZXJlbmNlIHRvIHRoZSBudWxsX3Jlc291cmNlIGZvciBkZXBlbmRlbmN5IHRyYWNraW5nXG4gICAgLy8gV2UnbGwgdXNlIGEgVGVycmFmb3JtRGF0YSBzb3VyY2UgYXMgYSBwcm94eSB0byByZWZlcmVuY2UgaXRcbiAgICBjb25zdCBidWlsZEFuZFB1c2hJbWFnZVJlZiA9IGBcXCR7bnVsbF9yZXNvdXJjZS4ke2J1aWxkQW5kUHVzaEltYWdlSWR9LmlkfWA7XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gVkNOIGFuZCBTdWJuZXRzXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIGNvbnN0IHZjbiA9IG5ldyBDb3JlVmNuKHRoaXMsICdWY24nLCB7XG4gICAgICBjb21wYXJ0bWVudElkOiBjb25maWcuY29tcGFydG1lbnRJZCxcbiAgICAgIGRpc3BsYXlOYW1lOiBgJHtpZH0tdmNuYCxcbiAgICAgIGNpZHJCbG9ja3M6IFsnMTAuMC4wLjAvMTYnXSxcbiAgICAgIGRuc0xhYmVsOiAnYXBwZm4nLFxuICAgIH0pO1xuXG4gICAgY29uc3QgcHVibGljU3VibmV0ID0gbmV3IENvcmVTdWJuZXQodGhpcywgJ1B1YmxpY1N1Ym5ldCcsIHtcbiAgICAgIGNvbXBhcnRtZW50SWQ6IGNvbmZpZy5jb21wYXJ0bWVudElkLFxuICAgICAgdmNuSWQ6IHZjbi5pZCxcbiAgICAgIGRpc3BsYXlOYW1lOiBgJHtpZH0tcHVibGljYCxcbiAgICAgIGNpZHJCbG9jazogJzEwLjAuMS4wLzI0JyxcbiAgICAgIGRuc0xhYmVsOiAncHVibGljJyxcbiAgICAgIHByb2hpYml0UHVibGljSXBPblZuaWM6IGZhbHNlLFxuICAgIH0pO1xuXG4gICAgY29uc3QgcHJpdmF0ZVN1Ym5ldCA9IG5ldyBDb3JlU3VibmV0KHRoaXMsICdQcml2YXRlU3VibmV0Jywge1xuICAgICAgY29tcGFydG1lbnRJZDogY29uZmlnLmNvbXBhcnRtZW50SWQsXG4gICAgICB2Y25JZDogdmNuLmlkLFxuICAgICAgZGlzcGxheU5hbWU6IGAke2lkfS1wcml2YXRlYCxcbiAgICAgIGNpZHJCbG9jazogJzEwLjAuMi4wLzI0JyxcbiAgICAgIGRuc0xhYmVsOiAncHJpdmF0ZScsXG4gICAgICBwcm9oaWJpdFB1YmxpY0lwT25WbmljOiB0cnVlLFxuICAgIH0pO1xuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIFNlY3VyaXR5IExpc3QgZm9yIFB1YmxpYyBTdWJuZXQgKEFQSSBHYXRld2F5KVxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBjb25zdCBwdWJsaWNTZWN1cml0eUxpc3QgPSBuZXcgQ29yZVNlY3VyaXR5TGlzdCh0aGlzLCAnUHVibGljU2VjdXJpdHlMaXN0Jywge1xuICAgICAgY29tcGFydG1lbnRJZDogY29uZmlnLmNvbXBhcnRtZW50SWQsXG4gICAgICB2Y25JZDogdmNuLmlkLFxuICAgICAgZGlzcGxheU5hbWU6IGAke2lkfS1wdWJsaWMtc2xgLFxuICAgICAgaW5ncmVzc1NlY3VyaXR5UnVsZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIHByb3RvY29sOiAnNicsIC8vIFRDUFxuICAgICAgICAgIHNvdXJjZTogJzAuMC4wLjAvMCcsXG4gICAgICAgICAgZGVzY3JpcHRpb246ICdBbGxvdyBIVFRQICg4MCkgZnJvbSBpbnRlcm5ldCcsXG4gICAgICAgICAgdGNwT3B0aW9uczoge1xuICAgICAgICAgICAgbWluOiA4MCxcbiAgICAgICAgICAgIG1heDogODAsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIHByb3RvY29sOiAnNicsIC8vIFRDUFxuICAgICAgICAgIHNvdXJjZTogJzAuMC4wLjAvMCcsXG4gICAgICAgICAgZGVzY3JpcHRpb246ICdBbGxvdyBIVFRQUyAoNDQzKSBmcm9tIGludGVybmV0JyxcbiAgICAgICAgICB0Y3BPcHRpb25zOiB7XG4gICAgICAgICAgICBtaW46IDQ0MyxcbiAgICAgICAgICAgIG1heDogNDQzLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgZWdyZXNzU2VjdXJpdHlSdWxlczogW1xuICAgICAgICB7XG4gICAgICAgICAgcHJvdG9jb2w6ICdhbGwnLFxuICAgICAgICAgIGRlc3RpbmF0aW9uOiAnMC4wLjAuMC8wJyxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogJ0FsbG93IGFsbCBvdXRib3VuZCB0cmFmZmljJyxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSk7XG5cbiAgICAvLyBBc3NvY2lhdGUgc2VjdXJpdHkgbGlzdCB3aXRoIHB1YmxpYyBzdWJuZXRcbiAgICBwdWJsaWNTdWJuZXQuYWRkT3ZlcnJpZGUoJ3NlY3VyaXR5X2xpc3RfaWRzJywgW3B1YmxpY1NlY3VyaXR5TGlzdC5pZF0pO1xuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIFNlY3VyaXR5IExpc3QgZm9yIFByaXZhdGUgU3VibmV0IChGdW5jdGlvbiArIFBHIGluIHNhbWUgc3VibmV0KVxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBjb25zdCBwcml2YXRlU3VibmV0Q2lkciA9ICcxMC4wLjIuMC8yNCc7XG4gICAgY29uc3QgcHJpdmF0ZVNlY3VyaXR5TGlzdCA9IG5ldyBDb3JlU2VjdXJpdHlMaXN0KHRoaXMsICdQcml2YXRlU2VjdXJpdHlMaXN0Jywge1xuICAgICAgY29tcGFydG1lbnRJZDogY29uZmlnLmNvbXBhcnRtZW50SWQsXG4gICAgICB2Y25JZDogdmNuLmlkLFxuICAgICAgZGlzcGxheU5hbWU6IGAke2lkfS1wcml2YXRlLXNsYCxcbiAgICAgIGluZ3Jlc3NTZWN1cml0eVJ1bGVzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBwcm90b2NvbDogJzYnLCAvLyBUQ1BcbiAgICAgICAgICBzb3VyY2U6IHByaXZhdGVTdWJuZXRDaWRyLFxuICAgICAgICAgIGRlc2NyaXB0aW9uOiAnVENQIHRyYWZmaWMgZm9yIHBvcnRzOiA1NDMyIChQb3N0Z3JlU1FMIGZyb20gcHJpdmF0ZSBzdWJuZXQpJyxcbiAgICAgICAgICB0Y3BPcHRpb25zOiB7XG4gICAgICAgICAgICBtaW46IDU0MzIsXG4gICAgICAgICAgICBtYXg6IDU0MzIsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBlZ3Jlc3NTZWN1cml0eVJ1bGVzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBwcm90b2NvbDogJ2FsbCcsXG4gICAgICAgICAgZGVzdGluYXRpb246ICcwLjAuMC4wLzAnLFxuICAgICAgICAgIGRlc2NyaXB0aW9uOiAnQWxsb3cgYWxsIG91dGJvdW5kIHRyYWZmaWMnLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KTtcblxuICAgIC8vIEFzc29jaWF0ZSBzZWN1cml0eSBsaXN0IHdpdGggcHJpdmF0ZSBzdWJuZXRcbiAgICBwcml2YXRlU3VibmV0LmFkZE92ZXJyaWRlKCdzZWN1cml0eV9saXN0X2lkcycsIFtwcml2YXRlU2VjdXJpdHlMaXN0LmlkXSk7XG5cbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gU2VydmljZSBHYXRld2F5IChmb3IgT0NJUiBhY2Nlc3MgZnJvbSBwcml2YXRlIHN1Ym5ldClcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gR2V0IE9iamVjdCBTdG9yYWdlIHNlcnZpY2UgSUQgKE9DSVIgdXNlcyBPYmplY3QgU3RvcmFnZSlcbiAgICAvLyBHZXQgYWxsIHNlcnZpY2VzIC0gdGhlIGZpcnN0IHNlcnZpY2UgaXMgdHlwaWNhbGx5IFwiQWxsIDxyZWdpb24+IFNlcnZpY2VzIGluIE9yYWNsZSBTZXJ2aWNlcyBOZXR3b3JrXCJcbiAgICAvLyBUaGlzIHNlcnZpY2UgaW5jbHVkZXMgT2JqZWN0IFN0b3JhZ2UgYW5kIG90aGVyIE9DSSBzZXJ2aWNlc1xuICAgIGNvbnN0IGFsbFNlcnZpY2VzID0gbmV3IERhdGFPY2lDb3JlU2VydmljZXModGhpcywgJ0FsbFNlcnZpY2VzJywge30pO1xuXG4gICAgY29uc3Qgc2VydmljZUdhdGV3YXkgPSBuZXcgQ29yZVNlcnZpY2VHYXRld2F5KHRoaXMsICdTZXJ2aWNlR2F0ZXdheScsIHtcbiAgICAgIGNvbXBhcnRtZW50SWQ6IGNvbmZpZy5jb21wYXJ0bWVudElkLFxuICAgICAgdmNuSWQ6IHZjbi5pZCxcbiAgICAgIGRpc3BsYXlOYW1lOiBgJHtpZH0tc2VydmljZS1nYXRld2F5YCxcbiAgICAgIHNlcnZpY2VzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBzZXJ2aWNlSWQ6IGFsbFNlcnZpY2VzLnNlcnZpY2VzLmdldCgwKS5pZCxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSk7XG5cbiAgICAvLyBSb3V0ZSB0YWJsZSBmb3IgcHJpdmF0ZSBzdWJuZXQgdG8gcm91dGUgT2JqZWN0IFN0b3JhZ2UgdHJhZmZpYyB2aWEgU2VydmljZSBHYXRld2F5XG4gICAgY29uc3QgcHJpdmF0ZVJvdXRlVGFibGUgPSBuZXcgQ29yZVJvdXRlVGFibGUodGhpcywgJ1ByaXZhdGVSb3V0ZVRhYmxlJywge1xuICAgICAgY29tcGFydG1lbnRJZDogY29uZmlnLmNvbXBhcnRtZW50SWQsXG4gICAgICB2Y25JZDogdmNuLmlkLFxuICAgICAgZGlzcGxheU5hbWU6IGAke2lkfS1wcml2YXRlLXJ0YCxcbiAgICAgIHJvdXRlUnVsZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5ldHdvcmtFbnRpdHlJZDogc2VydmljZUdhdGV3YXkuaWQsXG4gICAgICAgICAgZGVzdGluYXRpb246IGFsbFNlcnZpY2VzLnNlcnZpY2VzLmdldCgwKS5jaWRyQmxvY2ssXG4gICAgICAgICAgZGVzdGluYXRpb25UeXBlOiAnU0VSVklDRV9DSURSX0JMT0NLJyxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogJ1JvdXRlIE9iamVjdCBTdG9yYWdlL09DSVIgdHJhZmZpYyB2aWEgU2VydmljZSBHYXRld2F5JyxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSk7XG5cbiAgICAvLyBBc3NvY2lhdGUgcm91dGUgdGFibGUgd2l0aCBwcml2YXRlIHN1Ym5ldFxuICAgIHByaXZhdGVTdWJuZXQuYWRkT3ZlcnJpZGUoJ3JvdXRlX3RhYmxlX2lkJywgcHJpdmF0ZVJvdXRlVGFibGUuaWQpO1xuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIEludGVybmV0IEdhdGV3YXkgKGZvciBwdWJsaWMgc3VibmV0IGludGVybmV0IGFjY2VzcylcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgY29uc3QgaW50ZXJuZXRHYXRld2F5ID0gbmV3IENvcmVJbnRlcm5ldEdhdGV3YXkodGhpcywgJ0ludGVybmV0R2F0ZXdheScsIHtcbiAgICAgIGNvbXBhcnRtZW50SWQ6IGNvbmZpZy5jb21wYXJ0bWVudElkLFxuICAgICAgdmNuSWQ6IHZjbi5pZCxcbiAgICAgIGRpc3BsYXlOYW1lOiBgJHtpZH0taWd3YCxcbiAgICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgfSk7XG5cbiAgICAvLyBSb3V0ZSB0YWJsZSBmb3IgcHVibGljIHN1Ym5ldCB0byByb3V0ZSBpbnRlcm5ldCB0cmFmZmljIHZpYSBJbnRlcm5ldCBHYXRld2F5XG4gICAgY29uc3QgcHVibGljUm91dGVUYWJsZSA9IG5ldyBDb3JlUm91dGVUYWJsZSh0aGlzLCAnUHVibGljUm91dGVUYWJsZScsIHtcbiAgICAgIGNvbXBhcnRtZW50SWQ6IGNvbmZpZy5jb21wYXJ0bWVudElkLFxuICAgICAgdmNuSWQ6IHZjbi5pZCxcbiAgICAgIGRpc3BsYXlOYW1lOiBgJHtpZH0tcHVibGljLXJ0YCxcbiAgICAgIHJvdXRlUnVsZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5ldHdvcmtFbnRpdHlJZDogaW50ZXJuZXRHYXRld2F5LmlkLFxuICAgICAgICAgIGRlc3RpbmF0aW9uOiAnMC4wLjAuMC8wJyxcbiAgICAgICAgICBkZXN0aW5hdGlvblR5cGU6ICdDSURSX0JMT0NLJyxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogJ1JvdXRlIGFsbCBpbnRlcm5ldCB0cmFmZmljIHZpYSBJbnRlcm5ldCBHYXRld2F5JyxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSk7XG5cbiAgICAvLyBBc3NvY2lhdGUgcm91dGUgdGFibGUgd2l0aCBwdWJsaWMgc3VibmV0XG4gICAgcHVibGljU3VibmV0LmFkZE92ZXJyaWRlKCdyb3V0ZV90YWJsZV9pZCcsIHB1YmxpY1JvdXRlVGFibGUuaWQpO1xuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIFBHIGNvbm5lY3Rpb246IGVpdGhlciBwYXNzIFBHX1VSTCBhcyBmdW5jdGlvbiBjb25maWcsIG9yIGNyZWF0ZSBWYXVsdCBzZWNyZXQgYW5kIHBhc3MgUEdfU0VDUkVUX09DSURcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgY29uc3QgZnVuY3Rpb25Db25maWc6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICBpZiAoY29uZmlnLnBnVXJsICYmIGNvbmZpZy5wZ1VybC50cmltKCkpIHtcbiAgICAgIGlmIChjb25maWcudmF1bHRPY2lkPy50cmltKCkpIHtcbiAgICAgICAgLy8gVmF1bHQgcGF0aDogcmVxdWlyZSBrZXlPY2lkIGFuZCBjcmVhdGUgcGctdXJsIHNlY3JldFxuICAgICAgICBpZiAoIWNvbmZpZy5rZXlPY2lkPy50cmltKCkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAnV2hlbiBPQ0lfVkFVTFRfT0NJRCBpcyBzZXQsIE9DSV9LRVlfT0NJRCBpcyByZXF1aXJlZCB0byBjcmVhdGUgdGhlIHBnLXVybCBzZWNyZXQuICcgK1xuICAgICAgICAgICAgJ1NldCBPQ0lfS0VZX09DSUQgdG8geW91ciBWYXVsdCBlbmNyeXB0aW9uIEtleSBPQ0lELidcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIC8vIEFwcGVuZCByYW5kb20gc3VmZml4IHRvIGF2b2lkIFwibmFtZSBhbHJlYWR5IGV4aXN0c1wiIHdoZW4gYSBzZWNyZXQgd2l0aCB0aGUgc2FtZSBiYXNlIG5hbWUgZXhpc3RzIGluIHRoZSBWYXVsdC5cbiAgICAgICAgLy8gU2V0IFBHX1NFQ1JFVF9TVUZGSVggZW52IHZhciB0byBwaW4gdGhlIG5hbWUgYWNyb3NzIHN5bnRocyAoZS5nLiBQR19TRUNSRVRfU1VGRklYPWFiYzEyMzQ1KS5cbiAgICAgICAgY29uc3QgcGdVcmxTZWNyZXRTdWZmaXggPVxuICAgICAgICAgIHByb2Nlc3MuZW52LlBHX1NFQ1JFVF9TVUZGSVggfHwgY3J5cHRvLnJhbmRvbUJ5dGVzKDQpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgICAgY29uc3QgcGdVcmxTZWNyZXROYW1lID0gYCR7aWR9LXBnLXVybC0ke3BnVXJsU2VjcmV0U3VmZml4fWA7XG4gICAgICAgIGNvbnN0IHBnVXJsU2VjcmV0ID0gbmV3IFZhdWx0U2VjcmV0KHRoaXMsICdQZ1VybFNlY3JldCcsIHtcbiAgICAgICAgICBjb21wYXJ0bWVudElkOiBjb25maWcuY29tcGFydG1lbnRJZCxcbiAgICAgICAgICB2YXVsdElkOiBjb25maWcudmF1bHRPY2lkLFxuICAgICAgICAgIGtleUlkOiBjb25maWcua2V5T2NpZCxcbiAgICAgICAgICBzZWNyZXROYW1lOiBwZ1VybFNlY3JldE5hbWUsXG4gICAgICAgICAgZGVzY3JpcHRpb246ICdQb3N0Z3JlU1FMIGNvbm5lY3Rpb24gVVJMIGZvciBmdW5jdGlvbiAoZnJvbSBQR19VUkwpJyxcbiAgICAgICAgICBzZWNyZXRDb250ZW50OiB7XG4gICAgICAgICAgICBjb250ZW50VHlwZTogJ0JBU0U2NCcsXG4gICAgICAgICAgICBjb250ZW50OiBCdWZmZXIuZnJvbShjb25maWcucGdVcmwudHJpbSgpLCAndXRmLTgnKS50b1N0cmluZygnYmFzZTY0JyksXG4gICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICAgIGZ1bmN0aW9uQ29uZmlnLlBHX1NFQ1JFVF9PQ0lEID0gcGdVcmxTZWNyZXQuaWQ7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBObyBWYXVsdDogcGFzcyBQR19VUkwgZGlyZWN0bHkgYXMgZnVuY3Rpb24gY29uZmlnIChjbGVhci10ZXh0KVxuICAgICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICAgJ1tPQ0kgRnVuY3Rpb25dIFdBUk5JTkc6IFBHX1VSTCBpcyBiZWluZyBwYXNzZWQgdG8gdGhlIGZ1bmN0aW9uIGFzIHBsYWluIGNvbmZpZyAoY2xlYXItdGV4dCkuICcgK1xuICAgICAgICAgICdDcmVkZW50aWFscyBhcmUgdmlzaWJsZSBpbiBmdW5jdGlvbiBjb25maWd1cmF0aW9uLiBGb3IgcHJvZHVjdGlvbiwgc3RvcmUgdGhlIGNvbm5lY3Rpb24gc3RyaW5nIGluIE9DSSBWYXVsdCBhbmQgc2V0ICcgK1xuICAgICAgICAgICdPQ0lfVkFVTFRfT0NJRCBhbmQgT0NJX0tFWV9PQ0lEIHNvIHRoZSBzdGFjayBjcmVhdGVzIGEgVmF1bHQgc2VjcmV0OyB0aGUgZnVuY3Rpb24gd2lsbCB0aGVuIHJlY2VpdmUgb25seSBQR19TRUNSRVRfT0NJRC4nXG4gICAgICAgICk7XG4gICAgICAgIGZ1bmN0aW9uQ29uZmlnLlBHX1VSTCA9IGNvbmZpZy5wZ1VybC50cmltKCk7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChjb25maWcucGdTZWNyZXRPY2lkPy50cmltKCkpIHtcbiAgICAgIGZ1bmN0aW9uQ29uZmlnLlBHX1NFQ1JFVF9PQ0lEID0gY29uZmlnLnBnU2VjcmV0T2NpZC50cmltKCk7XG4gICAgfVxuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIEFQSSBHYXRld2F5IChwdWJsaWMgc3VibmV0KVxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBjb25zdCBhcGlHYXRld2F5ID0gbmV3IEFwaWdhdGV3YXlHYXRld2F5KHRoaXMsICdBcGlHYXRld2F5Jywge1xuICAgICAgY29tcGFydG1lbnRJZDogY29uZmlnLmNvbXBhcnRtZW50SWQsXG4gICAgICBzdWJuZXRJZDogcHVibGljU3VibmV0LmlkLFxuICAgICAgZW5kcG9pbnRUeXBlOiAnUFVCTElDJyxcbiAgICAgIGRpc3BsYXlOYW1lOiBgJHtpZH0tYXBpLWdhdGV3YXlgLFxuICAgIH0pO1xuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIEZ1bmN0aW9ucyBBcHBsaWNhdGlvbiAocHJpdmF0ZSBzdWJuZXQpIGFuZCBGdW5jdGlvblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICBjb25zdCBmdW5jdGlvbkFwcCA9IG5ldyBGdW5jdGlvbnNBcHBsaWNhdGlvbih0aGlzLCAnRnVuY3Rpb25BcHAnLCB7XG4gICAgICBjb21wYXJ0bWVudElkOiBjb25maWcuY29tcGFydG1lbnRJZCxcbiAgICAgIGRpc3BsYXlOYW1lOiBjb25maWcuZnVuY3Rpb25BcHBOYW1lLFxuICAgICAgc3VibmV0SWRzOiBbcHJpdmF0ZVN1Ym5ldC5pZF0sXG4gICAgfSk7XG5cbiAgICAvLyBGdW5jdGlvbiBkZXBlbmRzIG9uIGltYWdlIGJlaW5nIHB1c2hlZCB0byBPQ0lSXG4gICAgY29uc3Qgb2NpRnVuY3Rpb24gPSBuZXcgRnVuY3Rpb25zRnVuY3Rpb24odGhpcywgJ0Z1bmN0aW9uJywge1xuICAgICAgYXBwbGljYXRpb25JZDogZnVuY3Rpb25BcHAuaWQsXG4gICAgICBkaXNwbGF5TmFtZTogY29uZmlnLmZ1bmN0aW9uTmFtZSxcbiAgICAgIGltYWdlOiBpbWFnZVVybCxcbiAgICAgIG1lbW9yeUluTWJzOiAnMjU2JyxcbiAgICAgIHRpbWVvdXRJblNlY29uZHM6IDMwLFxuICAgICAgY29uZmlnOiBPYmplY3Qua2V5cyhmdW5jdGlvbkNvbmZpZykubGVuZ3RoID4gMCA/IGZ1bmN0aW9uQ29uZmlnIDogdW5kZWZpbmVkLFxuICAgIH0pO1xuICAgIC8vIEFkZCBkZXBlbmRlbmN5IG9uIG51bGxfcmVzb3VyY2UgdXNpbmcgYWRkT3ZlcnJpZGVcbiAgICAvLyBUaGlzIGVuc3VyZXMgdGhlIGltYWdlIGlzIGJ1aWx0IGFuZCBwdXNoZWQgYmVmb3JlIHRoZSBGdW5jdGlvbiBpcyBjcmVhdGVkXG4gICAgb2NpRnVuY3Rpb24uYWRkT3ZlcnJpZGUoJ2RlcGVuZHNfb24nLCBbYG51bGxfcmVzb3VyY2UuJHtidWlsZEFuZFB1c2hJbWFnZUlkfWBdKTtcblxuICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAvLyBBUEkgR2F0ZXdheSBEZXBsb3ltZW50IOKAkyByb3V0ZSB0byBmdW5jdGlvbiAob25seSBhZnRlciBmdW5jdGlvbiBleGlzdHMpXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIGNvbnN0IHBhdGhQcmVmaXggPSBjb25maWcuYXBpR3dQYXRoUHJlZml4ID8/ICcvJztcbiAgICBjb25zdCByb3V0ZVBhdGggPSBjb25maWcuYXBpR3dSb3V0ZVBhdGggPz8gJy97cGF0aCp9JztcbiAgICBjb25zdCBtZXRob2RzID0gY29uZmlnLmFwaUd3TWV0aG9kcz8ubGVuZ3RoID8gY29uZmlnLmFwaUd3TWV0aG9kcyA6IFsnR0VUJywgJ1BPU1QnLCAnT1BUSU9OUyddO1xuXG4gICAgY29uc3QgYXBpRGVwbG95bWVudCA9IG5ldyBBcGlnYXRld2F5RGVwbG95bWVudCh0aGlzLCAnQXBpRGVwbG95bWVudCcsIHtcbiAgICAgIGNvbXBhcnRtZW50SWQ6IGNvbmZpZy5jb21wYXJ0bWVudElkLFxuICAgICAgZ2F0ZXdheUlkOiBhcGlHYXRld2F5LmlkLFxuICAgICAgcGF0aFByZWZpeCxcbiAgICAgIGRpc3BsYXlOYW1lOiBgJHtpZH0tZGVwbG95bWVudGAsXG4gICAgICBzcGVjaWZpY2F0aW9uOiB7XG4gICAgICAgIHJvdXRlczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIHBhdGg6IHJvdXRlUGF0aCxcbiAgICAgICAgICAgIG1ldGhvZHMsXG4gICAgICAgICAgICBiYWNrZW5kOiB7XG4gICAgICAgICAgICAgIHR5cGU6ICdPUkFDTEVfRlVOQ1RJT05TX0JBQ0tFTkQnLFxuICAgICAgICAgICAgICBmdW5jdGlvbklkOiBvY2lGdW5jdGlvbi5pZCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0sXG4gICAgfSk7XG4gICAgYXBpRGVwbG95bWVudC5ub2RlLmFkZERlcGVuZGVuY3kob2NpRnVuY3Rpb24pO1xuXG4gICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgIC8vIE91dHB1dHNcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgbmV3IFRlcnJhZm9ybU91dHB1dCh0aGlzLCAnb2Npcl9yZXBvc2l0b3J5X25hbWUnLCB7XG4gICAgICB2YWx1ZTogb2NpclJlcG9zaXRvcnkuZGlzcGxheU5hbWUsXG4gICAgICBkZXNjcmlwdGlvbjogJ09DSVIgcmVwb3NpdG9yeSBkaXNwbGF5IG5hbWUnLFxuICAgIH0pO1xuXG4gICAgbmV3IFRlcnJhZm9ybU91dHB1dCh0aGlzLCAnYXBpX2dhdGV3YXlfaG9zdCcsIHtcbiAgICAgIHZhbHVlOiBhcGlHYXRld2F5Lmhvc3RuYW1lLFxuICAgICAgZGVzY3JpcHRpb246ICdBUEkgR2F0ZXdheSBob3N0bmFtZSBmb3IgaW52b2tpbmcgdGhlIGZ1bmN0aW9uJyxcbiAgICB9KTtcblxuICAgIG5ldyBUZXJyYWZvcm1PdXRwdXQodGhpcywgJ2Z1bmN0aW9uX2ludm9rZV91cmwnLCB7XG4gICAgICB2YWx1ZTogYGh0dHBzOi8vJHthcGlHYXRld2F5Lmhvc3RuYW1lfWAsXG4gICAgICBkZXNjcmlwdGlvbjogJ0Jhc2UgVVJMIHRvIGludm9rZSB0aGUgZnVuY3Rpb24gKHVzZSA/YWN0aW9uPWhlbGxvfGVjaG98aW5mbyknLFxuICAgIH0pO1xuXG4gICAgbmV3IFRlcnJhZm9ybU91dHB1dCh0aGlzLCAnZnVuY3Rpb25faWQnLCB7XG4gICAgICB2YWx1ZTogb2NpRnVuY3Rpb24uaWQsXG4gICAgICBkZXNjcmlwdGlvbjogJ09DSSBGdW5jdGlvbiBPQ0lEIChmb3IgZGVwbG95LWZ1bmN0aW9uLnNoIG9yIG9jaSBmbiBmdW5jdGlvbiB1cGRhdGUpJyxcbiAgICB9KTtcbiAgfVxufVxuIl19