aws-cdk-neuronx-patterns
Version:
> [!WARNING] > This library is experimental module.
133 lines • 17.7 kB
JavaScript
;
var _a, _b, _c, _d;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ApplicationLoadBalancedVllmNxDInferenceService = exports.VllmNxdInferenceTaskDefinition = exports.VllmNxdInferenceEcsImage = exports.VllmNxdInferenceEcsImageBase = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const ecs = require("aws-cdk-lib/aws-ecs");
const constructs_1 = require("constructs");
const aws_ecs_patterns_1 = require("../base/aws-ecs-patterns");
const neuronx_1 = require("../base/neuronx");
const vllm_engine_1 = require("../base/server-engine/vllm-engine");
/**
* Base class for VllmNxdInferenceImage.
*/
class VllmNxdInferenceEcsImageBase {
constructor(neuronxImage) {
this.neuronSdkVersion = neuronxImage.neuronSdkVersion;
}
}
exports.VllmNxdInferenceEcsImageBase = VllmNxdInferenceEcsImageBase;
_a = JSII_RTTI_SYMBOL_1;
VllmNxdInferenceEcsImageBase[_a] = { fqn: "aws-cdk-neuronx-patterns.VllmNxdInferenceEcsImageBase", version: "0.3.0" };
/**
* Inference ECS container image for vLLM on NxD Inference.
* This image uses the official AWS Neuron Deep Learning Containers which come with vLLM pre-installed.
*
* @example new VllmNxdInferenceEcsImage(VllmInferenceNeuronxImage.LATEST)
*/
class VllmNxdInferenceEcsImage extends VllmNxdInferenceEcsImageBase {
/**
* Create a VllmNxdInferenceImage from a custom neuronx image.
* This will build a container image using a Dockerfile that installs vLLM from source.
*
* @example
* new VllmNxdInferenceEcsImage(VllmInferenceNeuronxImage.LATEST)
*/
constructor(vllmInferenceNeuronxImage) {
vllmInferenceNeuronxImage ?? (vllmInferenceNeuronxImage = neuronx_1.VllmInferenceNeuronxImage.LATEST);
super(vllmInferenceNeuronxImage);
this.image = ecs.ContainerImage.fromRegistry(`${vllmInferenceNeuronxImage.imageName}:${vllmInferenceNeuronxImage.imageTag}`);
}
}
exports.VllmNxdInferenceEcsImage = VllmNxdInferenceEcsImage;
_b = JSII_RTTI_SYMBOL_1;
VllmNxdInferenceEcsImage[_b] = { fqn: "aws-cdk-neuronx-patterns.VllmNxdInferenceEcsImage", version: "0.3.0" };
/**
* Task definition for VllmNxdInference.
*/
class VllmNxdInferenceTaskDefinition extends aws_ecs_patterns_1.NeuronxTaskDefinition {
constructor(scope, id, props) {
const neuronxInstanceType = props.neuronxInstanceType ?? props.compiledModel.recommendedInstanceType;
const tensorParallelSize = props.compiledModel.vllmArgs.tensorParallelSize ?? 1;
super(scope, id, {
...props,
neuronxInstanceType,
tensorParallelSize,
});
const image = props.image ?? new VllmNxdInferenceEcsImage();
const port = props.compiledModel.vllmArgs.port ?? 8000;
const vllmCliArgs = vllm_engine_1.VllmEngineArgumentsParser.cli(props.compiledModel.vllmArgs);
// Prepare environment variables
const environment = {
...props.environment,
VLLM_NEURON_FRAMEWORK: "neuronx-distributed-inference",
NEURON_COMPILED_ARTIFACTS: "neuron-compiled-artifacts",
NEURON_RT_NUM_CORES: tensorParallelSize.toString(),
XLA_HANDLE_SPECIAL_SCALAR: "1",
MODEL_NAME: props.compiledModel.modelName,
};
this.addContainerWithDefault("vLLM", {
image: image.image,
portMappings: [
{
containerPort: port,
},
],
healthCheck: {
command: [
"CMD-SHELL",
`curl -f http://localhost:${port}/health || exit 1`,
],
startPeriod: aws_cdk_lib_1.Duration.minutes(5),
},
workingDirectory: `/opt/ml/model/${props.compiledModel.s3Prefix}`,
entryPoint: ["vllm", "serve"],
command: vllmCliArgs,
environment,
});
}
}
exports.VllmNxdInferenceTaskDefinition = VllmNxdInferenceTaskDefinition;
_c = JSII_RTTI_SYMBOL_1;
VllmNxdInferenceTaskDefinition[_c] = { fqn: "aws-cdk-neuronx-patterns.VllmNxdInferenceTaskDefinition", version: "0.3.0" };
/**
* ApplicationLoadBalancedVllmNxDInferenceService is a wrapper of ApplicationLoadBalancedNeuronxServiceBase.
* It provides a simple way to deploy vLLM on NxD Inference.
* @example
* const compiler = new VllmNxdInferenceCompiler(this, "Compiler", {
* vpc,
* bucket,
* model: Model.fromHuggingFace("example/example-7b-chat"),
* });
* const compiledModel = compiler.compile();
* const taskDefinition = new VllmNxdInferenceTaskDefinition(
* this,
* "TaskDefinition",
* {
* vpc,
* compiledModel,
* },
* );
* new ApplicationLoadBalancedVllmNxDInferenceService(this, "Service", {
* taskDefinition,
* });
*/
class ApplicationLoadBalancedVllmNxDInferenceService extends constructs_1.Construct {
constructor(scope, id, props) {
super(scope, id);
const resource = new aws_ecs_patterns_1.ApplicationLoadBalancedNeuronxService(this, "Resource", props);
resource.targetGroup.configureHealthCheck({
path: "/health",
});
this.loadBalancer = resource.loadBalancer;
this.listener = resource.listener;
this.targetGroup = resource.targetGroup;
this.service = resource.service;
this.taskDefinition = resource.taskDefinition;
}
}
exports.ApplicationLoadBalancedVllmNxDInferenceService = ApplicationLoadBalancedVllmNxDInferenceService;
_d = JSII_RTTI_SYMBOL_1;
ApplicationLoadBalancedVllmNxDInferenceService[_d] = { fqn: "aws-cdk-neuronx-patterns.ApplicationLoadBalancedVllmNxDInferenceService", version: "0.3.0" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmxsbS1ueGQtaW5mZXJlbmNlLWVjcy1wYXR0ZXJucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy92bGxtLW54ZC1pbmZlcmVuY2UvdmxsbS1ueGQtaW5mZXJlbmNlLWVjcy1wYXR0ZXJucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDZDQUF1QztBQUN2QywyQ0FBMkM7QUFNM0MsMkNBQXVDO0FBQ3ZDLCtEQUtrQztBQUNsQyw2Q0FHeUI7QUFFekIsbUVBQThFO0FBTzlFOztHQUVHO0FBQ0gsTUFBc0IsNEJBQTRCO0lBU2hELFlBQVksWUFBd0M7UUFDbEQsSUFBSSxDQUFDLGdCQUFnQixHQUFHLFlBQVksQ0FBQyxnQkFBZ0IsQ0FBQztJQUN4RCxDQUFDOztBQVhILG9FQVlDOzs7QUFFRDs7Ozs7R0FLRztBQUNILE1BQWEsd0JBQXlCLFNBQVEsNEJBQTRCO0lBR3hFOzs7Ozs7T0FNRztJQUNILFlBQVkseUJBQXNEO1FBQ2hFLHlCQUF5QixLQUF6Qix5QkFBeUIsR0FBSyxtQ0FBeUIsQ0FBQyxNQUFNLEVBQUM7UUFDL0QsS0FBSyxDQUFDLHlCQUF5QixDQUFDLENBQUM7UUFDakMsSUFBSSxDQUFDLEtBQUssR0FBRyxHQUFHLENBQUMsY0FBYyxDQUFDLFlBQVksQ0FDMUMsR0FBRyx5QkFBeUIsQ0FBQyxTQUFTLElBQUkseUJBQXlCLENBQUMsUUFBUSxFQUFFLENBQy9FLENBQUM7SUFDSixDQUFDOztBQWhCSCw0REFpQkM7OztBQTBCRDs7R0FFRztBQUNILE1BQWEsOEJBQStCLFNBQVEsd0NBQXFCO0lBQ3ZFLFlBQ0UsS0FBZ0IsRUFDaEIsRUFBVSxFQUNWLEtBQTBDO1FBRTFDLE1BQU0sbUJBQW1CLEdBQ3ZCLEtBQUssQ0FBQyxtQkFBbUIsSUFBSSxLQUFLLENBQUMsYUFBYSxDQUFDLHVCQUF1QixDQUFDO1FBQzNFLE1BQU0sa0JBQWtCLEdBQ3RCLEtBQUssQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLGtCQUFrQixJQUFJLENBQUMsQ0FBQztRQUN2RCxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsRUFBRTtZQUNmLEdBQUcsS0FBSztZQUNSLG1CQUFtQjtZQUNuQixrQkFBa0I7U0FDbkIsQ0FBQyxDQUFDO1FBQ0gsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLEtBQUssSUFBSSxJQUFJLHdCQUF3QixFQUFFLENBQUM7UUFDNUQsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQztRQUN2RCxNQUFNLFdBQVcsR0FBRyx1Q0FBeUIsQ0FBQyxHQUFHLENBQy9DLEtBQUssQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUM3QixDQUFDO1FBQ0YsZ0NBQWdDO1FBQ2hDLE1BQU0sV0FBVyxHQUEyQjtZQUMxQyxHQUFHLEtBQUssQ0FBQyxXQUFXO1lBQ3BCLHFCQUFxQixFQUFFLCtCQUErQjtZQUN0RCx5QkFBeUIsRUFBRSwyQkFBMkI7WUFDdEQsbUJBQW1CLEVBQUUsa0JBQWtCLENBQUMsUUFBUSxFQUFFO1lBQ2xELHlCQUF5QixFQUFFLEdBQUc7WUFDOUIsVUFBVSxFQUFFLEtBQUssQ0FBQyxhQUFhLENBQUMsU0FBUztTQUMxQyxDQUFDO1FBRUYsSUFBSSxDQUFDLHVCQUF1QixDQUFDLE1BQU0sRUFBRTtZQUNuQyxLQUFLLEVBQUUsS0FBSyxDQUFDLEtBQUs7WUFDbEIsWUFBWSxFQUFFO2dCQUNaO29CQUNFLGFBQWEsRUFBRSxJQUFJO2lCQUNwQjthQUNGO1lBQ0QsV0FBVyxFQUFFO2dCQUNYLE9BQU8sRUFBRTtvQkFDUCxXQUFXO29CQUNYLDRCQUE0QixJQUFJLG1CQUFtQjtpQkFDcEQ7Z0JBQ0QsV0FBVyxFQUFFLHNCQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQzthQUNqQztZQUNELGdCQUFnQixFQUFFLGlCQUFpQixLQUFLLENBQUMsYUFBYSxDQUFDLFFBQVEsRUFBRTtZQUNqRSxVQUFVLEVBQUUsQ0FBQyxNQUFNLEVBQUUsT0FBTyxDQUFDO1lBQzdCLE9BQU8sRUFBRSxXQUFXO1lBQ3BCLFdBQVc7U0FDWixDQUFDLENBQUM7SUFDTCxDQUFDOztBQWpESCx3RUFrREM7OztBQU9EOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQkc7QUFDSCxNQUFhLDhDQUErQyxTQUFRLHNCQUFTO0lBTTNFLFlBQ0UsS0FBZ0IsRUFDaEIsRUFBVSxFQUNWLEtBQTBEO1FBRTFELEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFDakIsTUFBTSxRQUFRLEdBQUcsSUFBSSx3REFBcUMsQ0FDeEQsSUFBSSxFQUNKLFVBQVUsRUFDVixLQUFLLENBQ04sQ0FBQztRQUNGLFFBQVEsQ0FBQyxXQUFXLENBQUMsb0JBQW9CLENBQUM7WUFDeEMsSUFBSSxFQUFFLFNBQVM7U0FDaEIsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFlBQVksR0FBRyxRQUFRLENBQUMsWUFBWSxDQUFDO1FBQzFDLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDLFFBQVEsQ0FBQztRQUNsQyxJQUFJLENBQUMsV0FBVyxHQUFHLFFBQVEsQ0FBQyxXQUFXLENBQUM7UUFDeEMsSUFBSSxDQUFDLE9BQU8sR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFDO1FBQ2hDLElBQUksQ0FBQyxjQUFjLEdBQUcsUUFBUSxDQUFDLGNBQWMsQ0FBQztJQUNoRCxDQUFDOztBQXpCSCx3R0EwQkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEdXJhdGlvbiB9IGZyb20gXCJhd3MtY2RrLWxpYlwiO1xuaW1wb3J0ICogYXMgZWNzIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtZWNzXCI7XG5pbXBvcnQge1xuICBBcHBsaWNhdGlvbkxpc3RlbmVyLFxuICBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlcixcbiAgQXBwbGljYXRpb25UYXJnZXRHcm91cCxcbn0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1lbGFzdGljbG9hZGJhbGFuY2luZ3YyXCI7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tIFwiY29uc3RydWN0c1wiO1xuaW1wb3J0IHtcbiAgQXBwbGljYXRpb25Mb2FkQmFsYW5jZWROZXVyb254U2VydmljZSxcbiAgQXBwbGljYXRpb25Mb2FkQmFsYW5jZWROZXVyb254U2VydmljZVByb3BzLFxuICBOZXVyb254VGFza0RlZmluaXRpb24sXG4gIE5ldXJvbnhUYXNrRGVmaW5pdGlvblByb3BzQmFzZSxcbn0gZnJvbSBcIi4uL2Jhc2UvYXdzLWVjcy1wYXR0ZXJuc1wiO1xuaW1wb3J0IHtcbiAgSVZsbG1JbmZlcmVuY2VOZXVyb254SW1hZ2UsXG4gIFZsbG1JbmZlcmVuY2VOZXVyb254SW1hZ2UsXG59IGZyb20gXCIuLi9iYXNlL25ldXJvbnhcIjtcbmltcG9ydCB7IElOZXVyb254Q29udGFpbmVySW1hZ2UgfSBmcm9tIFwiLi4vYmFzZS9uZXVyb254LWNvbXBpbGVyXCI7XG5pbXBvcnQgeyBWbGxtRW5naW5lQXJndW1lbnRzUGFyc2VyIH0gZnJvbSBcIi4uL2Jhc2Uvc2VydmVyLWVuZ2luZS92bGxtLWVuZ2luZVwiO1xuaW1wb3J0IHsgVmxsbU54ZEluZmVyZW5jZUNvbXBpbGVkTW9kZWwgfSBmcm9tIFwiLi92bGxtLW54ZC1pbmZlcmVuY2UtY29tcGlsZXJcIjtcblxuZXhwb3J0IGludGVyZmFjZSBWbGxtTnhkSW5mZXJlbmNlSW1hZ2VPcHRpb25zIHtcbiAgcmVhZG9ubHkgdmxsbUdpdEJyYW5jaD86IHN0cmluZztcbiAgcmVhZG9ubHkgdmxsbUdpdENvbW1pdEhhc2g/OiBzdHJpbmc7XG59XG4vKipcbiAqIEJhc2UgY2xhc3MgZm9yIFZsbG1OeGRJbmZlcmVuY2VJbWFnZS5cbiAqL1xuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFZsbG1OeGRJbmZlcmVuY2VFY3NJbWFnZUJhc2UgaW1wbGVtZW50cyBJTmV1cm9ueENvbnRhaW5lckltYWdlIHtcbiAgLyoqXG4gICAqIFRoZSBjb250YWluZXIgaW1hZ2UuXG4gICAqL1xuICBhYnN0cmFjdCByZWFkb25seSBpbWFnZTogZWNzLkNvbnRhaW5lckltYWdlO1xuICAvKipcbiAgICogVGhlIG5ldXJvbnggU0RLIHZlcnNpb24uXG4gICAqL1xuICByZWFkb25seSBuZXVyb25TZGtWZXJzaW9uOiBzdHJpbmc7XG4gIGNvbnN0cnVjdG9yKG5ldXJvbnhJbWFnZTogSVZsbG1JbmZlcmVuY2VOZXVyb254SW1hZ2UpIHtcbiAgICB0aGlzLm5ldXJvblNka1ZlcnNpb24gPSBuZXVyb254SW1hZ2UubmV1cm9uU2RrVmVyc2lvbjtcbiAgfVxufVxuXG4vKipcbiAqIEluZmVyZW5jZSBFQ1MgY29udGFpbmVyIGltYWdlIGZvciB2TExNIG9uIE54RCBJbmZlcmVuY2UuXG4gKiBUaGlzIGltYWdlIHVzZXMgdGhlIG9mZmljaWFsIEFXUyBOZXVyb24gRGVlcCBMZWFybmluZyBDb250YWluZXJzIHdoaWNoIGNvbWUgd2l0aCB2TExNIHByZS1pbnN0YWxsZWQuXG4gKlxuICogQGV4YW1wbGUgbmV3IFZsbG1OeGRJbmZlcmVuY2VFY3NJbWFnZShWbGxtSW5mZXJlbmNlTmV1cm9ueEltYWdlLkxBVEVTVClcbiAqL1xuZXhwb3J0IGNsYXNzIFZsbG1OeGRJbmZlcmVuY2VFY3NJbWFnZSBleHRlbmRzIFZsbG1OeGRJbmZlcmVuY2VFY3NJbWFnZUJhc2Uge1xuICByZWFkb25seSBpbWFnZTogZWNzLkNvbnRhaW5lckltYWdlO1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBWbGxtTnhkSW5mZXJlbmNlSW1hZ2UgZnJvbSBhIGN1c3RvbSBuZXVyb254IGltYWdlLlxuICAgKiBUaGlzIHdpbGwgYnVpbGQgYSBjb250YWluZXIgaW1hZ2UgdXNpbmcgYSBEb2NrZXJmaWxlIHRoYXQgaW5zdGFsbHMgdkxMTSBmcm9tIHNvdXJjZS5cbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogbmV3IFZsbG1OeGRJbmZlcmVuY2VFY3NJbWFnZShWbGxtSW5mZXJlbmNlTmV1cm9ueEltYWdlLkxBVEVTVClcbiAgICovXG4gIGNvbnN0cnVjdG9yKHZsbG1JbmZlcmVuY2VOZXVyb254SW1hZ2U/OiBJVmxsbUluZmVyZW5jZU5ldXJvbnhJbWFnZSkge1xuICAgIHZsbG1JbmZlcmVuY2VOZXVyb254SW1hZ2UgPz89IFZsbG1JbmZlcmVuY2VOZXVyb254SW1hZ2UuTEFURVNUO1xuICAgIHN1cGVyKHZsbG1JbmZlcmVuY2VOZXVyb254SW1hZ2UpO1xuICAgIHRoaXMuaW1hZ2UgPSBlY3MuQ29udGFpbmVySW1hZ2UuZnJvbVJlZ2lzdHJ5KFxuICAgICAgYCR7dmxsbUluZmVyZW5jZU5ldXJvbnhJbWFnZS5pbWFnZU5hbWV9OiR7dmxsbUluZmVyZW5jZU5ldXJvbnhJbWFnZS5pbWFnZVRhZ31gLFxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBUYXNrIGRlZmluaXRpb24gZm9yIFZsbG1OeGRJbmZlcmVuY2UuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVmxsbU54ZEluZmVyZW5jZVRhc2tEZWZpbml0aW9uUHJvcHMgZXh0ZW5kcyBOZXVyb254VGFza0RlZmluaXRpb25Qcm9wc0Jhc2Uge1xuICAvKipcbiAgICogVGhlIG1vZGVsIHRvIGJlIGNvbXBpbGVkLlxuICAgKi9cbiAgcmVhZG9ubHkgY29tcGlsZWRNb2RlbDogVmxsbU54ZEluZmVyZW5jZUNvbXBpbGVkTW9kZWw7XG4gIC8qKlxuICAgKiBUaGUgaW1hZ2UgdG8gYmUgdXNlZCBmb3IgdGhlIGNvbnRhaW5lci5cbiAgICogQGRlZmF1bHQgLSBsYXRlc3QgVmxsbU54ZEluZmVyZW5jZUltYWdlXG4gICAqL1xuICByZWFkb25seSBpbWFnZT86IFZsbG1OeGRJbmZlcmVuY2VFY3NJbWFnZUJhc2U7XG4gIC8qKlxuICAgKiBUaGUgZW52aXJvbm1lbnQgdmFyaWFibGVzIHRvIHBhc3MgdG8gdGhlIGNvbnRhaW5lci5cbiAgICogVGhpcyBpcyBvbmx5IGFwcGxpY2FibGUgd2hlbiB1c2luZyBjb250YWluZXIgcnVudGltZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBlbnZpcm9ubWVudCB2YXJpYWJsZXMuXG4gICAqL1xuICByZWFkb25seSBlbnZpcm9ubWVudD86IHtcbiAgICBba2V5OiBzdHJpbmddOiBzdHJpbmc7XG4gIH07XG59XG5cbi8qKlxuICogVGFzayBkZWZpbml0aW9uIGZvciBWbGxtTnhkSW5mZXJlbmNlLlxuICovXG5leHBvcnQgY2xhc3MgVmxsbU54ZEluZmVyZW5jZVRhc2tEZWZpbml0aW9uIGV4dGVuZHMgTmV1cm9ueFRhc2tEZWZpbml0aW9uIHtcbiAgY29uc3RydWN0b3IoXG4gICAgc2NvcGU6IENvbnN0cnVjdCxcbiAgICBpZDogc3RyaW5nLFxuICAgIHByb3BzOiBWbGxtTnhkSW5mZXJlbmNlVGFza0RlZmluaXRpb25Qcm9wcyxcbiAgKSB7XG4gICAgY29uc3QgbmV1cm9ueEluc3RhbmNlVHlwZSA9XG4gICAgICBwcm9wcy5uZXVyb254SW5zdGFuY2VUeXBlID8/IHByb3BzLmNvbXBpbGVkTW9kZWwucmVjb21tZW5kZWRJbnN0YW5jZVR5cGU7XG4gICAgY29uc3QgdGVuc29yUGFyYWxsZWxTaXplID1cbiAgICAgIHByb3BzLmNvbXBpbGVkTW9kZWwudmxsbUFyZ3MudGVuc29yUGFyYWxsZWxTaXplID8/IDE7XG4gICAgc3VwZXIoc2NvcGUsIGlkLCB7XG4gICAgICAuLi5wcm9wcyxcbiAgICAgIG5ldXJvbnhJbnN0YW5jZVR5cGUsXG4gICAgICB0ZW5zb3JQYXJhbGxlbFNpemUsXG4gICAgfSk7XG4gICAgY29uc3QgaW1hZ2UgPSBwcm9wcy5pbWFnZSA/PyBuZXcgVmxsbU54ZEluZmVyZW5jZUVjc0ltYWdlKCk7XG4gICAgY29uc3QgcG9ydCA9IHByb3BzLmNvbXBpbGVkTW9kZWwudmxsbUFyZ3MucG9ydCA/PyA4MDAwO1xuICAgIGNvbnN0IHZsbG1DbGlBcmdzID0gVmxsbUVuZ2luZUFyZ3VtZW50c1BhcnNlci5jbGkoXG4gICAgICBwcm9wcy5jb21waWxlZE1vZGVsLnZsbG1BcmdzLFxuICAgICk7XG4gICAgLy8gUHJlcGFyZSBlbnZpcm9ubWVudCB2YXJpYWJsZXNcbiAgICBjb25zdCBlbnZpcm9ubWVudDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHtcbiAgICAgIC4uLnByb3BzLmVudmlyb25tZW50LFxuICAgICAgVkxMTV9ORVVST05fRlJBTUVXT1JLOiBcIm5ldXJvbngtZGlzdHJpYnV0ZWQtaW5mZXJlbmNlXCIsXG4gICAgICBORVVST05fQ09NUElMRURfQVJUSUZBQ1RTOiBcIm5ldXJvbi1jb21waWxlZC1hcnRpZmFjdHNcIixcbiAgICAgIE5FVVJPTl9SVF9OVU1fQ09SRVM6IHRlbnNvclBhcmFsbGVsU2l6ZS50b1N0cmluZygpLFxuICAgICAgWExBX0hBTkRMRV9TUEVDSUFMX1NDQUxBUjogXCIxXCIsXG4gICAgICBNT0RFTF9OQU1FOiBwcm9wcy5jb21waWxlZE1vZGVsLm1vZGVsTmFtZSxcbiAgICB9O1xuXG4gICAgdGhpcy5hZGRDb250YWluZXJXaXRoRGVmYXVsdChcInZMTE1cIiwge1xuICAgICAgaW1hZ2U6IGltYWdlLmltYWdlLFxuICAgICAgcG9ydE1hcHBpbmdzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBjb250YWluZXJQb3J0OiBwb3J0LFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIGhlYWx0aENoZWNrOiB7XG4gICAgICAgIGNvbW1hbmQ6IFtcbiAgICAgICAgICBcIkNNRC1TSEVMTFwiLFxuICAgICAgICAgIGBjdXJsIC1mIGh0dHA6Ly9sb2NhbGhvc3Q6JHtwb3J0fS9oZWFsdGggfHwgZXhpdCAxYCxcbiAgICAgICAgXSxcbiAgICAgICAgc3RhcnRQZXJpb2Q6IER1cmF0aW9uLm1pbnV0ZXMoNSksXG4gICAgICB9LFxuICAgICAgd29ya2luZ0RpcmVjdG9yeTogYC9vcHQvbWwvbW9kZWwvJHtwcm9wcy5jb21waWxlZE1vZGVsLnMzUHJlZml4fWAsXG4gICAgICBlbnRyeVBvaW50OiBbXCJ2bGxtXCIsIFwic2VydmVcIl0sXG4gICAgICBjb21tYW5kOiB2bGxtQ2xpQXJncyxcbiAgICAgIGVudmlyb25tZW50LFxuICAgIH0pO1xuICB9XG59XG5cbi8qKlxuICogUHJvcHMgZm9yIEFwcGxpY2F0aW9uTG9hZEJhbGFuY2VkVmxsbU54REluZmVyZW5jZVNlcnZpY2UuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXBwbGljYXRpb25Mb2FkQmFsYW5jZWRWbGxtTnhESW5mZXJlbmNlU2VydmljZVByb3BzIGV4dGVuZHMgQXBwbGljYXRpb25Mb2FkQmFsYW5jZWROZXVyb254U2VydmljZVByb3BzIHt9XG5cbi8qKlxuICogQXBwbGljYXRpb25Mb2FkQmFsYW5jZWRWbGxtTnhESW5mZXJlbmNlU2VydmljZSBpcyBhIHdyYXBwZXIgb2YgQXBwbGljYXRpb25Mb2FkQmFsYW5jZWROZXVyb254U2VydmljZUJhc2UuXG4gKiBJdCBwcm92aWRlcyBhIHNpbXBsZSB3YXkgdG8gZGVwbG95IHZMTE0gb24gTnhEIEluZmVyZW5jZS5cbiAqIEBleGFtcGxlXG4gKiBjb25zdCBjb21waWxlciA9IG5ldyBWbGxtTnhkSW5mZXJlbmNlQ29tcGlsZXIodGhpcywgXCJDb21waWxlclwiLCB7XG4gKiAgIHZwYyxcbiAqICAgYnVja2V0LFxuICogICBtb2RlbDogTW9kZWwuZnJvbUh1Z2dpbmdGYWNlKFwiZXhhbXBsZS9leGFtcGxlLTdiLWNoYXRcIiksXG4gKiB9KTtcbiAqIGNvbnN0IGNvbXBpbGVkTW9kZWwgPSBjb21waWxlci5jb21waWxlKCk7XG4gKiBjb25zdCB0YXNrRGVmaW5pdGlvbiA9IG5ldyBWbGxtTnhkSW5mZXJlbmNlVGFza0RlZmluaXRpb24oXG4gKiAgIHRoaXMsXG4gKiAgIFwiVGFza0RlZmluaXRpb25cIixcbiAqICAge1xuICogICAgIHZwYyxcbiAqICAgICBjb21waWxlZE1vZGVsLFxuICogICB9LFxuICogKTtcbiAqIG5ldyBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlZFZsbG1OeERJbmZlcmVuY2VTZXJ2aWNlKHRoaXMsIFwiU2VydmljZVwiLCB7XG4gKiAgIHRhc2tEZWZpbml0aW9uLFxuICogfSk7XG4gKi9cbmV4cG9ydCBjbGFzcyBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlZFZsbG1OeERJbmZlcmVuY2VTZXJ2aWNlIGV4dGVuZHMgQ29uc3RydWN0IHtcbiAgcmVhZG9ubHkgbG9hZEJhbGFuY2VyOiBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlcjtcbiAgcmVhZG9ubHkgbGlzdGVuZXI6IEFwcGxpY2F0aW9uTGlzdGVuZXI7XG4gIHJlYWRvbmx5IHRhcmdldEdyb3VwOiBBcHBsaWNhdGlvblRhcmdldEdyb3VwO1xuICByZWFkb25seSBzZXJ2aWNlOiBlY3MuRWMyU2VydmljZTtcbiAgcmVhZG9ubHkgdGFza0RlZmluaXRpb246IGVjcy5FYzJUYXNrRGVmaW5pdGlvbjtcbiAgY29uc3RydWN0b3IoXG4gICAgc2NvcGU6IENvbnN0cnVjdCxcbiAgICBpZDogc3RyaW5nLFxuICAgIHByb3BzOiBBcHBsaWNhdGlvbkxvYWRCYWxhbmNlZFZsbG1OeERJbmZlcmVuY2VTZXJ2aWNlUHJvcHMsXG4gICkge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG4gICAgY29uc3QgcmVzb3VyY2UgPSBuZXcgQXBwbGljYXRpb25Mb2FkQmFsYW5jZWROZXVyb254U2VydmljZShcbiAgICAgIHRoaXMsXG4gICAgICBcIlJlc291cmNlXCIsXG4gICAgICBwcm9wcyxcbiAgICApO1xuICAgIHJlc291cmNlLnRhcmdldEdyb3VwLmNvbmZpZ3VyZUhlYWx0aENoZWNrKHtcbiAgICAgIHBhdGg6IFwiL2hlYWx0aFwiLFxuICAgIH0pO1xuICAgIHRoaXMubG9hZEJhbGFuY2VyID0gcmVzb3VyY2UubG9hZEJhbGFuY2VyO1xuICAgIHRoaXMubGlzdGVuZXIgPSByZXNvdXJjZS5saXN0ZW5lcjtcbiAgICB0aGlzLnRhcmdldEdyb3VwID0gcmVzb3VyY2UudGFyZ2V0R3JvdXA7XG4gICAgdGhpcy5zZXJ2aWNlID0gcmVzb3VyY2Uuc2VydmljZTtcbiAgICB0aGlzLnRhc2tEZWZpbml0aW9uID0gcmVzb3VyY2UudGFza0RlZmluaXRpb247XG4gIH1cbn1cbiJdfQ==