UNPKG

@project-lakechain/opensearch-index

Version:

Creates an OpenSearch index using AWS CDK.

179 lines 20.4 kB
"use strict"; /* * Copyright (C) 2023 Amazon.com, Inc. or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.OpenSearchIndex = void 0; const path_1 = __importDefault(require("path")); const cdk = __importStar(require("aws-cdk-lib")); const lambda = __importStar(require("aws-cdk-lib/aws-lambda")); const node = __importStar(require("aws-cdk-lib/aws-lambda-nodejs")); const custom = __importStar(require("aws-cdk-lib/custom-resources")); const iam = __importStar(require("aws-cdk-lib/aws-iam")); const constructs_1 = require("constructs"); /** * A custom resource making it easy to create an index * and manage its lifecycle as a CDK construct. * This construct uses a lambda function to interact with * the OpenSearch endpoint, and uses the OpenSearch SDK to * create and delete the index. * This construct is compatible with OpenSearch domains and serverless * collections deployed in a VPC or not. */ class OpenSearchIndex extends constructs_1.Construct { /** * The name of the index managed by the construct. */ indexName; /** * OpenSearch Index constructor * @param scope the scope of the construct * @param id the id of the construct */ constructor(scope, id, props) { super(scope, id); // Set the index name. this.indexName = props.indexName; // The OpenSearch endpoint. const endpoint = this.getEndpoint(props.endpoint); // The identifier of the OpenSearch service. const serviceIdentifier = this.getServiceIdentifier(props.endpoint); // The path to the lambda function directory. const processorPath = path_1.default.resolve(__dirname, 'lambdas', 'index-manager'); // Create the lambda function that will create the index. const processor = new node.NodejsFunction(this, 'Compute', { description: 'A custom resource managing the state of an OpenSearch index.', entry: path_1.default.resolve(processorPath, 'index.js'), vpc: props.vpc, timeout: cdk.Duration.seconds(10), runtime: lambda.Runtime.NODEJS_18_X, architecture: lambda.Architecture.ARM_64, logGroup: props.logGroup, environment: { OPENSEARCH_ENDPOINT: endpoint, OPENSEARCH_INDEX_NAME: props.indexName, BODY_PARAMETERS: JSON.stringify(props.body), SERVICE_IDENTIFIER: serviceIdentifier }, bundling: { minify: true, externalModules: [ '@aws-sdk/credential-provider-node' ] } }); if (serviceIdentifier === 'es') { // Allow the lambda function to manage the index. props.endpoint.grantWrite(processor); } else if (serviceIdentifier === 'aoss') { const endpoint = props.endpoint; // If the endpoint is a collection, we also need to create an // access policy on the collection to allow the lambda function // to manage the index. // Add a new access policy. endpoint.addAccessPolicy(this.indexName, [processor.role.roleArn], ['aoss:CreateIndex', 'aoss:DeleteIndex', 'aoss:UpdateIndex']); // We also need to grant the lambda function permissions // to write to the OpenSearch index. processor.addToRolePolicy(new iam.PolicyStatement({ effect: iam.Effect.ALLOW, actions: ['aoss:APIAccessAll'], resources: [endpoint.collectionArn] })); } // Create a custom resource that will manage the index. const resource = new cdk.CustomResource(this, 'Resource', { serviceToken: new custom.Provider(this, 'Provider', { onEventHandler: processor, logGroup: props.logGroup }).serviceToken, resourceType: 'Custom::OpenSearchIndex', properties: { IndexName: props.indexName, Body: props.body, Endpoint: endpoint } }); resource.node.addDependency(props.endpoint); } /** * Get the URL of the OpenSearch endpoint. * @param endpoint the OpenSearch endpoint. * @returns the endpoint URL. */ getEndpoint(endpoint) { const serviceIdentifier = this.getServiceIdentifier(endpoint); if (serviceIdentifier === 'es') { return (`https://${endpoint.domainEndpoint}`); } else if (serviceIdentifier === 'aoss') { return (endpoint.collectionEndpoint); } else { throw new Error('Invalid endpoint.'); } } /** * Get the service identifier of the OpenSearch endpoint. * @param endpoint the OpenSearch endpoint. * @returns the service identifier. */ getServiceIdentifier(endpoint) { const e = endpoint; if (e.domainArn && e.domainName && e.domainId && e.domainEndpoint) { return ('es'); } else if (e.collectionName && e.collectionArn && e.collectionId && e.collectionEndpoint) { return ('aoss'); } else { throw new Error('Invalid endpoint.'); } } } exports.OpenSearchIndex = OpenSearchIndex; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7Ozs7Ozs7OztHQWNHOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUVILGdEQUF3QjtBQUV4QixpREFBbUM7QUFDbkMsK0RBQWlEO0FBQ2pELG9FQUFzRDtBQUV0RCxxRUFBdUQ7QUFFdkQseURBQTJDO0FBSTNDLDJDQUF1QztBQW9DdkM7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFhLGVBQWdCLFNBQVEsc0JBQVM7SUFFNUM7O09BRUc7SUFDYSxTQUFTLENBQVM7SUFFbEM7Ozs7T0FJRztJQUNILFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBMkI7UUFDbkUsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUVqQixzQkFBc0I7UUFDdEIsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDO1FBRWpDLDJCQUEyQjtRQUMzQixNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUVsRCw0Q0FBNEM7UUFDNUMsTUFBTSxpQkFBaUIsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBRXBFLDZDQUE2QztRQUM3QyxNQUFNLGFBQWEsR0FBRyxjQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxTQUFTLEVBQUUsZUFBZSxDQUFDLENBQUM7UUFFMUUseURBQXlEO1FBQ3pELE1BQU0sU0FBUyxHQUFHLElBQUksSUFBSSxDQUFDLGNBQWMsQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFO1lBQ3pELFdBQVcsRUFBRSw4REFBOEQ7WUFDM0UsS0FBSyxFQUFFLGNBQUksQ0FBQyxPQUFPLENBQUMsYUFBYSxFQUFFLFVBQVUsQ0FBQztZQUM5QyxHQUFHLEVBQUUsS0FBSyxDQUFD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Q0FBQztRQUN2QyxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7O09BSUc7SUFDSyxvQkFBb0IsQ0FBQyxRQUE4QztRQUN6RSxNQUFNLENBQUMsR0FBRyxRQUFlLENBQUM7UUFFMUIsSUFBSSxDQUFDLENBQUMsU0FBUztlQUNWLENBQUMsQ0FBQyxVQUFVO2VBQ1osQ0FBQyxDQUFDLFFBQVE7ZUFDVixDQUFDLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDdEIsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2hCLENBQUM7YUFBTSxJQUFJLENBQUMsQ0FBQyxjQUFjO2VBQ3RCLENBQUMsQ0FBQyxhQUFhO2VBQ2YsQ0FBQyxDQUFDLFlBQVk7ZUFDZCxDQUFDLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztZQUMxQixPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDbEIsQ0FBQzthQUFNLENBQUM7WUFDTixNQUFNLElBQUksS0FBSyxDQUFDLG1CQUFtQixDQUFDLENBQUM7UUFDdkMsQ0FBQztJQUNILENBQUM7Q0FDRjtBQW5JRCwwQ0FtSUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDIzIEFtYXpvbi5jb20sIEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMuXG4gKlxuICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuXG5pbXBvcnQgcGF0aCBmcm9tICdwYXRoJztcblxuaW1wb3J0ICogYXMgY2RrIGZyb20gJ2F3cy1jZGstbGliJztcbmltcG9ydCAqIGFzIGxhbWJkYSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcbmltcG9ydCAqIGFzIG5vZGUgZnJvbSAnYXdzLWNkay1saWIvYXdzLWxhbWJkYS1ub2RlanMnO1xuaW1wb3J0ICogYXMgZWMyIGZyb20gJ2F3cy1jZGstbGliL2F3cy1lYzInO1xuaW1wb3J0ICogYXMgY3VzdG9tIGZyb20gJ2F3cy1jZGstbGliL2N1c3RvbS1yZXNvdXJjZXMnO1xuaW1wb3J0ICogYXMgb3BlbnNlYXJjaCBmcm9tICdhd3MtY2RrLWxpYi9hd3Mtb3BlbnNlYXJjaHNlcnZpY2UnO1xuaW1wb3J0ICogYXMgaWFtIGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuaW1wb3J0ICogYXMgb3NzIGZyb20gJ0Bwcm9qZWN0LWxha2VjaGFpbi9vcGVuc2VhcmNoLWNvbGxlY3Rpb24nO1xuaW1wb3J0ICogYXMgbG9ncyBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbG9ncyc7XG5cbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgU2VydmljZUlkZW50aWZpZXIgfSBmcm9tICcuL2RlZmluaXRpb25zL3NlcnZpY2UtaWRlbnRpZmllcic7XG5cbi8qKlxuICogVGhlIHByb3BlcnRpZXMgZm9yIHRoZSBPcGVuU2VhcmNoSW5kZXggY29uc3RydWN0LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIE9wZW5TZWFyY2hJbmRleFByb3BzIHtcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIGluZGV4LlxuICAgKi9cbiAgcmVhZG9ubHkgaW5kZXhOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBib2R5IG9mIHRoZSBpbmRleCBjcmVhdGlvbiByZXF1ZXN0LlxuICAgKi9cbiAgcmVhZG9ubHkgYm9keTogUmVjb3JkPHN0cmluZywgYW55PjtcblxuICAvKipcbiAgICogVGhlIE9wZW5TZWFyY2ggZW5kcG9pbnQgb24gd2hpY2ggdGhlIGluZGV4XG4gICAqIHNob3VsZCBiZSBjcmVhdGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgZW5kcG9pbnQ6IG9wZW5zZWFyY2guSURvbWFpbiB8IG9zcy5JQ29sbGVjdGlvbjtcblxuICAvKipcbiAgICogVGhlIFZQQyBpbiB3aGljaCB0aGUgT3BlblNlYXJjaCBkb21haW4gaXMgZGVwbG95ZWQuXG4gICAqL1xuICByZWFkb25seSB2cGM/OiBlYzIuSVZwYztcblxuICAvKipcbiAgICogVGhlIGxvZyBncm91cCBpbiB3aGljaCB0aGUgbGFtYmRhIGZ1bmN0aW9uIHdpbGxcbiAgICogd3JpdGUgaXRzIGxvZ3MuXG4gICAqL1xuICByZWFkb25seSBsb2dHcm91cD86IGxvZ3MuSUxvZ0dyb3VwO1xufVxuXG4vKipcbiAqIEEgY3VzdG9tIHJlc291cmNlIG1ha2luZyBpdCBlYXN5IHRvIGNyZWF0ZSBhbiBpbmRleFxuICogYW5kIG1hbmFnZSBpdHMgbGlmZWN5Y2xlIGFzIGEgQ0RLIGNvbnN0cnVjdC5cbiAqIFRoaXMgY29uc3RydWN0IHVzZXMgYSBsYW1iZGEgZnVuY3Rpb24gdG8gaW50ZXJhY3Qgd2l0aFxuICogdGhlIE9wZW5TZWFyY2ggZW5kcG9pbnQsIGFuZCB1c2VzIHRoZSBPcGVuU2VhcmNoIFNESyB0b1xuICogY3JlYXRlIGFuZCBkZWxldGUgdGhlIGluZGV4LlxuICogVGhpcyBjb25zdHJ1Y3QgaXMgY29tcGF0aWJsZSB3aXRoIE9wZW5TZWFyY2ggZG9tYWlucyBhbmQgc2VydmVybGVzc1xuICogY29sbGVjdGlvbnMgZGVwbG95ZWQgaW4gYSBWUEMgb3Igbm90LlxuICovXG5leHBvcnQgY2xhc3MgT3BlblNlYXJjaEluZGV4IGV4dGVuZHMgQ29uc3RydWN0IHtcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIGluZGV4IG1hbmFnZWQgYnkgdGhlIGNvbnN0cnVjdC5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBpbmRleE5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogT3BlblNlYXJjaCBJbmRleCBjb25zdHJ1Y3RvclxuICAgKiBAcGFyYW0gc2NvcGUgdGhlIHNjb3BlIG9mIHRoZSBjb25zdHJ1Y3RcbiAgICogQHBhcmFtIGlkIHRoZSBpZCBvZiB0aGUgY29uc3RydWN0XG4gICAqL1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogT3BlblNlYXJjaEluZGV4UHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQpO1xuXG4gICAgLy8gU2V0IHRoZSBpbmRleCBuYW1lLlxuICAgIHRoaXMuaW5kZXhOYW1lID0gcHJvcHMuaW5kZXhOYW1lO1xuXG4gICAgLy8gVGhlIE9wZW5TZWFyY2ggZW5kcG9pbnQuXG4gICAgY29uc3QgZW5kcG9pbnQgPSB0aGlzLmdldEVuZHBvaW50KHByb3BzLmVuZHBvaW50KTtcblxuICAgIC8vIFRoZSBpZGVudGlmaWVyIG9mIHRoZSBPcGVuU2VhcmNoIHNlcnZpY2UuXG4gICAgY29uc3Qgc2VydmljZUlkZW50aWZpZXIgPSB0aGlzLmdldFNlcnZpY2VJZGVudGlmaWVyKHByb3BzLmVuZHBvaW50KTtcblxuICAgIC8vIFRoZSBwYXRoIHRvIHRoZSBsYW1iZGEgZnVuY3Rpb24gZGlyZWN0b3J5LlxuICAgIGNvbnN0IHByb2Nlc3NvclBhdGggPSBwYXRoLnJlc29sdmUoX19kaXJuYW1lLCAnbGFtYmRhcycsICdpbmRleC1tYW5hZ2VyJyk7XG5cbiAgICAvLyBDcmVhdGUgdGhlIGxhbWJkYSBmdW5jdGlvbiB0aGF0IHdpbGwgY3JlYXRlIHRoZSBpbmRleC5cbiAgICBjb25zdCBwcm9jZXNzb3IgPSBuZXcgbm9kZS5Ob2RlanNGdW5jdGlvbih0aGlzLCAnQ29tcHV0ZScsIHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnQSBjdXN0b20gcmVzb3VyY2UgbWFuYWdpbmcgdGhlIHN0YXRlIG9mIGFuIE9wZW5TZWFyY2ggaW5kZXguJyxcbiAgICAgIGVudHJ5OiBwYXRoLnJlc29sdmUocHJvY2Vzc29yUGF0aCwgJ2luZGV4LmpzJyksXG4gICAgICB2cGM6IHByb3BzLnZwYyxcbiAgICAgIHRpbWVvdXQ6IGNkay5EdXJhdGlvbi5zZWNvbmRzKDEwKSxcbiAgICAgIHJ1bnRpbWU6IGxhbWJkYS5SdW50aW1lLk5PREVKU18xOF9YLFxuICAgICAgYXJjaGl0ZWN0dXJlOiBsYW1iZGEuQXJjaGl0ZWN0dXJlLkFSTV82NCxcbiAgICAgIGxvZ0dyb3VwOiBwcm9wcy5sb2dHcm91cCxcbiAgICAgIGVudmlyb25tZW50OiB7XG4gICAgICAgIE9QRU5TRUFSQ0hfRU5EUE9JTlQ6IGVuZHBvaW50LFxuICAgICAgICBPUEVOU0VBUkNIX0lOREVYX05BTUU6IHByb3BzLmluZGV4TmFtZSxcbiAgICAgICAgQk9EWV9QQVJBTUVURVJTOiBKU09OLnN0cmluZ2lmeShwcm9wcy5ib2R5KSxcbiAgICAgICAgU0VSVklDRV9JREVOVElGSUVSOiBzZXJ2aWNlSWRlbnRpZmllclxuICAgICAgfSxcbiAgICAgIGJ1bmRsaW5nOiB7XG4gICAgICAgIG1pbmlmeTogdHJ1ZSxcbiAgICAgICAgZXh0ZXJuYWxNb2R1bGVzOiBbXG4gICAgICAgICAgJ0Bhd3Mtc2RrL2NyZWRlbnRpYWwtcHJvdmlkZXItbm9kZSdcbiAgICAgICAgXVxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgaWYgKHNlcnZpY2VJZGVudGlmaWVyID09PSAnZXMnKSB7XG4gICAgICAvLyBBbGxvdyB0aGUgbGFtYmRhIGZ1bmN0aW9uIHRvIG1hbmFnZSB0aGUgaW5kZXguXG4gICAgICAocHJvcHMuZW5kcG9pbnQgYXMgb3BlbnNlYXJjaC5Eb21haW4pLmdyYW50V3JpdGUocHJvY2Vzc29yKTtcbiAgICB9IGVsc2UgaWYgKHNlcnZpY2VJZGVudGlmaWVyID09PSAnYW9zcycpIHtcbiAgICAgIGNvbnN0IGVuZHBvaW50ID0gcHJvcHMuZW5kcG9pbnQgYXMgb3NzLkNvbGxlY3Rpb247XG5cbiAgICAgIC8vIElmIHRoZSBlbmRwb2ludCBpcyBhIGNvbGxlY3Rpb24sIHdlIGFsc28gbmVlZCB0byBjcmVhdGUgYW5cbiAgICAgIC8vIGFjY2VzcyBwb2xpY3kgb24gdGhlIGNvbGxlY3Rpb24gdG8gYWxsb3cgdGhlIGxhbWJkYSBmdW5jdGlvblxuICAgICAgLy8gdG8gbWFuYWdlIHRoZSBpbmRleC5cbiAgICAgIC8vIEFkZCBhIG5ldyBhY2Nlc3MgcG9saWN5LlxuICAgICAgZW5kcG9pbnQuYWRkQWNjZXNzUG9saWN5KFxuICAgICAgICB0aGlzLmluZGV4TmFtZSxcbiAgICAgICAgW3Byb2Nlc3Nvci5yb2xlIS5yb2xlQXJuXSxcbiAgICAgICAgWydhb3NzOkNyZWF0ZUluZGV4JywgJ2Fvc3M6RGVsZXRlSW5kZXgnLCAnYW9zczpVcGRhdGVJbmRleCddXG4gICAgICApO1xuXG4gICAgICAvLyBXZSBhbHNvIG5lZWQgdG8gZ3JhbnQgdGhlIGxhbWJkYSBmdW5jdGlvbiBwZXJtaXNzaW9uc1xuICAgICAgLy8gdG8gd3JpdGUgdG8gdGhlIE9wZW5TZWFyY2ggaW5kZXguXG4gICAgICBwcm9jZXNzb3IuYWRkVG9Sb2xlUG9saWN5KG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgICBhY3Rpb25zOiBbJ2Fvc3M6QVBJQWNjZXNzQWxsJ10sXG4gICAgICAgIHJlc291cmNlczogW2VuZHBvaW50LmNvbGxlY3Rpb25Bcm5dXG4gICAgICB9KSk7XG4gICAgfVxuXG4gICAgLy8gQ3JlYXRlIGEgY3VzdG9tIHJlc291cmNlIHRoYXQgd2lsbCBtYW5hZ2UgdGhlIGluZGV4LlxuICAgIGNvbnN0IHJlc291cmNlID0gbmV3IGNkay5DdXN0b21SZXNvdXJjZSh0aGlzLCAnUmVzb3VyY2UnLCB7XG4gICAgICBzZXJ2aWNlVG9rZW46IG5ldyBjdXN0b20uUHJvdmlkZXIodGhpcywgJ1Byb3ZpZGVyJywge1xuICAgICAgICBvbkV2ZW50SGFuZGxlcjogcHJvY2Vzc29yLFxuICAgICAgICBsb2dHcm91cDogcHJvcHMubG9nR3JvdXBcbiAgICAgIH0pLnNlcnZpY2VUb2tlbixcbiAgICAgIHJlc291cmNlVHlwZTogJ0N1c3RvbTo6T3BlblNlYXJjaEluZGV4JyxcbiAgICAgIHByb3BlcnRpZXM6IHtcbiAgICAgICAgSW5kZXhOYW1lOiBwcm9wcy5pbmRleE5hbWUsXG4gICAgICAgIEJvZHk6IHByb3BzLmJvZHksXG4gICAgICAgIEVuZHBvaW50OiBlbmRwb2ludFxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmVzb3VyY2Uubm9kZS5hZGREZXBlbmRlbmN5KHByb3BzLmVuZHBvaW50KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIFVSTCBvZiB0aGUgT3BlblNlYXJjaCBlbmRwb2ludC5cbiAgICogQHBhcmFtIGVuZHBvaW50IHRoZSBPcGVuU2VhcmNoIGVuZHBvaW50LlxuICAgKiBAcmV0dXJucyB0aGUgZW5kcG9pbnQgVVJMLlxuICAgKi9cbiAgcHJpdmF0ZSBnZXRFbmRwb2ludChlbmRwb2ludDogb3BlbnNlYXJjaC5JRG9tYWluIHwgb3NzLklDb2xsZWN0aW9uKTogc3RyaW5nIHtcbiAgICBjb25zdCBzZXJ2aWNlSWRlbnRpZmllciA9IHRoaXMuZ2V0U2VydmljZUlkZW50aWZpZXIoZW5kcG9pbnQpO1xuXG4gICAgaWYgKHNlcnZpY2VJZGVudGlmaWVyID09PSAnZXMnKSB7XG4gICAgICByZXR1cm4gKGBodHRwczovLyR7KGVuZHBvaW50IGFzIG9wZW5zZWFyY2guRG9tYWluKS5kb21haW5FbmRwb2ludH1gKTtcbiAgICB9IGVsc2UgaWYgKHNlcnZpY2VJZGVudGlmaWVyID09PSAnYW9zcycpIHtcbiAgICAgIHJldHVybiAoKGVuZHBvaW50IGFzIG9zcy5Db2xsZWN0aW9uKS5jb2xsZWN0aW9uRW5kcG9pbnQpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgZW5kcG9pbnQuJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgc2VydmljZSBpZGVudGlmaWVyIG9mIHRoZSBPcGVuU2VhcmNoIGVuZHBvaW50LlxuICAgKiBAcGFyYW0gZW5kcG9pbnQgdGhlIE9wZW5TZWFyY2ggZW5kcG9pbnQuXG4gICAqIEByZXR1cm5zIHRoZSBzZXJ2aWNlIGlkZW50aWZpZXIuXG4gICAqL1xuICBwcml2YXRlIGdldFNlcnZpY2VJZGVudGlmaWVyKGVuZHBvaW50OiBvcGVuc2VhcmNoLklEb21haW4gfCBvc3MuSUNvbGxlY3Rpb24pOiBTZXJ2aWNlSWRlbnRpZmllciB7XG4gICAgY29uc3QgZSA9IGVuZHBvaW50IGFzIGFueTtcbiAgICBcbiAgICBpZiAoZS5kb21haW5Bcm5cbiAgICAgICYmIGUuZG9tYWluTmFtZVxuICAgICAgJiYgZS5kb21haW5JZFxuICAgICAgJiYgZS5kb21haW5FbmRwb2ludCkge1xuICAgICAgcmV0dXJuICgnZXMnKTtcbiAgICB9IGVsc2UgaWYgKGUuY29sbGVjdGlvbk5hbWVcbiAgICAgICYmIGUuY29sbGVjdGlvbkFyblxuICAgICAgJiYgZS5jb2xsZWN0aW9uSWRcbiAgICAgICYmIGUuY29sbGVjdGlvbkVuZHBvaW50KSB7XG4gICAgICByZXR1cm4gKCdhb3NzJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBlbmRwb2ludC4nKTtcbiAgICB9XG4gIH1cbn0iXX0=