@aws-cdk/aws-ecs
Version:
The CDK Construct Library for AWS::ECS
536 lines • 94.7 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.isExternalCompatible = exports.isFargateCompatible = exports.isEc2Compatible = exports.Compatibility = exports.Scope = exports.PidMode = exports.IpcMode = exports.NetworkMode = exports.TaskDefinition = void 0;
const jsiiDeprecationWarnings = require("../../.warnings.jsii.js");
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const ec2 = require("@aws-cdk/aws-ec2");
const iam = require("@aws-cdk/aws-iam");
const core_1 = require("@aws-cdk/core");
const container_definition_1 = require("../container-definition");
const ecs_generated_1 = require("../ecs.generated");
const firelens_log_router_1 = require("../firelens-log-router");
const aws_log_driver_1 = require("../log-drivers/aws-log-driver");
const _imported_task_definition_1 = require("./_imported-task-definition");
class TaskDefinitionBase extends core_1.Resource {
/**
* Return true if the task definition can be run on an EC2 cluster
*/
get isEc2Compatible() {
return isEc2Compatible(this.compatibility);
}
/**
* Return true if the task definition can be run on a Fargate cluster
*/
get isFargateCompatible() {
return isFargateCompatible(this.compatibility);
}
/**
* Return true if the task definition can be run on a ECS anywhere cluster
*/
get isExternalCompatible() {
return isExternalCompatible(this.compatibility);
}
}
/**
* The base class for all task definitions.
*/
class TaskDefinition extends TaskDefinitionBase {
/**
* Constructs a new instance of the TaskDefinition class.
*/
constructor(scope, id, props) {
var _b, _c, _d, _e, _f, _g, _h;
super(scope, id);
/**
* The container definitions.
*/
this.containers = new Array();
/**
* All volumes
*/
this.volumes = [];
/**
* Placement constraints for task instances
*/
this.placementConstraints = new Array();
/**
* Inference accelerators for task instances
*/
this._inferenceAccelerators = [];
jsiiDeprecationWarnings._aws_cdk_aws_ecs_TaskDefinitionProps(props);
this.family = props.family || core_1.Names.uniqueId(this);
this.compatibility = props.compatibility;
if (props.volumes) {
props.volumes.forEach(v => this.addVolume(v));
}
this.networkMode = (_b = props.networkMode) !== null && _b !== void 0 ? _b : (this.isFargateCompatible ? NetworkMode.AWS_VPC : NetworkMode.BRIDGE);
if (this.isFargateCompatible && this.networkMode !== NetworkMode.AWS_VPC) {
throw new Error(`Fargate tasks can only have AwsVpc network mode, got: ${this.networkMode}`);
}
if (props.proxyConfiguration && this.networkMode !== NetworkMode.AWS_VPC) {
throw new Error(`ProxyConfiguration can only be used with AwsVpc network mode, got: ${this.networkMode}`);
}
if (props.placementConstraints && props.placementConstraints.length > 0 && this.isFargateCompatible) {
throw new Error('Cannot set placement constraints on tasks that run on Fargate');
}
if (this.isFargateCompatible && (!props.cpu || !props.memoryMiB)) {
throw new Error(`Fargate-compatible tasks require both CPU (${props.cpu}) and memory (${props.memoryMiB}) specifications`);
}
if (props.inferenceAccelerators && props.inferenceAccelerators.length > 0 && this.isFargateCompatible) {
throw new Error('Cannot use inference accelerators on tasks that run on Fargate');
}
if (this.isExternalCompatible && this.networkMode !== NetworkMode.BRIDGE) {
throw new Error(`External tasks can only have Bridge network mode, got: ${this.networkMode}`);
}
if (!this.isFargateCompatible && props.runtimePlatform) {
throw new Error('Cannot specify runtimePlatform in non-Fargate compatible tasks');
}
this._executionRole = props.executionRole;
this.taskRole = props.taskRole || new iam.Role(this, 'TaskRole', {
assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
});
if (props.inferenceAccelerators) {
props.inferenceAccelerators.forEach(ia => this.addInferenceAccelerator(ia));
}
this.ephemeralStorageGiB = props.ephemeralStorageGiB;
// validate the cpu and memory size for the Windows operation system family.
if ((_d = (_c = props.runtimePlatform) === null || _c === void 0 ? void 0 : _c.operatingSystemFamily) === null || _d === void 0 ? void 0 : _d._operatingSystemFamily.includes('WINDOWS')) {
// We know that props.cpu and props.memoryMiB are defined because an error would have been thrown previously if they were not.
// But, typescript is not able to figure this out, so using the `!` operator here to let the type-checker know they are defined.
this.checkFargateWindowsBasedTasksSize(props.cpu, props.memoryMiB, props.runtimePlatform);
}
this.runtimePlatform = props.runtimePlatform;
const taskDef = new ecs_generated_1.CfnTaskDefinition(this, 'Resource', {
containerDefinitions: core_1.Lazy.any({ produce: () => this.renderContainers() }, { omitEmptyArray: true }),
volumes: core_1.Lazy.any({ produce: () => this.renderVolumes() }, { omitEmptyArray: true }),
executionRoleArn: core_1.Lazy.string({ produce: () => this.executionRole && this.executionRole.roleArn }),
family: this.family,
taskRoleArn: this.taskRole.roleArn,
requiresCompatibilities: [
...(isEc2Compatible(props.compatibility) ? ['EC2'] : []),
...(isFargateCompatible(props.compatibility) ? ['FARGATE'] : []),
...(isExternalCompatible(props.compatibility) ? ['EXTERNAL'] : []),
],
networkMode: this.renderNetworkMode(this.networkMode),
placementConstraints: core_1.Lazy.any({
produce: () => !isFargateCompatible(this.compatibility) ? this.placementConstraints : undefined,
}, { omitEmptyArray: true }),
proxyConfiguration: props.proxyConfiguration ? props.proxyConfiguration.bind(this.stack, this) : undefined,
cpu: props.cpu,
memory: props.memoryMiB,
ipcMode: props.ipcMode,
pidMode: props.pidMode,
inferenceAccelerators: core_1.Lazy.any({
produce: () => !isFargateCompatible(this.compatibility) ? this.renderInferenceAccelerators() : undefined,
}, { omitEmptyArray: true }),
ephemeralStorage: this.ephemeralStorageGiB ? {
sizeInGiB: this.ephemeralStorageGiB,
} : undefined,
runtimePlatform: this.isFargateCompatible && this.runtimePlatform ? {
cpuArchitecture: (_f = (_e = this.runtimePlatform) === null || _e === void 0 ? void 0 : _e.cpuArchitecture) === null || _f === void 0 ? void 0 : _f._cpuArchitecture,
operatingSystemFamily: (_h = (_g = this.runtimePlatform) === null || _g === void 0 ? void 0 : _g.operatingSystemFamily) === null || _h === void 0 ? void 0 : _h._operatingSystemFamily,
} : undefined,
});
if (props.placementConstraints) {
props.placementConstraints.forEach(pc => this.addPlacementConstraint(pc));
}
this.taskDefinitionArn = taskDef.ref;
}
/**
* Imports a task definition from the specified task definition ARN.
*
* The task will have a compatibility of EC2+Fargate.
*/
static fromTaskDefinitionArn(scope, id, taskDefinitionArn) {
return new _imported_task_definition_1.ImportedTaskDefinition(scope, id, { taskDefinitionArn: taskDefinitionArn });
}
/**
* Create a task definition from a task definition reference
*/
static fromTaskDefinitionAttributes(scope, id, attrs) {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_TaskDefinitionAttributes(attrs);
return new _imported_task_definition_1.ImportedTaskDefinition(scope, id, {
taskDefinitionArn: attrs.taskDefinitionArn,
compatibility: attrs.compatibility,
networkMode: attrs.networkMode,
taskRole: attrs.taskRole,
});
}
get executionRole() {
return this._executionRole;
}
/**
* Public getter method to access list of inference accelerators attached to the instance.
*/
get inferenceAccelerators() {
return this._inferenceAccelerators;
}
renderVolumes() {
return this.volumes.map(renderVolume);
function renderVolume(spec) {
return {
host: spec.host,
name: spec.name,
dockerVolumeConfiguration: spec.dockerVolumeConfiguration && {
autoprovision: spec.dockerVolumeConfiguration.autoprovision,
driver: spec.dockerVolumeConfiguration.driver,
driverOpts: spec.dockerVolumeConfiguration.driverOpts,
labels: spec.dockerVolumeConfiguration.labels,
scope: spec.dockerVolumeConfiguration.scope,
},
efsVolumeConfiguration: spec.efsVolumeConfiguration && {
fileSystemId: spec.efsVolumeConfiguration.fileSystemId,
authorizationConfig: spec.efsVolumeConfiguration.authorizationConfig,
rootDirectory: spec.efsVolumeConfiguration.rootDirectory,
transitEncryption: spec.efsVolumeConfiguration.transitEncryption,
transitEncryptionPort: spec.efsVolumeConfiguration.transitEncryptionPort,
},
};
}
}
renderInferenceAccelerators() {
return this._inferenceAccelerators.map(renderInferenceAccelerator);
function renderInferenceAccelerator(inferenceAccelerator) {
return {
deviceName: inferenceAccelerator.deviceName,
deviceType: inferenceAccelerator.deviceType,
};
}
}
/**
* Validate the existence of the input target and set default values.
*
* @internal
*/
_validateTarget(options) {
const targetContainer = this.findContainer(options.containerName);
if (targetContainer === undefined) {
throw new Error(`No container named '${options.containerName}'. Did you call "addContainer()"?`);
}
const targetProtocol = options.protocol || container_definition_1.Protocol.TCP;
const targetContainerPort = options.containerPort || targetContainer.containerPort;
const portMapping = targetContainer.findPortMapping(targetContainerPort, targetProtocol);
if (portMapping === undefined) {
// eslint-disable-next-line max-len
throw new Error(`Container '${targetContainer}' has no mapping for port ${options.containerPort} and protocol ${targetProtocol}. Did you call "container.addPortMappings()"?`);
}
return {
containerName: options.containerName,
portMapping,
};
}
/**
* Returns the port range to be opened that match the provided container name and container port.
*
* @internal
*/
_portRangeFromPortMapping(portMapping) {
if (portMapping.hostPort !== undefined && portMapping.hostPort !== 0) {
return portMapping.protocol === container_definition_1.Protocol.UDP ? ec2.Port.udp(portMapping.hostPort) : ec2.Port.tcp(portMapping.hostPort);
}
if (this.networkMode === NetworkMode.BRIDGE || this.networkMode === NetworkMode.NAT) {
return EPHEMERAL_PORT_RANGE;
}
return portMapping.protocol === container_definition_1.Protocol.UDP ? ec2.Port.udp(portMapping.containerPort) : ec2.Port.tcp(portMapping.containerPort);
}
/**
* Adds a policy statement to the task IAM role.
*/
addToTaskRolePolicy(statement) {
this.taskRole.addToPrincipalPolicy(statement);
}
/**
* Adds a policy statement to the task execution IAM role.
*/
addToExecutionRolePolicy(statement) {
this.obtainExecutionRole().addToPrincipalPolicy(statement);
}
/**
* Adds a new container to the task definition.
*/
addContainer(id, props) {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_ContainerDefinitionOptions(props);
return new container_definition_1.ContainerDefinition(this, id, { taskDefinition: this, ...props });
}
/**
* Adds a firelens log router to the task definition.
*/
addFirelensLogRouter(id, props) {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_FirelensLogRouterDefinitionOptions(props);
// only one firelens log router is allowed in each task.
if (this.containers.find(x => x instanceof firelens_log_router_1.FirelensLogRouter)) {
throw new Error('Firelens log router is already added in this task.');
}
return new firelens_log_router_1.FirelensLogRouter(this, id, { taskDefinition: this, ...props });
}
/**
* Links a container to this task definition.
* @internal
*/
_linkContainer(container) {
this.containers.push(container);
if (this.defaultContainer === undefined && container.essential) {
this.defaultContainer = container;
}
if (container.referencesSecretJsonField) {
this._referencesSecretJsonField = true;
}
}
/**
* Adds a volume to the task definition.
*/
addVolume(volume) {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_Volume(volume);
this.volumes.push(volume);
}
/**
* Adds the specified placement constraint to the task definition.
*/
addPlacementConstraint(constraint) {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_PlacementConstraint(constraint);
if (isFargateCompatible(this.compatibility)) {
throw new Error('Cannot set placement constraints on tasks that run on Fargate');
}
this.placementConstraints.push(...constraint.toJson());
}
/**
* Adds the specified extension to the task definition.
*
* Extension can be used to apply a packaged modification to
* a task definition.
*/
addExtension(extension) {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_ITaskDefinitionExtension(extension);
extension.extend(this);
}
/**
* Adds an inference accelerator to the task definition.
*/
addInferenceAccelerator(inferenceAccelerator) {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_InferenceAccelerator(inferenceAccelerator);
if (isFargateCompatible(this.compatibility)) {
throw new Error('Cannot use inference accelerators on tasks that run on Fargate');
}
this._inferenceAccelerators.push(inferenceAccelerator);
}
/**
* Creates the task execution IAM role if it doesn't already exist.
*/
obtainExecutionRole() {
if (!this._executionRole) {
this._executionRole = new iam.Role(this, 'ExecutionRole', {
assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
// needed for cross-account access with TagParameterContainerImage
roleName: core_1.PhysicalName.GENERATE_IF_NEEDED,
});
}
return this._executionRole;
}
/**
* Whether this task definition has at least a container that references a
* specific JSON field of a secret stored in Secrets Manager.
*/
get referencesSecretJsonField() {
return this._referencesSecretJsonField;
}
/**
* Validates the task definition.
*/
validate() {
const ret = super.validate();
if (isEc2Compatible(this.compatibility)) {
// EC2 mode validations
// Container sizes
for (const container of this.containers) {
if (!container.memoryLimitSpecified) {
ret.push(`ECS Container ${container.containerName} must have at least one of 'memoryLimitMiB' or 'memoryReservationMiB' specified`);
}
}
}
return ret;
}
/**
* Returns the container that match the provided containerName.
*/
findContainer(containerName) {
return this.containers.find(c => c.containerName === containerName);
}
renderNetworkMode(networkMode) {
return (networkMode === NetworkMode.NAT) ? undefined : networkMode;
}
renderContainers() {
// add firelens log router container if any application container is using firelens log driver,
// also check if already created log router container
for (const container of this.containers) {
if (container.logDriverConfig && container.logDriverConfig.logDriver === 'awsfirelens'
&& !this.containers.find(x => x instanceof firelens_log_router_1.FirelensLogRouter)) {
this.addFirelensLogRouter('log-router', {
image: firelens_log_router_1.obtainDefaultFluentBitECRImage(this, container.logDriverConfig),
firelensConfig: {
type: firelens_log_router_1.FirelensLogRouterType.FLUENTBIT,
},
logging: new aws_log_driver_1.AwsLogDriver({ streamPrefix: 'firelens' }),
memoryReservationMiB: 50,
});
break;
}
}
return this.containers.map(x => x.renderContainerDefinition());
}
checkFargateWindowsBasedTasksSize(cpu, memory, runtimePlatform) {
if (Number(cpu) === 1024) {
if (Number(memory) < 1024 || Number(memory) > 8192 || (Number(memory) % 1024 !== 0)) {
throw new Error(`If provided cpu is ${cpu}, then memoryMiB must have a min of 1024 and a max of 8192, in 1024 increments. Provided memoryMiB was ${Number(memory)}.`);
}
}
else if (Number(cpu) === 2048) {
if (Number(memory) < 4096 || Number(memory) > 16384 || (Number(memory) % 1024 !== 0)) {
throw new Error(`If provided cpu is ${cpu}, then memoryMiB must have a min of 4096 and max of 16384, in 1024 increments. Provided memoryMiB ${Number(memory)}.`);
}
}
else if (Number(cpu) === 4096) {
if (Number(memory) < 8192 || Number(memory) > 30720 || (Number(memory) % 1024 !== 0)) {
throw new Error(`If provided cpu is ${cpu}, then memoryMiB must have a min of 8192 and a max of 30720, in 1024 increments.Provided memoryMiB was ${Number(memory)}.`);
}
}
else {
throw new Error(`If operatingSystemFamily is ${runtimePlatform.operatingSystemFamily._operatingSystemFamily}, then cpu must be in 1024 (1 vCPU), 2048 (2 vCPU), or 4096 (4 vCPU). Provided value was: ${cpu}`);
}
}
;
}
exports.TaskDefinition = TaskDefinition;
_a = JSII_RTTI_SYMBOL_1;
TaskDefinition[_a] = { fqn: "@aws-cdk/aws-ecs.TaskDefinition", version: "1.149.0" };
/**
* The port range to open up for dynamic port mapping
*/
const EPHEMERAL_PORT_RANGE = ec2.Port.tcpRange(32768, 65535);
/**
* The networking mode to use for the containers in the task.
*/
var NetworkMode;
(function (NetworkMode) {
/**
* The task's containers do not have external connectivity and port mappings can't be specified in the container definition.
*/
NetworkMode["NONE"] = "none";
/**
* The task utilizes Docker's built-in virtual network which runs inside each container instance.
*/
NetworkMode["BRIDGE"] = "bridge";
/**
* The task is allocated an elastic network interface.
*/
NetworkMode["AWS_VPC"] = "awsvpc";
/**
* The task bypasses Docker's built-in virtual network and maps container ports directly to the EC2 instance's network interface directly.
*
* In this mode, you can't run multiple instantiations of the same task on a
* single container instance when port mappings are used.
*/
NetworkMode["HOST"] = "host";
/**
* The task utilizes NAT network mode required by Windows containers.
*
* This is the only supported network mode for Windows containers. For more information, see
* [Task Definition Parameters](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html#network_mode).
*/
NetworkMode["NAT"] = "nat";
})(NetworkMode = exports.NetworkMode || (exports.NetworkMode = {}));
/**
* The IPC resource namespace to use for the containers in the task.
*/
var IpcMode;
(function (IpcMode) {
/**
* If none is specified, then IPC resources within the containers of a task are private and not
* shared with other containers in a task or on the container instance
*/
IpcMode["NONE"] = "none";
/**
* If host is specified, then all containers within the tasks that specified the host IPC mode on
* the same container instance share the same IPC resources with the host Amazon EC2 instance.
*/
IpcMode["HOST"] = "host";
/**
* If task is specified, all containers within the specified task share the same IPC resources.
*/
IpcMode["TASK"] = "task";
})(IpcMode = exports.IpcMode || (exports.IpcMode = {}));
/**
* The process namespace to use for the containers in the task.
*/
var PidMode;
(function (PidMode) {
/**
* If host is specified, then all containers within the tasks that specified the host PID mode
* on the same container instance share the same process namespace with the host Amazon EC2 instance.
*/
PidMode["HOST"] = "host";
/**
* If task is specified, all containers within the specified task share the same process namespace.
*/
PidMode["TASK"] = "task";
})(PidMode = exports.PidMode || (exports.PidMode = {}));
/**
* The scope for the Docker volume that determines its lifecycle.
* Docker volumes that are scoped to a task are automatically provisioned when the task starts and destroyed when the task stops.
* Docker volumes that are scoped as shared persist after the task stops.
*/
var Scope;
(function (Scope) {
/**
* Docker volumes that are scoped to a task are automatically provisioned when the task starts and destroyed when the task stops.
*/
Scope["TASK"] = "task";
/**
* Docker volumes that are scoped as shared persist after the task stops.
*/
Scope["SHARED"] = "shared";
})(Scope = exports.Scope || (exports.Scope = {}));
/**
* The task launch type compatibility requirement.
*/
var Compatibility;
(function (Compatibility) {
/**
* The task should specify the EC2 launch type.
*/
Compatibility[Compatibility["EC2"] = 0] = "EC2";
/**
* The task should specify the Fargate launch type.
*/
Compatibility[Compatibility["FARGATE"] = 1] = "FARGATE";
/**
* The task can specify either the EC2 or Fargate launch types.
*/
Compatibility[Compatibility["EC2_AND_FARGATE"] = 2] = "EC2_AND_FARGATE";
/**
* The task should specify the External launch type.
*/
Compatibility[Compatibility["EXTERNAL"] = 3] = "EXTERNAL";
})(Compatibility = exports.Compatibility || (exports.Compatibility = {}));
/**
* Return true if the given task definition can be run on an EC2 cluster
*/
function isEc2Compatible(compatibility) {
return [Compatibility.EC2, Compatibility.EC2_AND_FARGATE].includes(compatibility);
}
exports.isEc2Compatible = isEc2Compatible;
/**
* Return true if the given task definition can be run on a Fargate cluster
*/
function isFargateCompatible(compatibility) {
return [Compatibility.FARGATE, Compatibility.EC2_AND_FARGATE].includes(compatibility);
}
exports.isFargateCompatible = isFargateCompatible;
/**
* Return true if the given task definition can be run on a ECS Anywhere cluster
*/
function isExternalCompatible(compatibility) {
return [Compatibility.EXTERNAL].includes(compatibility);
}
exports.isExternalCompatible = isExternalCompatible;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFzay1kZWZpbml0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsidGFzay1kZWZpbml0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLHdDQUF3QztBQUN4Qyx3Q0FBd0M7QUFDeEMsd0NBQStFO0FBRS9FLGtFQUFpSDtBQUNqSCxvREFBcUQ7QUFDckQsZ0VBQXNKO0FBQ3RKLGtFQUE2RDtBQUk3RCwyRUFBcUU7QUF1UHJFLE1BQWUsa0JBQW1CLFNBQVEsZUFBUTtJQVFoRDs7T0FFRztJQUNILElBQVcsZUFBZTtRQUN4QixPQUFPLGVBQWUsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7S0FDNUM7SUFFRDs7T0FFRztJQUNILElBQVcsbUJBQW1CO1FBQzVCLE9BQU8sbUJBQW1CLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0tBQ2hEO0lBRUQ7O09BRUc7SUFDSCxJQUFXLG9CQUFvQjtRQUM3QixPQUFPLG9CQUFvQixDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztLQUNqRDtDQUNGO0FBRUQ7O0dBRUc7QUFDSCxNQUFhLGNBQWUsU0FBUSxrQkFBa0I7SUE0RnBEOztPQUVHO0lBQ0gsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUEwQjs7UUFDbEUsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQTlCbkI7O1dBRUc7UUFDZ0IsZUFBVSxHQUFHLElBQUksS0FBSyxFQUF1QixDQUFDO1FBRWpFOztXQUVHO1FBQ2MsWUFBTyxHQUFhLEVBQUUsQ0FBQztRQUV4Qzs7V0FFRztRQUNjLHlCQUFvQixHQUFHLElBQUksS0FBSyxFQUErRCxDQUFDO1FBRWpIOztXQUVHO1FBQ2MsMkJBQXNCLEdBQTJCLEVBQUUsQ0FBQzs7UUFjbkUsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTSxJQUFJLFlBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDbkQsSUFBSSxD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QUVHO0lBQ0gseURBQVEsQ0FBQTtBQUNWLENBQUMsRUFwQlcsYUFBYSxHQUFiLHFCQUFhLEtBQWIscUJBQWEsUUFvQnhCO0FBb0JEOztHQUVHO0FBQ0gsU0FBZ0IsZUFBZSxDQUFDLGFBQTRCO0lBQzFELE9BQU8sQ0FBQyxhQUFhLENBQUMsR0FBRyxFQUFFLGFBQWEsQ0FBQyxlQUFlLENBQUMsQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLENBQUM7QUFDcEYsQ0FBQztBQUZELDBDQUVDO0FBRUQ7O0dBRUc7QUFDSCxTQUFnQixtQkFBbUIsQ0FBQyxhQUE0QjtJQUM5RCxPQUFPLENBQUMsYUFBYSxDQUFDLE9BQU8sRUFBRSxhQUFhLENBQUMsZUFBZSxDQUFDLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxDQUFDO0FBQ3hGLENBQUM7QUFGRCxrREFFQztBQUVEOztHQUVHO0FBQ0gsU0FBZ0Isb0JBQW9CLENBQUMsYUFBNEI7SUFDL0QsT0FBTyxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsYUFBYSxDQUFDLENBQUM7QUFDMUQsQ0FBQztBQUZELG9EQUVDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgZWMyIGZyb20gJ0Bhd3MtY2RrL2F3cy1lYzInO1xuaW1wb3J0ICogYXMgaWFtIGZyb20gJ0Bhd3MtY2RrL2F3cy1pYW0nO1xuaW1wb3J0IHsgSVJlc291cmNlLCBMYXp5LCBOYW1lcywgUGh5c2ljYWxOYW1lLCBSZXNvdXJjZSB9IGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1xuaW1wb3J0IHsgQ29uc3RydWN0IH0gZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBDb250YWluZXJEZWZpbml0aW9uLCBDb250YWluZXJEZWZpbml0aW9uT3B0aW9ucywgUG9ydE1hcHBpbmcsIFByb3RvY29sIH0gZnJvbSAnLi4vY29udGFpbmVyLWRlZmluaXRpb24nO1xuaW1wb3J0IHsgQ2ZuVGFza0RlZmluaXRpb24gfSBmcm9tICcuLi9lY3MuZ2VuZXJhdGVkJztcbmltcG9ydCB7IEZpcmVsZW5zTG9nUm91dGVyLCBGaXJlbGVuc0xvZ1JvdXRlckRlZmluaXRpb25PcHRpb25zLCBGaXJlbGVuc0xvZ1JvdXRlclR5cGUsIG9idGFpbkRlZmF1bHRGbHVlbnRCaXRFQ1JJbWFnZSB9IGZyb20gJy4uL2ZpcmVsZW5zLWxvZy1yb3V0ZXInO1xuaW1wb3J0IHsgQXdzTG9nRHJpdmVyIH0gZnJvbSAnLi4vbG9nLWRyaXZlcnMvYXdzLWxvZy1kcml2ZXInO1xuaW1wb3J0IHsgUGxhY2VtZW50Q29uc3RyYWludCB9IGZyb20gJy4uL3BsYWNlbWVudCc7XG5pbXBvcnQgeyBQcm94eUNvbmZpZ3VyYXRpb24gfSBmcm9tICcuLi9wcm94eS1jb25maWd1cmF0aW9uL3Byb3h5LWNvbmZpZ3VyYXRpb24nO1xuaW1wb3J0IHsgUnVudGltZVBsYXRmb3JtIH0gZnJvbSAnLi4vcnVudGltZS1wbGF0Zm9ybSc7XG5pbXBvcnQgeyBJbXBvcnRlZFRhc2tEZWZpbml0aW9uIH0gZnJvbSAnLi9faW1wb3J0ZWQtdGFzay1kZWZpbml0aW9uJztcblxuLyoqXG4gKiBUaGUgaW50ZXJmYWNlIGZvciBhbGwgdGFzayBkZWZpbml0aW9ucy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJVGFza0RlZmluaXRpb24gZXh0ZW5kcyBJUmVzb3VyY2Uge1xuICAvKipcbiAgICogQVJOIG9mIHRoaXMgdGFzayBkZWZpbml0aW9uXG4gICAqIEBhdHRyaWJ1dGVcbiAgICovXG4gIHJlYWRvbmx5IHRhc2tEZWZpbml0aW9uQXJuOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEV4ZWN1dGlvbiByb2xlIGZvciB0aGlzIHRhc2sgZGVmaW5pdGlvblxuICAgKi9cbiAgcmVhZG9ubHkgZXhlY3V0aW9uUm9sZT86IGlhbS5JUm9sZTtcblxuICAvKipcbiAgICogV2hhdCBsYXVuY2ggdHlwZXMgdGhpcyB0YXNrIGRlZmluaXRpb24gc2hvdWxkIGJlIGNvbXBhdGlibGUgd2l0aC5cbiAgICovXG4gIHJlYWRvbmx5IGNvbXBhdGliaWxpdHk6IENvbXBhdGliaWxpdHk7XG5cbiAgLyoqXG4gICAqIFJldHVybiB0cnVlIGlmIHRoZSB0YXNrIGRlZmluaXRpb24gY2FuIGJlIHJ1biBvbiBhbiBFQzIgY2x1c3RlclxuICAgKi9cbiAgcmVhZG9ubHkgaXNFYzJDb21wYXRpYmxlOiBib29sZWFuO1xuXG4gIC8qKlxuICAgKiBSZXR1cm4gdHJ1ZSBpZiB0aGUgdGFzayBkZWZpbml0aW9uIGNhbiBiZSBydW4gb24gYSBGYXJnYXRlIGNsdXN0ZXJcbiAgICovXG4gIHJlYWRvbmx5IGlzRmFyZ2F0ZUNvbXBhdGlibGU6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFJldHVybiB0cnVlIGlmIHRoZSB0YXNrIGRlZmluaXRpb24gY2FuIGJlIHJ1biBvbiBhIEVDUyBBbnl3aGVyZSBjbHVzdGVyXG4gICAqL1xuICByZWFkb25seSBpc0V4dGVybmFsQ29tcGF0aWJsZTogYm9vbGVhbjtcblxuXG4gIC8qKlxuICAgKiBUaGUgbmV0d29ya2luZyBtb2RlIHRvIHVzZSBmb3IgdGhlIGNvbnRhaW5lcnMgaW4gdGhlIHRhc2suXG4gICAqL1xuICByZWFkb25seSBuZXR3b3JrTW9kZTogTmV0d29ya01vZGU7XG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBJQU0gcm9sZSB0aGF0IGdyYW50cyBjb250YWluZXJzIGluIHRoZSB0YXNrIHBlcm1pc3Npb24gdG8gY2FsbCBBV1MgQVBJcyBvbiB5b3VyIGJlaGFsZi5cbiAgICovXG4gIHJlYWRvbmx5IHRhc2tSb2xlOiBpYW0uSVJvbGU7XG59XG5cbi8qKlxuICogVGhlIGNvbW1vbiBwcm9wZXJ0aWVzIGZvciBhbGwgdGFzayBkZWZpbml0aW9ucy4gRm9yIG1vcmUgaW5mb3JtYXRpb24sIHNlZVxuICogW1Rhc2sgRGVmaW5pdGlvbiBQYXJhbWV0ZXJzXShodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uRUNTL2xhdGVzdC9kZXZlbG9wZXJndWlkZS90YXNrX2RlZmluaXRpb25fcGFyYW1ldGVycy5odG1sKS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDb21tb25UYXNrRGVmaW5pdGlvblByb3BzIHtcbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIGEgZmFtaWx5IHRoYXQgdGhpcyB0YXNrIGRlZmluaXRpb24gaXMgcmVnaXN0ZXJlZCB0by4gQSBmYW1pbHkgZ3JvdXBzIG11bHRpcGxlIHZlcnNpb25zIG9mIGEgdGFzayBkZWZpbml0aW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEF1dG9tYXRpY2FsbHkgZ2VuZXJhdGVkIG5hbWUuXG4gICAqL1xuICByZWFkb25seSBmYW1pbHk/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBJQU0gdGFzayBleGVjdXRpb24gcm9sZSB0aGF0IGdyYW50cyB0aGUgRUNTIGFnZW50IHBlcm1pc3Npb24gdG8gY2FsbCBBV1MgQVBJcyBvbiB5b3VyIGJlaGFsZi5cbiAgICpcbiAgICogVGhlIHJvbGUgd2lsbCBiZSB1c2VkIHRvIHJldHJpZXZlIGNvbnRhaW5lciBpbWFnZXMgZnJvbSBFQ1IgYW5kIGNyZWF0ZSBDbG91ZFdhdGNoIGxvZyBncm91cHMuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gQW4gZXhlY3V0aW9uIHJvbGUgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IGNyZWF0ZWQgaWYgeW91IHVzZSBFQ1IgaW1hZ2VzIGluIHlvdXIgdGFzayBkZWZpbml0aW9uLlxuICAgKi9cbiAgcmVhZG9ubHkgZXhlY3V0aW9uUm9sZT86IGlhbS5JUm9sZTtcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhlIElBTSByb2xlIHRoYXQgZ3JhbnRzIGNvbnRhaW5lcnMgaW4gdGhlIHRhc2sgcGVybWlzc2lvbiB0byBjYWxsIEFXUyBBUElzIG9uIHlvdXIgYmVoYWxmLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEEgdGFzayByb2xlIGlzIGF1dG9tYXRpY2FsbHkgY3JlYXRlZCBmb3IgeW91LlxuICAgKi9cbiAgcmVhZG9ubHkgdGFza1JvbGU/OiBpYW0uSVJvbGU7XG5cbiAgLyoqXG4gICAqIFRoZSBjb25maWd1cmF0aW9uIGRldGFpbHMgZm9yIHRoZSBBcHAgTWVzaCBwcm94eS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBwcm94eSBjb25maWd1cmF0aW9uLlxuICAgKi9cbiAgcmVhZG9ubHkgcHJveHlDb25maWd1cmF0aW9uPzogUHJveHlDb25maWd1cmF0aW9uO1xuXG4gIC8qKlxuICAgKiBUaGUgbGlzdCBvZiB2b2x1bWUgZGVmaW5pdGlvbnMgZm9yIHRoZSB0YXNrLiBGb3IgbW9yZSBpbmZvcm1hdGlvbiwgc2VlXG4gICAqIFtUYXNrIERlZmluaXRpb24gUGFyYW1ldGVyIFZvbHVtZXNdKGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BbWF6b25FQ1MvbGF0ZXN0L2RldmVsb3Blcmd1aWRlLy90YXNrX2RlZmluaXRpb25fcGFyYW1ldGVycy5odG1sI3ZvbHVtZXMpLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIHZvbHVtZXMgYXJlIHBhc3NlZCB0byB0aGUgRG9ja2VyIGRhZW1vbiBvbiBhIGNvbnRhaW5lciBpbnN0YW5jZS5cbiAgICovXG4gIHJlYWRvbmx5IHZvbHVtZXM/OiBWb2x1bWVbXTtcbn1cblxuLyoqXG4gKiBUaGUgcHJvcGVydGllcyBmb3IgdGFzayBkZWZpbml0aW9ucy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBUYXNrRGVmaW5pdGlvblByb3BzIGV4dGVuZHMgQ29tbW9uVGFza0RlZmluaXRpb25Qcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgbmV0d29ya2luZyBtb2RlIHRvIHVzZSBmb3IgdGhlIGNvbnRhaW5lcnMgaW4gdGhlIHRhc2suXG4gICAqXG4gICAqIE9uIEZhcmdhdGUsIHRoZSBvbmx5IHN1cHBvcnRlZCBuZXR3b3JraW5nIG1vZGUgaXMgQXdzVnBjLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5ldHdvcmtNb2RlLkJyaWRnZSBmb3IgRUMyICYgRXh0ZXJuYWwgdGFza3MsIEF3c1ZwYyBmb3IgRmFyZ2F0ZSB0YXNrcy5cbiAgICovXG4gIHJlYWRvbmx5IG5ldHdvcmtNb2RlPzogTmV0d29ya01vZGU7XG5cbiAgLyoqXG4gICAqIFRoZSBwbGFjZW1lbnQgY29uc3RyYWludHMgdG8gdXNlIGZvciB0YXNrcyBpbiB0aGUgc2VydmljZS5cbiAgICpcbiAgICogWW91IGNhbiBzcGVjaWZ5IGEgbWF4aW11bSBvZiAxMCBjb25zdHJhaW50cyBwZXIgdGFzayAodGhpcyBsaW1pdCBpbmNsdWRlc1xuICAgKiBjb25zdHJhaW50cyBpbiB0aGUgdGFzayBkZWZpbml0aW9uIGFuZCB0aG9zZSBzcGVjaWZpZWQgYXQgcnVuIHRpbWUpLlxuICAgKlxuICAgKiBOb3Qgc3VwcG9ydGVkIGluIEZhcmdhdGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gcGxhY2VtZW50IGNvbnN0cmFpbnRzLlxuICAgKi9cbiAgcmVhZG9ubHkgcGxhY2VtZW50Q29uc3RyYWludHM/OiBQbGFjZW1lbnRDb25zdHJhaW50W107XG5cbiAgLyoqXG4gICAqIFRoZSB0YXNrIGxhdW5jaCB0eXBlIGNvbXBhdGlibGl0eSByZXF1aXJlbWVudC5cbiAgICovXG4gIHJlYWRvbmx5IGNvbXBhdGliaWxpdHk6IENvbXBhdGliaWxpdHk7XG5cbiAgLyoqXG4gICAqIFRoZSBudW1iZXIgb2YgY3B1IHVuaXRzIHVzZWQgYnkgdGhlIHRhc2suXG4gICAqXG4gICAqIElmIHlvdSBhcmUgdXNpbmcgdGhlIEVDMiBsYXVuY2ggdHlwZSwgdGhpcyBmaWVsZCBpcyBvcHRpb25hbCBhbmQgYW55IHZhbHVlIGNhbiBiZSB1c2VkLlxuICAgKiBJZiB5b3UgYXJlIHVzaW5nIHRoZSBGYXJnYXRlIGxhdW5jaCB0eXBlLCB0aGlzIGZpZWxkIGlzIHJlcXVpcmVkIGFuZCB5b3UgbXVzdCB1c2Ugb25lIG9mIHRoZSBmb2xsb3dpbmcgdmFsdWVzLFxuICAgKiB3aGljaCBkZXRlcm1pbmVzIHlvdXIgcmFuZ2Ugb2YgdmFsaWQgdmFsdWVzIGZvciB0aGUgbWVtb3J5IHBhcmFtZXRlcjpcbiAgICpcbiAgICogMjU2ICguMjUgdkNQVSkgLSBBdmFpbGFibGUgbWVtb3J5IHZhbHVlczogNTEyICgwLjUgR0IpLCAxMDI0ICgxIEdCKSwgMjA0OCAoMiBHQilcbiAgICpcbiAgICogNTEyICguNSB2Q1BVKSAtIEF2YWlsYWJsZSBtZW1vcnkgdmFsdWVzOiAxMDI0ICgxIEdCKSwgMjA0OCAoMiBHQiksIDMwNzIgKDMgR0IpLCA0MDk2ICg0IEdCKVxuICAgKlxuICAgKiAxMDI0ICgxIHZDUFUpIC0gQXZhaWxhYmxlIG1lbW9yeSB2YWx1ZXM6IDIwNDggKDIgR0IpLCAzMDcyICgzIEdCKSwgNDA5NiAoNCBHQiksIDUxMjAgKDUgR0IpLCA2MTQ0ICg2IEdCKSwgNzE2OCAoNyBHQiksIDgxOTIgKDggR0IpXG4gICAqXG4gICAqIDIwNDggKDIgdkNQVSkgLSBBdmFpbGFibGUgbWVtb3J5IHZhbHVlczogQmV0d2VlbiA0MDk2ICg0IEdCKSBhbmQgMTYzODQgKDE2IEdCKSBpbiBpbmNyZW1lbnRzIG9mIDEwMjQgKDEgR0IpXG4gICAqXG4gICAqIDQwOTYgKDQgdkNQVSkgLSBBdmFpbGFibGUgbWVtb3J5IHZhbHVlczogQmV0d2VlbiA4MTkyICg4IEdCKSBhbmQgMzA3MjAgKDMwIEdCKSBpbiBpbmNyZW1lbnRzIG9mIDEwMjQgKDEgR0IpXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gQ1BVIHVuaXRzIGFyZSBub3Qgc3BlY2lmaWVkLlxuICAgKi9cbiAgcmVhZG9ubHkgY3B1Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgYW1vdW50IChpbiBNaUIpIG9mIG1lbW9yeSB1c2VkIGJ5IHRoZSB0YXNrLlxuICAgKlxuICAgKiBJZiB1c2luZyB0aGUgRUMyIGxhdW5jaCB0eXBlLCB0aGlzIGZpZWxkIGlzIG9wdGlvbmFsIGFuZCBhbnkgdmFsdWUgY2FuIGJlIHVzZWQuXG4gICAqIElmIHVzaW5nIHRoZSBGYXJnYXRlIGxhdW5jaCB0eXBlLCB0aGlzIGZpZWxkIGlzIHJlcXVpcmVkIGFuZCB5b3UgbXVzdCB1c2Ugb25lIG9mIHRoZSBmb2xsb3dpbmcgdmFsdWVzLFxuICAgKiB3aGljaCBkZXRlcm1pbmVzIHlvdXIgcmFuZ2Ugb2YgdmFsaWQgdmFsdWVzIGZvciB0aGUgY3B1IHBhcmFtZXRlcjpcbiAgICpcbiAgICogNTEyICgwLjUgR0IpLCAxMDI0ICgxIEdCKSwgMjA0OCAoMiBHQikgLSBBdmFpbGFibGUgY3B1IHZhbHVlczogMjU2ICguMjUgdkNQVSlcbiAgICpcbiAgICogMTAyNCAoMSBHQiksIDIwNDggKDIgR0IpLCAzMDcyICgzIEdCKSwgNDA5NiAoNCBHQikgLSBBdmFpbGFibGUgY3B1IHZhbHVlczogNTEyICguNSB2Q1BVKVxuICAgKlxuICAgKiAyMDQ4ICgyIEdCKSwgMzA3MiAoMyBHQiksIDQwOTYgKD