UNPKG

@aws-cdk/aws-eks-v2-alpha

Version:

The CDK Construct Library for AWS::EKS

489 lines 71.8 kB
"use strict"; var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; } var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); var _, done = false; for (var i = decorators.length - 1; i >= 0; i--) { var context = {}; for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p]; for (var p in contextIn.access) context.access[p] = contextIn.access[p]; context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); }; var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context); if (kind === "accessor") { if (result === void 0) continue; if (result === null || typeof result !== "object") throw new TypeError("Object expected"); if (_ = accept(result.get)) descriptor.get = _; if (_ = accept(result.set)) descriptor.set = _; if (_ = accept(result.init)) initializers.unshift(_); } else if (_ = accept(result)) { if (kind === "field") initializers.unshift(_); else descriptor[key] = _; } } if (target) Object.defineProperty(target, contextIn.name, descriptor); done = true; }; var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) { var useValue = arguments.length > 2; for (var i = 0; i < initializers.length; i++) { value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg); } return useValue ? value : void 0; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Nodegroup = exports.TaintEffect = exports.CapacityType = exports.NodegroupAmiType = void 0; const jsiiDeprecationWarnings = require("../.warnings.jsii.js"); const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const constructs_1 = require("constructs"); const cluster_1 = require("./cluster"); const aws_eks_1 = require("aws-cdk-lib/aws-eks"); const aws_ec2_1 = require("aws-cdk-lib/aws-ec2"); const aws_iam_1 = require("aws-cdk-lib/aws-iam"); const core_1 = require("aws-cdk-lib/core"); const cxapi = require("aws-cdk-lib/cx-api"); const nodegroup_1 = require("./private/nodegroup"); const metadata_resource_1 = require("aws-cdk-lib/core/lib/metadata-resource"); const prop_injectable_1 = require("aws-cdk-lib/core/lib/prop-injectable"); /** * The AMI type for your node group. * * GPU instance types should use the `AL2_x86_64_GPU` AMI type, which uses the * Amazon EKS-optimized Linux AMI with GPU support or the `BOTTLEROCKET_ARM_64_NVIDIA` or `BOTTLEROCKET_X86_64_NVIDIA` * AMI types, which uses the Amazon EKS-optimized Linux AMI with Nvidia-GPU support. * * Non-GPU instances should use the `AL2_x86_64` AMI type, which uses the Amazon EKS-optimized Linux AMI. */ var NodegroupAmiType; (function (NodegroupAmiType) { /** * Amazon Linux 2 (x86-64) */ NodegroupAmiType["AL2_X86_64"] = "AL2_x86_64"; /** * Amazon Linux 2 with GPU support */ NodegroupAmiType["AL2_X86_64_GPU"] = "AL2_x86_64_GPU"; /** * Amazon Linux 2 (ARM-64) */ NodegroupAmiType["AL2_ARM_64"] = "AL2_ARM_64"; /** * Bottlerocket Linux (ARM-64) */ NodegroupAmiType["BOTTLEROCKET_ARM_64"] = "BOTTLEROCKET_ARM_64"; /** * Bottlerocket (x86-64) */ NodegroupAmiType["BOTTLEROCKET_X86_64"] = "BOTTLEROCKET_x86_64"; /** * Bottlerocket Linux with Nvidia-GPU support (ARM-64) */ NodegroupAmiType["BOTTLEROCKET_ARM_64_NVIDIA"] = "BOTTLEROCKET_ARM_64_NVIDIA"; /** * Bottlerocket with Nvidia-GPU support (x86-64) */ NodegroupAmiType["BOTTLEROCKET_X86_64_NVIDIA"] = "BOTTLEROCKET_x86_64_NVIDIA"; /** * Bottlerocket Linux (ARM-64) with FIPS enabled */ NodegroupAmiType["BOTTLEROCKET_ARM_64_FIPS"] = "BOTTLEROCKET_ARM_64_FIPS"; /** * Bottlerocket (x86-64) with FIPS enabled */ NodegroupAmiType["BOTTLEROCKET_X86_64_FIPS"] = "BOTTLEROCKET_x86_64_FIPS"; /** * Windows Core 2019 (x86-64) */ NodegroupAmiType["WINDOWS_CORE_2019_X86_64"] = "WINDOWS_CORE_2019_x86_64"; /** * Windows Core 2022 (x86-64) */ NodegroupAmiType["WINDOWS_CORE_2022_X86_64"] = "WINDOWS_CORE_2022_x86_64"; /** * Windows Full 2019 (x86-64) */ NodegroupAmiType["WINDOWS_FULL_2019_X86_64"] = "WINDOWS_FULL_2019_x86_64"; /** * Windows Full 2022 (x86-64) */ NodegroupAmiType["WINDOWS_FULL_2022_X86_64"] = "WINDOWS_FULL_2022_x86_64"; /** * Amazon Linux 2023 (x86-64) */ NodegroupAmiType["AL2023_X86_64_STANDARD"] = "AL2023_x86_64_STANDARD"; /** * Amazon Linux 2023 with AWS Neuron drivers (x86-64) */ NodegroupAmiType["AL2023_X86_64_NEURON"] = "AL2023_x86_64_NEURON"; /** * Amazon Linux 2023 with NVIDIA drivers (x86-64) */ NodegroupAmiType["AL2023_X86_64_NVIDIA"] = "AL2023_x86_64_NVIDIA"; /** * Amazon Linux 2023 with NVIDIA drivers (ARM-64) */ NodegroupAmiType["AL2023_ARM_64_NVIDIA"] = "AL2023_ARM_64_NVIDIA"; /** * Amazon Linux 2023 (ARM-64) */ NodegroupAmiType["AL2023_ARM_64_STANDARD"] = "AL2023_ARM_64_STANDARD"; })(NodegroupAmiType || (exports.NodegroupAmiType = NodegroupAmiType = {})); /** * Capacity type of the managed node group */ var CapacityType; (function (CapacityType) { /** * spot instances */ CapacityType["SPOT"] = "SPOT"; /** * on-demand instances */ CapacityType["ON_DEMAND"] = "ON_DEMAND"; /** * capacity block instances */ CapacityType["CAPACITY_BLOCK"] = "CAPACITY_BLOCK"; })(CapacityType || (exports.CapacityType = CapacityType = {})); /** * Effect types of kubernetes node taint. * * Note: These values are specifically for AWS EKS NodeGroups and use the AWS API format. * When using AWS CLI or API, taint effects must be NO_SCHEDULE, PREFER_NO_SCHEDULE, or NO_EXECUTE. * When using Kubernetes directly or kubectl, taint effects must be NoSchedule, PreferNoSchedule, or NoExecute. * * For Kubernetes manifests (like Karpenter NodePools), use string literals with PascalCase format: * - 'NoSchedule' instead of TaintEffect.NO_SCHEDULE * - 'PreferNoSchedule' instead of TaintEffect.PREFER_NO_SCHEDULE * - 'NoExecute' instead of TaintEffect.NO_EXECUTE * * @see https://docs.aws.amazon.com/eks/latest/userguide/node-taints-managed-node-groups.html */ var TaintEffect; (function (TaintEffect) { /** * NoSchedule */ TaintEffect["NO_SCHEDULE"] = "NO_SCHEDULE"; /** * PreferNoSchedule */ TaintEffect["PREFER_NO_SCHEDULE"] = "PREFER_NO_SCHEDULE"; /** * NoExecute */ TaintEffect["NO_EXECUTE"] = "NO_EXECUTE"; })(TaintEffect || (exports.TaintEffect = TaintEffect = {})); /** * The Nodegroup resource class * @resource AWS::EKS::Nodegroup */ let Nodegroup = (() => { let _classDecorators = [prop_injectable_1.propertyInjectable]; let _classDescriptor; let _classExtraInitializers = []; let _classThis; let _classSuper = core_1.Resource; var Nodegroup = class extends _classSuper { static { _classThis = this; } static { const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0; __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers); Nodegroup = _classThis = _classDescriptor.value; if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata }); } static [JSII_RTTI_SYMBOL_1] = { fqn: "@aws-cdk/aws-eks-v2-alpha.Nodegroup", version: "2.223.0-alpha.0" }; /** Uniquely identifies this class. */ static PROPERTY_INJECTION_ID = '@aws-cdk.aws-eks-v2-alpha.Nodegroup'; /** * Import the Nodegroup from attributes */ static fromNodegroupName(scope, id, nodegroupName) { class Import extends core_1.Resource { nodegroupName = nodegroupName; } return new Import(scope, id); } /** * ARN of the nodegroup * * @attribute */ nodegroupArn; /** * Nodegroup name * * @attribute */ nodegroupName; /** * the Amazon EKS cluster resource * * @attribute ClusterName */ cluster; /** * IAM role of the instance profile for the nodegroup */ role; desiredSize; maxSize; minSize; constructor(scope, id, props) { super(scope, id, { physicalName: props.nodegroupName, }); try { jsiiDeprecationWarnings._aws_cdk_aws_eks_v2_alpha_NodegroupProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, Nodegroup); } throw error; } // Enhanced CDK Analytics Telemetry (0, metadata_resource_1.addConstructMetadata)(this, props); this.cluster = props.cluster; this.desiredSize = props.desiredSize ?? props.minSize ?? 2; this.maxSize = props.maxSize ?? this.desiredSize; this.minSize = props.minSize ?? 1; (0, core_1.withResolved)(this.desiredSize, this.maxSize, (desired, max) => { if (desired === undefined) { return; } if (desired > max) { throw new Error(`Desired capacity ${desired} can't be greater than max size ${max}`); } }); (0, core_1.withResolved)(this.desiredSize, this.minSize, (desired, min) => { if (desired === undefined) { return; } if (desired < min) { throw new Error(`Minimum capacity ${min} can't be greater than desired size ${desired}`); } }); if (props.launchTemplateSpec && props.diskSize) { // see - https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html // and https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-nodegroup.html#cfn-eks-nodegroup-disksize throw new Error('diskSize must be specified within the launch template'); } if (props.instanceType && props.instanceTypes) { throw new Error('"instanceType is deprecated, please use "instanceTypes" only.'); } if (props.instanceType) { core_1.Annotations.of(this).addWarningV2('@aws-cdk/aws-eks:managedNodeGroupDeprecatedInstanceType', '"instanceType" is deprecated and will be removed in the next major version. please use "instanceTypes" instead'); } const instanceTypes = props.instanceTypes ?? (props.instanceType ? [props.instanceType] : undefined); let possibleAmiTypes = []; if (instanceTypes && instanceTypes.length > 0) { /** * if the user explicitly configured instance types, we can't caculate the expected ami type as we support * Amazon Linux 2, Bottlerocket, and Windows now. However we can check: * * 1. instance types of different CPU architectures are not mixed(e.g. X86 with ARM). * 2. user-specified amiType should be included in `possibleAmiTypes`. */ possibleAmiTypes = getPossibleAmiTypes(instanceTypes); // if the user explicitly configured an ami type, make sure it's included in the possibleAmiTypes if (props.amiType && !possibleAmiTypes.includes(props.amiType)) { throw new Error(`The specified AMI does not match the instance types architecture, either specify one of ${possibleAmiTypes.join(', ').toUpperCase()} or don't specify any`); } // if the user explicitly configured a Windows ami type, make sure the instanceType is allowed if (props.amiType && windowsAmiTypes.includes(props.amiType) && instanceTypes.filter(isWindowsSupportedInstanceType).length < instanceTypes.length) { throw new Error('The specified instanceType does not support Windows workloads. ' + 'Amazon EC2 instance types C3, C4, D2, I2, M4 (excluding m4.16xlarge), M6a.x, and ' + 'R3 instances aren\'t supported for Windows workloads.'); } } if (!props.nodeRole) { const ngRole = new aws_iam_1.Role(this, 'NodeGroupRole', { assumedBy: new aws_iam_1.ServicePrincipal('ec2.amazonaws.com'), }); ngRole.addManagedPolicy(aws_iam_1.ManagedPolicy.fromAwsManagedPolicyName('AmazonEKSWorkerNodePolicy')); ngRole.addManagedPolicy(aws_iam_1.ManagedPolicy.fromAwsManagedPolicyName('AmazonEKS_CNI_Policy')); ngRole.addManagedPolicy(aws_iam_1.ManagedPolicy.fromAwsManagedPolicyName('AmazonEC2ContainerRegistryReadOnly')); // Grant additional IPv6 networking permissions if running in IPv6 // https://docs.aws.amazon.com/eks/latest/userguide/cni-iam-role.html if (props.cluster.ipFamily == cluster_1.IpFamily.IP_V6) { ngRole.addToPrincipalPolicy(new aws_iam_1.PolicyStatement({ // eslint-disable-next-line @cdklabs/no-literal-partition resources: ['arn:aws:ec2:*:*:network-interface/*'], actions: [ 'ec2:AssignIpv6Addresses', 'ec2:UnassignIpv6Addresses', ], })); } this.role = ngRole; } else { this.role = props.nodeRole; } this.validateUpdateConfig(props.maxUnavailable, props.maxUnavailablePercentage); const resource = new aws_eks_1.CfnNodegroup(this, 'Resource', { clusterName: this.cluster.clusterName, nodegroupName: props.nodegroupName, nodeRole: this.role.roleArn, subnets: this.cluster.vpc.selectSubnets(props.subnets).subnetIds, /** * Case 1: If launchTemplate is explicitly specified with custom AMI, we cannot specify amiType, or the node group deployment will fail. * As we don't know if the custom AMI is specified in the lauchTemplate, we just use props.amiType. * * Case 2: If launchTemplate is not specified, we try to determine amiType from the instanceTypes and it could be either AL2 or Bottlerocket. * To avoid breaking changes, we use possibleAmiTypes[0] if amiType is undefined and make sure AL2 is always the first element in possibleAmiTypes * as AL2 is previously the `expectedAmi` and this avoids breaking changes. * * That being said, users now either have to explicitly specify correct amiType or just leave it undefined. */ amiType: props.launchTemplateSpec ? props.amiType : (props.amiType ?? possibleAmiTypes[0]), capacityType: props.capacityType ? props.capacityType.valueOf() : undefined, diskSize: props.diskSize, forceUpdateEnabled: props.forceUpdate ?? true, // note that we don't check if a launch template is configured here (even though it might configure instance types as well) // because this doesn't have a default value, meaning the user had to explicitly configure this. instanceTypes: instanceTypes?.map(t => t.toString()), labels: props.labels, taints: props.taints, launchTemplate: props.launchTemplateSpec, releaseVersion: props.releaseVersion, remoteAccess: props.remoteAccess ? { ec2SshKey: props.remoteAccess.sshKeyName, sourceSecurityGroups: props.remoteAccess.sourceSecurityGroups ? props.remoteAccess.sourceSecurityGroups.map(m => m.securityGroupId) : undefined, } : undefined, scalingConfig: { desiredSize: this.desiredSize, maxSize: this.maxSize, minSize: this.minSize, }, tags: props.tags, updateConfig: props.maxUnavailable || props.maxUnavailablePercentage ? { maxUnavailable: props.maxUnavailable, maxUnavailablePercentage: props.maxUnavailablePercentage, } : undefined, nodeRepairConfig: props.enableNodeAutoRepair ? { enabled: props.enableNodeAutoRepair, } : undefined, }); if (this.cluster instanceof cluster_1.Cluster) { // the controller runs on the worker nodes so they cannot // be deleted before the controller. if (this.cluster.albController) { constructs_1.Node.of(this.cluster.albController).addDependency(this); } } this.nodegroupArn = this.getResourceArnAttribute(resource.attrArn, { service: 'eks', resource: 'nodegroup', resourceName: this.physicalName, }); if (core_1.FeatureFlags.of(this).isEnabled(cxapi.EKS_NODEGROUP_NAME)) { this.nodegroupName = this.getResourceNameAttribute(resource.attrNodegroupName); } else { this.nodegroupName = this.getResourceNameAttribute(resource.ref); } } validateUpdateConfig(maxUnavailable, maxUnavailablePercentage) { if (!maxUnavailable && !maxUnavailablePercentage) return; if (maxUnavailable && maxUnavailablePercentage) { throw new Error('maxUnavailable and maxUnavailablePercentage are not allowed to be defined together'); } if (maxUnavailablePercentage && (maxUnavailablePercentage < 1 || maxUnavailablePercentage > 100)) { throw new Error(`maxUnavailablePercentage must be between 1 and 100, got ${maxUnavailablePercentage}`); } if (maxUnavailable) { if (maxUnavailable > this.maxSize) { throw new Error(`maxUnavailable must be lower than maxSize (${this.maxSize}), got ${maxUnavailable}`); } if (maxUnavailable < 1 || maxUnavailable > 100) { throw new Error(`maxUnavailable must be between 1 and 100, got ${maxUnavailable}`); } } } static { __runInitializers(_classThis, _classExtraInitializers); } }; return Nodegroup = _classThis; })(); exports.Nodegroup = Nodegroup; /** * AMI types of different architectures. Make sure AL2 is always the first element, which will be the default * AmiType if amiType and launchTemplateSpec are both undefined. */ const arm64AmiTypes = [ NodegroupAmiType.AL2_ARM_64, NodegroupAmiType.AL2023_ARM_64_STANDARD, NodegroupAmiType.BOTTLEROCKET_ARM_64, ]; const x8664AmiTypes = [ NodegroupAmiType.AL2_X86_64, NodegroupAmiType.AL2023_X86_64_STANDARD, NodegroupAmiType.BOTTLEROCKET_X86_64, NodegroupAmiType.WINDOWS_CORE_2019_X86_64, NodegroupAmiType.WINDOWS_CORE_2022_X86_64, NodegroupAmiType.WINDOWS_FULL_2019_X86_64, NodegroupAmiType.WINDOWS_FULL_2022_X86_64, ]; const windowsAmiTypes = [ NodegroupAmiType.WINDOWS_CORE_2019_X86_64, NodegroupAmiType.WINDOWS_CORE_2022_X86_64, NodegroupAmiType.WINDOWS_FULL_2019_X86_64, NodegroupAmiType.WINDOWS_FULL_2022_X86_64, ]; const gpuAmiTypes = [ NodegroupAmiType.AL2_X86_64_GPU, NodegroupAmiType.AL2023_X86_64_NEURON, NodegroupAmiType.AL2023_X86_64_NVIDIA, NodegroupAmiType.AL2023_ARM_64_NVIDIA, NodegroupAmiType.BOTTLEROCKET_X86_64_NVIDIA, NodegroupAmiType.BOTTLEROCKET_ARM_64_NVIDIA, ]; /** * This function check if the instanceType is supported by Windows AMI. * https://docs.aws.amazon.com/eks/latest/userguide/windows-support.html * @param instanceType The EC2 instance type */ function isWindowsSupportedInstanceType(instanceType) { // compare instanceType to forbidden InstanceTypes for Windows. Add exception for m6a.16xlarge. // NOTE: i2 instance class is not present in the InstanceClass enum. const forbiddenInstanceClasses = [aws_ec2_1.InstanceClass.C3, aws_ec2_1.InstanceClass.C4, aws_ec2_1.InstanceClass.D2, aws_ec2_1.InstanceClass.M4, aws_ec2_1.InstanceClass.M6A, aws_ec2_1.InstanceClass.R3]; return instanceType.toString() === aws_ec2_1.InstanceType.of(aws_ec2_1.InstanceClass.M4, aws_ec2_1.InstanceSize.XLARGE16).toString() || forbiddenInstanceClasses.every((c) => !instanceType.sameInstanceClassAs(aws_ec2_1.InstanceType.of(c, aws_ec2_1.InstanceSize.LARGE)) && !instanceType.toString().match(/^i2/)); } /** * This function examines the CPU architecture of every instance type and determines * what AMI types are compatible for all of them. it either throws or produces an array of possible AMI types because * instance types of different CPU architectures are not supported. * @param instanceTypes The instance types * @returns NodegroupAmiType[] */ function getPossibleAmiTypes(instanceTypes) { function typeToArch(instanceType) { return (0, nodegroup_1.isGpuInstanceType)(instanceType) ? 'GPU' : instanceType.architecture; } const archAmiMap = new Map([ [aws_ec2_1.InstanceArchitecture.ARM_64, arm64AmiTypes], [aws_ec2_1.InstanceArchitecture.X86_64, x8664AmiTypes], ['GPU', gpuAmiTypes], ]); const architectures = new Set(instanceTypes.map(typeToArch)); if (architectures.size === 0) { // protective code, the current implementation will never result in this. throw new Error(`Cannot determine any ami type compatible with instance types: ${instanceTypes.map(i => i.toString()).join(', ')}`); } if (architectures.size > 1) { throw new Error('instanceTypes of different architectures is not allowed'); } return archAmiMap.get(Array.from(architectures)[0]); } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFuYWdlZC1ub2RlZ3JvdXAuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJtYW5hZ2VkLW5vZGVncm91cC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSwyQ0FBNkM7QUFDN0MsdUNBQXdEO0FBQ3hELGlEQUFtRDtBQUNuRCxpREFBdUk7QUFDdkksaURBQW9HO0FBQ3BHLDJDQUFnRztBQUNoRyw0Q0FBNEM7QUFDNUMsbURBQXdEO0FBQ3hELDhFQUE4RTtBQUM5RSwwRUFBMEU7QUFhMUU7Ozs7Ozs7O0dBUUc7QUFDSCxJQUFZLGdCQXlFWDtBQXpFRCxXQUFZLGdCQUFnQjtJQUMxQjs7T0FFRztJQUNILDZDQUF5QixDQUFBO0lBQ3pCOztPQUVHO0lBQ0gscURBQWlDLENBQUE7SUFDakM7O09BRUc7SUFDSCw2Q0FBeUIsQ0FBQTtJQUN6Qjs7T0FFRztJQUNILCtEQUEyQyxDQUFBO0lBQzNDOztPQUVHO0lBQ0gsK0RBQTJDLENBQUE7SUFDM0M7O09BRUc7SUFDSCw2RUFBeUQsQ0FBQTtJQUN6RDs7T0FFRztJQUNILDZFQUF5RCxDQUFBO0lBQ3pEOztPQUVHO0lBQ0gseUVBQXFELENBQUE7SUFDckQ7O09BRUc7SUFDSCx5RUFBcUQsQ0FBQTtJQUNyRDs7T0FFRztJQUNILHlFQUFxRCxDQUFBO0lBQ3JEOztPQUVHO0lBQ0gseUVBQXFELENBQUE7SUFDckQ7O09BRUc7SUFDSCx5RUFBcUQsQ0FBQTtJQUNyRDs7T0FFRztJQUNILHlFQUFxRCxDQUFBO0lBQ3JEOztPQUVHO0lBQ0gscUVBQWlELENBQUE7SUFDakQ7O09BRUc7SUFDSCxpRUFBNkMsQ0FBQTtJQUM3Qzs7T0FFRztJQUNILGlFQUE2QyxDQUFBO0lBQzdDOztPQUVHO0lBQ0gsaUVBQTZDLENBQUE7SUFDN0M7O09BRUc7SUFDSCxxRUFBaUQsQ0FBQTtBQUNuRCxDQUFDLEVBekVXLGdCQUFnQixnQ0FBaEIsZ0JBQWdCLFFB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TUFBTSxFQUFFLGFBQWEsQ0FBQztRQUM1QyxDQUFDLDhCQUFvQixDQUFDLE1BQU0sRUFBRSxhQUFhLENBQUM7UUFDNUMsQ0FBQyxLQUFLLEVBQUUsV0FBVyxDQUFDO0tBQ3JCLENBQUMsQ0FBQztJQUNILE1BQU0sYUFBYSxHQUF5QixJQUFJLEdBQUcsQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7SUFFbkYsSUFBSSxhQUFhLENBQUMsSUFBSSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMseUVBQXlFO1FBQ3ZHLE1BQU0sSUFBSSxLQUFLLENBQUMsaUVBQWlFLGFBQWEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3RJLENBQUM7SUFFRCxJQUFJLGFBQWEsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDM0IsTUFBTSxJQUFJLEtBQUssQ0FBQyx5REFBeUQsQ0FBQyxDQUFDO0lBQzdFLENBQUM7SUFFRCxPQUFPLFVBQVUsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBRSxDQUFDO0FBQ3ZELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb25zdHJ1Y3QsIE5vZGUgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IENsdXN0ZXIsIElDbHVzdGVyLCBJcEZhbWlseSB9IGZyb20gJy4vY2x1c3Rlcic7XG5pbXBvcnQgeyBDZm5Ob2RlZ3JvdXAgfSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtZWtzJztcbmltcG9ydCB7IEluc3RhbmNlVHlwZSwgSVNlY3VyaXR5R3JvdXAsIFN1Ym5ldFNlbGVjdGlvbiwgSW5zdGFuY2VBcmNoaXRlY3R1cmUsIEluc3RhbmNlQ2xhc3MsIEluc3RhbmNlU2l6ZSB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1lYzInO1xuaW1wb3J0IHsgSVJvbGUsIE1hbmFnZWRQb2xpY3ksIFBvbGljeVN0YXRlbWVudCwgUm9sZSwgU2VydmljZVByaW5jaXBhbCB9IGZyb20gJ2F3cy1jZGstbGliL2F3cy1pYW0nO1xuaW1wb3J0IHsgSVJlc291cmNlLCBSZXNvdXJjZSwgQW5ub3RhdGlvbnMsIHdpdGhSZXNvbHZlZCwgRmVhdHVyZUZsYWdzIH0gZnJvbSAnYXdzLWNkay1saWIvY29yZSc7XG5pbXBvcnQgKiBhcyBjeGFwaSBmcm9tICdhd3MtY2RrLWxpYi9jeC1hcGknO1xuaW1wb3J0IHsgaXNHcHVJbnN0YW5jZVR5cGUgfSBmcm9tICcuL3ByaXZhdGUvbm9kZWdyb3VwJztcbmltcG9ydCB7IGFkZENvbnN0cnVjdE1ldGFkYXRhIH0gZnJvbSAnYXdzLWNkay1saWIvY29yZS9saWIvbWV0YWRhdGEtcmVzb3VyY2UnO1xuaW1wb3J0IHsgcHJvcGVydHlJbmplY3RhYmxlIH0gZnJvbSAnYXdzLWNkay1saWIvY29yZS9saWIvcHJvcC1pbmplY3RhYmxlJztcblxuLyoqXG4gKiBOb2RlR3JvdXAgaW50ZXJmYWNlXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSU5vZGVncm91cCBleHRlbmRzIElSZXNvdXJjZSB7XG4gIC8qKlxuICAgKiBOYW1lIG9mIHRoZSBub2RlZ3JvdXBcbiAgICogQGF0dHJpYnV0ZVxuICAgKi9cbiAgcmVhZG9ubHkgbm9kZWdyb3VwTmFtZTogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBBTUkgdHlwZSBmb3IgeW91ciBub2RlIGdyb3VwLlxuICpcbiAqIEdQVSBpbnN0YW5jZSB0eXBlcyBzaG91bGQgdXNlIHRoZSBgQUwyX3g4Nl82NF9HUFVgIEFNSSB0eXBlLCB3aGljaCB1c2VzIHRoZVxuICogQW1hem9uIEVLUy1vcHRpbWl6ZWQgTGludXggQU1JIHdpdGggR1BVIHN1cHBvcnQgb3IgdGhlIGBCT1RUTEVST0NLRVRfQVJNXzY0X05WSURJQWAgb3IgYEJPVFRMRVJPQ0tFVF9YODZfNjRfTlZJRElBYFxuICogQU1JIHR5cGVzLCB3aGljaCB1c2VzIHRoZSBBbWF6b24gRUtTLW9wdGltaXplZCBMaW51eCBBTUkgd2l0aCBOdmlkaWEtR1BVIHN1cHBvcnQuXG4gKlxuICogTm9uLUdQVSBpbnN0YW5jZXMgc2hvdWxkIHVzZSB0aGUgYEFMMl94ODZfNjRgIEFNSSB0eXBlLCB3aGljaCB1c2VzIHRoZSBBbWF6b24gRUtTLW9wdGltaXplZCBMaW51eCBBTUkuXG4gKi9cbmV4cG9ydCBlbnVtIE5vZGVncm91cEFtaVR5cGUge1xuICAvKipcbiAgICogQW1hem9uIExpbnV4IDIgKHg4Ni02NClcbiAgICovXG4gIEFMMl9YODZfNjQgPSAnQUwyX3g4Nl82NCcsXG4gIC8qKlxuICAgKiBBbWF6b24gTGludXggMiB3aXRoIEdQVSBzdXBwb3J0XG4gICAqL1xuICBBTDJfWDg2XzY0X0dQVSA9ICdBTDJfeDg2XzY0X0dQVScsXG4gIC8qKlxuICAgKiBBbWF6b24gTGludXggMiAoQVJNLTY0KVxuICAgKi9cbiAgQUwyX0FSTV82NCA9ICdBTDJfQVJNXzY0JyxcbiAgLyoqXG4gICAqICBCb3R0bGVyb2NrZXQgTGludXggKEFSTS02NClcbiAgICovXG4gIEJPVFRMRVJPQ0tFVF9BUk1fNjQgPSAnQk9UVExFUk9DS0VUX0FSTV82NCcsXG4gIC8qKlxuICAgKiBCb3R0bGVyb2NrZXQgKHg4Ni02NClcbiAgICovXG4gIEJPVFRMRVJPQ0tFVF9YODZfNjQgPSAnQk9UVExFUk9DS0VUX3g4Nl82NCcsXG4gIC8qKlxuICAgKiAgQm90dGxlcm9ja2V0IExpbnV4IHdpdGggTnZpZGlhLUdQVSBzdXBwb3J0IChBUk0tNjQpXG4gICAqL1xuICBCT1RUTEVST0NLRVRfQVJNXzY0X05WSURJQSA9ICdCT1RUTEVST0NLRVRfQVJNXzY0X05WSURJQScsXG4gIC8qKlxuICAgKiBCb3R0bGVyb2NrZXQgd2l0aCBOdmlkaWEtR1BVIHN1cHBvcnQgKHg4Ni02NClcbiAgICovXG4gIEJPVFRMRVJPQ0tFVF9YODZfNjRfTlZJRElBID0gJ0JPVFRMRVJPQ0tFVF94ODZfNjRfTlZJRElBJyxcbiAgLyoqXG4gICAqIEJvdHRsZXJvY2tldCBMaW51eCAoQVJNLTY0KSB3aXRoIEZJUFMgZW5hYmxlZFxuICAgKi9cbiAgQk9UVExFUk9DS0VUX0FSTV82NF9GSVBTID0gJ0JPVFRMRVJPQ0tFVF9BUk1fNjRfRklQUycsXG4gIC8qKlxuICAgKiBCb3R0bGVyb2NrZXQgKHg4Ni02NCkgd2l0aCBGSVBTIGVuYWJsZWRcbiAgICovXG4gIEJPVFRMRVJPQ0tFVF9YODZfNjRfRklQUyA9ICdCT1RUTEVST0NLRVRfeDg2XzY0X0ZJUFMnLFxuICAvKipcbiAgICogV2luZG93cyBDb3JlIDIwMTkgKHg4Ni02NClcbiAgICovXG4gIFdJTkRPV1NfQ09SRV8yMDE5X1g4Nl82NCA9ICdXSU5ET1dTX0NPUkVfMjAxOV94ODZfNjQnLFxuICAvKipcbiAgICogV2luZG93cyBDb3JlIDIwMjIgKHg4Ni02NClcbiAgICovXG4gIFdJTkRPV1NfQ09SRV8yMDIyX1g4Nl82NCA9ICdXSU5ET1dTX0NPUkVfMjAyMl94ODZfNjQnLFxuICAvKipcbiAgICogV2luZG93cyBGdWxsIDIwMTkgKHg4Ni02NClcbiAgICovXG4gIFdJTkRPV1NfRlVMTF8yMDE5X1g4Nl82NCA9ICdXSU5ET1dTX0ZVTExfMjAxOV94ODZfNjQnLFxuICAvKipcbiAgICogV2luZG93cyBGdWxsIDIwMjIgKHg4Ni02NClcbiAgICovXG4gIFdJTkRPV1NfRlVMTF8yMDIyX1g4Nl82NCA9ICdXSU5ET1dTX0ZVTExfMjAyMl94ODZfNjQnLFxuICAvKipcbiAgICogQW1hem9uIExpbnV4IDIwMjMgKHg4Ni02NClcbiAgICovXG4gIEFMMjAyM19YODZfNjRfU1RBTkRBUkQgPSAnQUwyMDIzX3g4Nl82NF9TVEFOREFSRCcsXG4gIC8qKlxuICAgKiBBbWF6b24gTGludXggMjAyMyB3aXRoIEFXUyBOZXVyb24gZHJpdmVycyAoeDg2LTY0KVxuICAgKi9cbiAgQUwyMDIzX1g4Nl82NF9ORVVST04gPSAnQUwyMDIzX3g4Nl82NF9ORVVST04nLFxuICAvKipcbiAgICogQW1hem9uIExpbnV4IDIwMjMgd2l0aCBOVklESUEgZHJpdmVycyAoeDg2LTY0KVxuICAgKi9cbiAgQUwyMDIzX1g4Nl82NF9OVklESUEgPSAnQUwyMDIzX3g4Nl82NF9OVklESUEnLFxuICAvKipcbiAgICogQW1hem9uIExpbnV4IDIwMjMgd2l0aCBOVklESUEgZHJpdmVycyAoQVJNLTY0KVxuICAgKi9cbiAgQUwyMDIzX0FSTV82NF9OVklESUEgPSAnQUwyMDIzX0FSTV82NF9OVklESUEnLFxuICAvKipcbiAgICogQW1hem9uIExpbnV4IDIwMjMgKEFSTS02NClcbiAgICovXG4gIEFMMjAyM19BUk1fNjRfU1RBTkRBUkQgPSAnQUwyMDIzX0FSTV82NF9TVEFOREFSRCcsXG59XG5cbi8qKlxuICogQ2FwYWNpdHkgdHlwZSBvZiB0aGUgbWFuYWdlZCBub2RlIGdyb3VwXG4gKi9cbmV4cG9ydCBlbnVtIENhcGFjaXR5VHlwZSB7XG4gIC8qKlxuICAgKiBzcG90IGluc3RhbmNlc1xuICAgKi9cbiAgU1BPVCA9ICdTUE9UJyxcbiAgLyoqXG4gICAqIG9uLWRlbWFuZCBpbnN0YW5jZXNcbiAgICovXG4gIE9OX0RFTUFORCA9ICdPTl9ERU1BTkQnLFxuICAvKipcbiAgICogY2FwYWNpdHkgYmxvY2sgaW5zdGFuY2VzXG4gICAqL1xuICBDQVBBQ0lUWV9CTE9DSyA9ICdDQVBBQ0lUWV9CTE9DSycsXG59XG5cbi8qKlxuICogVGhlIHJlbW90ZSBhY2Nlc3MgKFNTSCkgY29uZmlndXJhdGlvbiB0byB1c2Ugd2l0aCB5b3VyIG5vZGUgZ3JvdXAuXG4gKlxuICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQVdTQ2xvdWRGb3JtYXRpb24vbGF0ZXN0L1VzZXJHdWlkZS9hd3MtcHJvcGVydGllcy1la3Mtbm9kZWdyb3VwLXJlbW90ZWFjY2Vzcy5odG1sXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTm9kZWdyb3VwUmVtb3RlQWNjZXNzIHtcbiAgLyoqXG4gICAqIFRoZSBBbWF6b24gRUMyIFNTSCBrZXkgdGhhdCBwcm92aWRlcyBhY2Nlc3MgZm9yIFNTSCBjb21tdW5pY2F0aW9uIHdpdGggdGhlIHdvcmtlciBub2RlcyBpbiB0aGUgbWFuYWdlZCBub2RlIGdyb3VwLlxuICAgKi9cbiAgcmVhZG9ubHkgc3NoS2V5TmFtZTogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIHNlY3VyaXR5IGdyb3VwcyB0aGF0IGFyZSBhbGxvd2VkIFNTSCBhY2Nlc3MgKHBvcnQgMjIpIHRvIHRoZSB3b3JrZXIgbm9kZXMuIElmIHlvdSBzcGVjaWZ5IGFuIEFtYXpvbiBFQzIgU1NIXG4gICAqIGtleSBidXQgZG8gbm90IHNwZWNpZnkgYSBzb3VyY2Ugc2VjdXJpdHkgZ3JvdXAgd2hlbiB5b3UgY3JlYXRlIGEgbWFuYWdlZCBub2RlIGdyb3VwLCB0aGVuIHBvcnQgMjIgb24gdGhlIHdvcmtlclxuICAgKiBub2RlcyBpcyBvcGVuZWQgdG8gdGhlIGludGVybmV0ICgwLjAuMC4wLzApLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHBvcnQgMjIgb24gdGhlIHdvcmtlciBub2RlcyBpcyBvcGVuZWQgdG8gdGhlIGludGVybmV0ICgwLjAuMC4wLzApXG4gICAqL1xuICByZWFkb25seSBzb3VyY2VTZWN1cml0eUdyb3Vwcz86IElTZWN1cml0eUdyb3VwW107XG59XG5cbi8qKlxuICogTGF1bmNoIHRlbXBsYXRlIHByb3BlcnR5IHNwZWNpZmljYXRpb25cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBMYXVuY2hUZW1wbGF0ZVNwZWMge1xuICAvKipcbiAgICogVGhlIExhdW5jaCB0ZW1wbGF0ZSBJRFxuICAgKi9cbiAgcmVhZG9ubHkgaWQ6IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBsYXVuY2ggdGVtcGxhdGUgdmVyc2lvbiB0byBiZSB1c2VkIChvcHRpb25hbCkuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gdGhlIGRlZmF1bHQgdmVyc2lvbiBvZiB0aGUgbGF1bmNoIHRlbXBsYXRlXG4gICAqL1xuICByZWFkb25seSB2ZXJzaW9uPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIEVmZmVjdCB0eXBlcyBvZiBrdWJlcm5ldGVzIG5vZGUgdGFpbnQuXG4gKlxuICogTm90ZTogVGhlc2UgdmFsdWVzIGFyZSBzcGVjaWZpY2FsbHkgZm9yIEFXUyBFS1MgTm9kZUdyb3VwcyBhbmQgdXNlIHRoZSBBV1MgQVBJIGZvcm1hdC5cbiAqIFdoZW4gdXNpbmcgQVdTIENMSSBvciBBUEksIHRhaW50IGVmZmVjdHMgbXVzdCBiZSBOT19TQ0hFRFVMRSwgUFJFRkVSX05PX1NDSEVEVUxFLCBvciBOT19FWEVDVVRFLlxuICogV2hlbiB1c2luZyBLdWJlcm5ldGVzIGRpcmVjdGx5IG9yIGt1YmVjdGwsIHRhaW50IGVmZmVjdHMgbXVzdCBiZSBOb1NjaGVkdWxlLCBQcmVmZXJOb1NjaGVkdWxlLCBvciBOb0V4ZWN1dGUuXG4gKlxuICogRm9yIEt1YmVybmV0ZXMgbWFuaWZlc3RzIChsaWtlIEthcnBlbnRlciBOb2RlUG9vbHMpLCB1c2Ugc3RyaW5nIGxpdGVyYWxzIHdpdGggUGFzY2FsQ2FzZSBmb3JtYXQ6XG4gKiAtICdOb1NjaGVkdWxlJyBpbnN0ZWFkIG9mIFRhaW50RWZmZWN0Lk5PX1NDSEVEVUxFXG4gKiAtICdQcmVmZXJOb1NjaGVkdWxlJyBpbnN0ZWFkIG9mIFRhaW50RWZmZWN0LlBSRUZFUl9OT19TQ0hFRFVMRVxuICogLSAnTm9FeGVjdXRlJyBpbnN0ZWFkIG9mIFRhaW50RWZmZWN0Lk5PX0VYRUNVVEVcbiAqXG4gKiBAc2VlIGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9la3MvbGF0ZXN0L3VzZXJndWlkZS9ub2RlLXRhaW50cy1tYW5hZ2VkLW5vZGUtZ3JvdXBzLmh0bWxcbiAqL1xuZXhwb3J0IGVudW0gVGFpbnRFZmZlY3Qge1xuICAvKipcbiAgICogTm9TY2hlZHVsZVxuICAgKi9cbiAgTk9fU0NIRURVTEUgPSAnTk9fU0NIRURVTEUnLFxuICAvKipcbiAgICogUHJlZmVyTm9TY2hlZHVsZVxuICAgKi9cbiAgUFJFRkVSX05PX1NDSEVEVUxFID0gJ1BSRUZFUl9OT19TQ0hFRFVMRScsXG4gIC8qKlxuICAgKiBOb0V4ZWN1dGVcbiAgICovXG4gIE5PX0VYRUNVVEUgPSAnTk9fRVhFQ1VURScsXG59XG5cbi8qKlxuICogVGFpbnQgaW50ZXJmYWNlXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVGFpbnRTcGVjIHtcbiAgLyoqXG4gICAqIEVmZmVjdCB0eXBlXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm9uZVxuICAgKi9cbiAgcmVhZG9ubHkgZWZmZWN0PzogVGFpbnRFZmZlY3Q7XG4gIC8qKlxuICAgKiBUYWludCBrZXlcbiAgICpcbiAgICogQGRlZmF1bHQgLSBOb25lXG4gICAqL1xuICByZWFkb25seSBrZXk/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUYWludCB2YWx1ZVxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vbmVcbiAgICovXG4gIHJlYWRvbmx5IHZhbHVlPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBOb2RlZ3JvdXAgT3B0aW9ucyBmb3IgYWRkTm9kZUdyb3VwKCkgbWV0aG9kXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTm9kZWdyb3VwT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBOYW1lIG9mIHRoZSBOb2RlZ3JvdXBcbiAgICpcbiAgICogQGRlZmF1bHQgLSByZXNvdXJjZSBJRFxuICAgKi9cbiAgcmVhZG9ubHkgbm9kZWdyb3VwTmFtZT86IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBzdWJuZXRzIHRvIHVzZSBmb3IgdGhlIEF1dG8gU2NhbGluZyBncm91cCB0aGF0IGlzIGNyZWF0ZWQgZm9yIHlvdXIgbm9kZSBncm91cC4gQnkgc3BlY2lmeWluZyB0aGVcbiAgICogU3VibmV0U2VsZWN0aW9uLCB0aGUgc2VsZWN0ZWQgc3VibmV0cyB3aWxsIGF1dG9tYXRpY2FsbHkgYXBwbHkgcmVxdWlyZWQgdGFncyBpLmUuXG4gICAqIGBrdWJlcm5ldGVzLmlvL2NsdXN0ZXIvQ0xVU1RFUl9OQU1FYCB3aXRoIGEgdmFsdWUgb2YgYHNoYXJlZGAsIHdoZXJlIGBDTFVTVEVSX05BTUVgIGlzIHJlcGxhY2VkIHdpdGhcbiAgICogdGhlIG5hbWUgb2YgeW91ciBjbHVzdGVyLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIHByaXZhdGUgc3VibmV0c1xuICAgKi9cbiAgcmVhZG9ubHkgc3VibmV0cz86IFN1Ym5ldFNlbGVjdGlvbjtcbiAgLyoqXG4gICAqIFRoZSBBTUkgdHlwZSBmb3IgeW91ciBub2RlIGdyb3VwLiBJZiB5b3UgZXhwbGljaXRseSBzcGVjaWZ5IHRoZSBsYXVuY2hUZW1wbGF0ZSB3aXRoIGN1c3RvbSBBTUksIGRvIG5vdCBzcGVjaWZ5IHRoaXMgcHJvcGVydHksIG9yXG4gICAqIHRoZSBub2RlIGdyb3VwIGRlcGxveW1lbnQgd2lsbCBmYWlsLiBJbiBvdGhlciBjYXNlcywgeW91IHdpbGwgbmVlZCB0byBzcGVjaWZ5IGNvcnJlY3QgYW1pVHlwZSBmb3IgdGhlIG5vZGVncm91cC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBhdXRvLWRldGVybWluZWQgZnJvbSB0aGUgaW5zdGFuY2VUeXBlcyBwcm9wZXJ0eSB3aGVuIGxhdW5jaFRlbXBsYXRlU3BlYyBwcm9wZXJ0eSBpcyBub3Qgc3BlY2lmaWVkXG4gICAqL1xuICByZWFkb25seSBhbWlUeXBlPzogTm9kZWdyb3VwQW1pVHlwZTtcbiAgLyoqXG4gICAqIFRoZSByb290IGRldmljZSBkaXNrIHNpemUgKGluIEdpQikgZm9yIHlvdXIgbm9kZSBncm91cCBpbnN0YW5jZXMuXG4gICAqXG4gICAqIEBkZWZhdWx0IDIwXG4gICAqL1xuICByZWFkb25seSBkaXNrU2l6ZT86IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSBjdXJyZW50IG51bWJlciBvZiB3b3JrZXIgbm9kZXMgdGhhdCB0aGUgbWFuYWdlZCBub2RlIGdyb3VwIHNob3VsZCBtYWludGFpbi4gSWYgbm90IHNwZWNpZmllZCxcbiAgICogdGhlIG5vZGV3Z3JvdXAgd2lsbCBpbml0aWFsbHkgY3JlYXRlIGBtaW5TaXplYCBpbnN0YW5jZXMuXG4gICAqXG4gICAqIEBkZWZhdWx0IDJcbiAgICovXG4gIHJlYWRvbmx5IGRlc2lyZWRTaXplPzogbnVtYmVyO1xuICAvKipcbiAgICogVGhlIG1heGltdW0gbnVtYmVyIG9mIHdvcmtlciBub2RlcyB0aGF0IHRoZSBtYW5hZ2VkIG5vZGUgZ3JvdXAgY2FuIHNjYWxlIG91dCB0by4gTWFuYWdlZCBub2RlIGdyb3VwcyBjYW4gc3VwcG9ydCB1cCB0byAxMDAgbm9kZXMgYnkgZGVmYXVsdC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBkZXNpcmVkU2l6ZVxuICAgKi9cbiAgcmVhZG9ubHkgbWF4U2l6ZT86IG51bWJlcjtcbiAgLyoqXG4gICAqIFRoZSBtaW5pbXVtIG51bWJlciBvZiB3b3JrZXIgbm9kZXMgdGhhdCB0aGUgbWFuYWdlZCBub2RlIGdyb3VwIGNhbiBzY2FsZSBpbiB0by4gVGhpcyBudW1iZXIgbXVzdCBiZSBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gemVyby5cbiAgICpcbiAgICogQGRlZmF1bHQgMVxuICAgKi9cbiAgcmVhZG9ubHkgbWluU2l6ZT86IG51bWJlcjtcbiAgLyoqXG4gICAqIEZvcmNlIHRoZSB1cGRhdGUgaWYgdGhlIGV4aXN0aW5nIG5vZGUgZ3JvdXAncyBwb2RzIGFyZSB1bmFibGUgdG8gYmUgZHJhaW5lZCBkdWUgdG8gYSBwb2QgZGlzcnVwdGlvbiBidWRnZXQgaXNzdWUuXG4gICAqIElmIGFuIHVwZGF0ZSBmYWlscyBiZWNhdXNlIHBvZHMgY291bGQgbm90IGJlIGRyYWluZWQsIHlvdSBjYW4gZm9yY2UgdGhlIHVwZGF0ZSBhZnRlciBpdCBmYWlscyB0byB0ZXJtaW5hdGUgdGhlIG9sZFxuICAgKiBub2RlIHdoZXRoZXIgb3Igbm90IGFueSBwb2RzIGFyZVxuICAgKiBydW5uaW5nIG9uIHRoZSBub2RlLlxuICAgKlxuICAgKiBAZGVmYXVsdCB0cnVlXG4gICAqL1xuICByZWFkb25seSBmb3JjZVVwZGF0ZT86IGJvb2xlYW47XG4gIC8qKlxuICAgKiBUaGUgaW5zdGFuY2UgdHlwZSB0byB1c2UgZm9yIHlvdXIgbm9kZSBncm91cC4gQ3VycmVudGx5LCB5b3UgY2FuIHNwZWNpZnkgYSBzaW5nbGUgaW5zdGFuY2UgdHlwZSBmb3IgYSBub2RlIGdyb3VwLlxuICAgKiBUaGUgZGVmYXVsdCB2YWx1ZSBmb3IgdGhpcyBwYXJhbWV0ZXIgaXMgYHQzLm1lZGl1bWAuIElmIHlvdSBjaG9vc2UgYSBHUFUgaW5zdGFuY2UgdHlwZSwgYmUgc3VyZSB0byBzcGVjaWZ5IHRoZVxuICAgKiBgQUwyX3g4Nl82NF9HUFVgLCBgQk9UVExFUk9DS0VUX0FSTV82NF9OVklESUFgLCBvciBgQk9UVExFUk9DS0VUX3g4Nl82NF9OVklESUFgIHdpdGggdGhlIGFtaVR5cGUgcGFyYW1ldGVyLlxuICAgKlxuICAgKiBAZGVmYXVsdCB0My5tZWRpdW1cbiAgICogQGRlcHJlY2F0ZWQgVXNlIGBpbnN0YW5jZVR5cGVzYCBpbnN0ZWFkLlxuICAgKi9cbiAgcmVhZG9ubHkgaW5zdGFuY2VUeXBlPzogSW5zdGFuY2VUeXBlO1xuICAvKipcbiAgICogVGhlIGluc3RhbmNlIHR5cGVzIHRvIHVzZSBmb3IgeW91ciBub2RlIGdyb3VwLlxuICAgKiBAZGVmYXVsdCB0My5tZWRpdW0gd2lsbCBiZSB1c2VkIGFjY29yZGluZyB0byB0aGUgY2xvdWRmb3JtYXRpb24gZG9jdW1lbnQuXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXJlc291cmNlLWVrcy1ub2RlZ3JvdXAuaHRtbCNjZm4tZWtzLW5vZGVncm91cC1pbnN0YW5jZXR5cGVzXG4gICAqL1xuICByZWFkb25seSBpbnN0YW5jZVR5cGVzPzogSW5zdGFuY2VUeXBlW107XG4gIC8qKlxuICAgKiBUaGUgS3ViZXJuZXRlcyBsYWJlbHMgdG8gYmUgYXBwbGllZCB0byB0aGUgbm9kZXMgaW4gdGhlIG5vZGUgZ3JvdXAgd2hlbiB0aGV5IGFyZSBjcmVhdGVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vbmVcbiAgICovXG4gIHJlYWRvbmx5IGxhYmVscz86IHsgW25hbWU6IHN0cmluZ106IHN0cmluZyB9O1xuICAvKipcbiAgICogVGhlIEt1YmVybmV0ZXMgdGFpbnRzIHRvIGJlIGFwcGxpZWQgdG8gdGhlIG5vZGVzIGluIHRoZSBub2RlIGdyb3VwIHdoZW4gdGhleSBhcmUgY3JlYXRlZC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBOb25lXG4gICAqL1xuICByZWFkb25seSB0YWludHM/OiBUYWludFNwZWNbXTtcbiAgLyoqXG4gICAqIFRoZSBJQU0gcm9sZSB0byBhc3NvY2lhdGUgd2l0aCB5b3VyIG5vZGUgZ3JvdXAuIFRoZSBBbWF6b24gRUtTIHdvcmtlciBub2RlIGt1YmVsZXQgZGFlbW9uXG4gICAqIG1ha2VzIGNhbGxzIHRvIEFXUyBBUElzIG9uIHlvdXIgYmVoYWxmLiBXb3JrZXIgbm9kZXMgcmVjZWl2ZSBwZXJtaXNzaW9ucyBmb3IgdGhlc2UgQVBJIGNhbGxzIHRocm91Z2hcbiAgICogYW4gSUFNIGluc3RhbmNlIHByb2ZpbGUgYW5kIGFzc29jaWF0ZWQgcG9saWNpZXMuIEJlZm9yZSB5b3UgY2FuIGxhdW5jaCB3b3JrZXIgbm9kZXMgYW5kIHJlZ2lzdGVyIHRoZW1cbiAgICogaW50byBhIGNsdXN0ZXIsIHlvdSBtdXN0IGNyZWF0ZSBhbiBJQU0gcm9sZSBmb3IgdGhvc2Ugd29ya2VyIG5vZGVzIHRvIHVzZSB3aGVuIHRoZXkgYXJlIGxhdW5jaGVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vbmUuIEF1dG8tZ2VuZXJhdGVkIGlmIG5vdCBzcGVjaWZpZWQuXG4gICAqL1xuICByZWFkb25seSBub2RlUm9sZT86IElSb2xlO1xuICAvKipcbiAgICogVGhlIEFNSSB2ZXJzaW9uIG9mIHRoZSBBbWF6b24gRUtTLW9wdGltaXplZCBBTUkgdG8gdXNlIHdpdGggeW91ciBub2RlIGdyb3VwIChmb3IgZXhhbXBsZSwgYDEuMTQuNy1ZWVlZTU1ERGApLlxu