@aws-cdk/aws-eks-v2-alpha
Version:
The CDK Construct Library for AWS::EKS
489 lines • 71.8 kB
JavaScript
"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