@aws-cdk/aws-ecs
Version:
The CDK Construct Library for AWS::ECS
606 lines • 90.5 kB
JavaScript
"use strict";
var _a, _b;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Protocol = exports.ContainerDependencyCondition = exports.UlimitName = exports.ContainerDefinition = exports.Secret = void 0;
const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const cdk = require("@aws-cdk/core");
const task_definition_1 = require("./base/task-definition");
// keep this import separate from other imports to reduce chance for merge conflicts with v2-main
// eslint-disable-next-line no-duplicate-imports, import/order
const core_1 = require("@aws-cdk/core");
/**
* A secret environment variable.
*/
class Secret {
/**
* Creates an environment variable value from a parameter stored in AWS
* Systems Manager Parameter Store.
*/
static fromSsmParameter(parameter) {
return {
arn: parameter.parameterArn,
grantRead: grantee => parameter.grantRead(grantee),
};
}
/**
* Creates a environment variable value from a secret stored in AWS Secrets
* Manager.
*
* @param secret the secret stored in AWS Secrets Manager
* @param field the name of the field with the value that you want to set as
* the environment variable value. Only values in JSON format are supported.
* If you do not specify a JSON field, then the full content of the secret is
* used.
*/
static fromSecretsManager(secret, field) {
return {
arn: field ? `${secret.secretArn}:${field}::` : secret.secretArn,
hasField: !!field,
grantRead: grantee => secret.grantRead(grantee),
};
}
/**
* Creates a environment variable value from a secret stored in AWS Secrets
* Manager.
*
* @param secret the secret stored in AWS Secrets Manager
* @param versionInfo the version information to reference the secret
* @param field the name of the field with the value that you want to set as
* the environment variable value. Only values in JSON format are supported.
* If you do not specify a JSON field, then the full content of the secret is
* used.
*/
static fromSecretsManagerVersion(secret, versionInfo, field) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_SecretVersionInfo(versionInfo);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.fromSecretsManagerVersion);
}
throw error;
}
return {
arn: `${secret.secretArn}:${field ?? ''}:${versionInfo.versionStage ?? ''}:${versionInfo.versionId ?? ''}`,
hasField: !!field,
grantRead: grantee => secret.grantRead(grantee),
};
}
}
exports.Secret = Secret;
_a = JSII_RTTI_SYMBOL_1;
Secret[_a] = { fqn: "@aws-cdk/aws-ecs.Secret", version: "1.204.0" };
/**
* A container definition is used in a task definition to describe the containers that are launched as part of a task.
*/
class ContainerDefinition extends core_1.Construct {
/**
* Constructs a new instance of the ContainerDefinition class.
*/
constructor(scope, id, props) {
super(scope, id);
this.props = props;
/**
* The mount points for data volumes in your container.
*/
this.mountPoints = new Array();
/**
* The list of port mappings for the container. Port mappings allow containers to access ports
* on the host container instance to send or receive traffic.
*/
this.portMappings = new Array();
/**
* The data volumes to mount from another container in the same task definition.
*/
this.volumesFrom = new Array();
/**
* An array of ulimits to set in the container.
*/
this.ulimits = new Array();
/**
* An array dependencies defined for container startup and shutdown.
*/
this.containerDependencies = new Array();
/**
* The inference accelerators referenced by this container.
*/
this.inferenceAcceleratorResources = [];
/**
* The configured container links
*/
this.links = new Array();
try {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_ContainerDefinitionProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, ContainerDefinition);
}
throw error;
}
if (props.memoryLimitMiB !== undefined && props.memoryReservationMiB !== undefined) {
if (props.memoryLimitMiB < props.memoryReservationMiB) {
throw new Error('MemoryLimitMiB should not be less than MemoryReservationMiB.');
}
}
this.essential = props.essential ?? true;
this.taskDefinition = props.taskDefinition;
this.memoryLimitSpecified = props.memoryLimitMiB !== undefined || props.memoryReservationMiB !== undefined;
this.linuxParameters = props.linuxParameters;
this.containerName = props.containerName ?? this.node.id;
this.imageConfig = props.image.bind(this, this);
this.imageName = this.imageConfig.imageName;
if (props.logging) {
this.logDriverConfig = props.logging.bind(this, this);
}
if (props.secrets) {
this.secrets = [];
for (const [name, secret] of Object.entries(props.secrets)) {
if (secret.hasField) {
this.referencesSecretJsonField = true;
}
secret.grantRead(this.taskDefinition.obtainExecutionRole());
this.secrets.push({
name,
valueFrom: secret.arn,
});
}
}
if (props.environment) {
this.environment = { ...props.environment };
}
else {
this.environment = {};
}
if (props.environmentFiles) {
this.environmentFiles = [];
for (const environmentFile of props.environmentFiles) {
this.environmentFiles.push(environmentFile.bind(this));
}
}
props.taskDefinition._linkContainer(this);
if (props.portMappings) {
this.addPortMappings(...props.portMappings);
}
if (props.inferenceAcceleratorResources) {
this.addInferenceAcceleratorResource(...props.inferenceAcceleratorResources);
}
}
/**
* This method adds a link which allows containers to communicate with each other without the need for port mappings.
*
* This parameter is only supported if the task definition is using the bridge network mode.
* Warning: The --link flag is a legacy feature of Docker. It may eventually be removed.
*/
addLink(container, alias) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_ContainerDefinition(container);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addLink);
}
throw error;
}
if (this.taskDefinition.networkMode !== task_definition_1.NetworkMode.BRIDGE) {
throw new Error('You must use network mode Bridge to add container links.');
}
if (alias !== undefined) {
this.links.push(`${container.containerName}:${alias}`);
}
else {
this.links.push(`${container.containerName}`);
}
}
/**
* This method adds one or more mount points for data volumes to the container.
*/
addMountPoints(...mountPoints) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_MountPoint(mountPoints);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addMountPoints);
}
throw error;
}
this.mountPoints.push(...mountPoints);
}
/**
* This method mounts temporary disk space to the container.
*
* This adds the correct container mountPoint and task definition volume.
*/
addScratch(scratch) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_ScratchSpace(scratch);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addScratch);
}
throw error;
}
const mountPoint = {
containerPath: scratch.containerPath,
readOnly: scratch.readOnly,
sourceVolume: scratch.name,
};
const volume = {
host: {
sourcePath: scratch.sourcePath,
},
name: scratch.name,
};
this.taskDefinition.addVolume(volume);
this.addMountPoints(mountPoint);
}
/**
* This method adds one or more port mappings to the container.
*/
addPortMappings(...portMappings) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_PortMapping(portMappings);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addPortMappings);
}
throw error;
}
this.portMappings.push(...portMappings.map(pm => {
if (this.taskDefinition.networkMode === task_definition_1.NetworkMode.AWS_VPC || this.taskDefinition.networkMode === task_definition_1.NetworkMode.HOST) {
if (pm.containerPort !== pm.hostPort && pm.hostPort !== undefined) {
throw new Error(`Host port (${pm.hostPort}) must be left out or equal to container port ${pm.containerPort} for network mode ${this.taskDefinition.networkMode}`);
}
}
if (this.taskDefinition.networkMode === task_definition_1.NetworkMode.BRIDGE) {
if (pm.hostPort === undefined) {
pm = {
...pm,
hostPort: 0,
};
}
}
return pm;
}));
}
/**
* This method adds an environment variable to the container.
*/
addEnvironment(name, value) {
this.environment[name] = value;
}
/**
* This method adds one or more resources to the container.
*/
addInferenceAcceleratorResource(...inferenceAcceleratorResources) {
this.inferenceAcceleratorResources.push(...inferenceAcceleratorResources.map(resource => {
for (const inferenceAccelerator of this.taskDefinition.inferenceAccelerators) {
if (resource === inferenceAccelerator.deviceName) {
return resource;
}
}
throw new Error(`Resource value ${resource} in container definition doesn't match any inference accelerator device name in the task definition.`);
}));
}
/**
* This method adds one or more ulimits to the container.
*/
addUlimits(...ulimits) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_Ulimit(ulimits);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addUlimits);
}
throw error;
}
this.ulimits.push(...ulimits);
}
/**
* This method adds one or more container dependencies to the container.
*/
addContainerDependencies(...containerDependencies) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_ContainerDependency(containerDependencies);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addContainerDependencies);
}
throw error;
}
this.containerDependencies.push(...containerDependencies);
}
/**
* This method adds one or more volumes to the container.
*/
addVolumesFrom(...volumesFrom) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_VolumeFrom(volumesFrom);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.addVolumesFrom);
}
throw error;
}
this.volumesFrom.push(...volumesFrom);
}
/**
* This method adds the specified statement to the IAM task execution policy in the task definition.
*/
addToExecutionPolicy(statement) {
this.taskDefinition.addToExecutionRolePolicy(statement);
}
/**
* Returns the host port for the requested container port if it exists
*/
findPortMapping(containerPort, protocol) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_Protocol(protocol);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.findPortMapping);
}
throw error;
}
for (const portMapping of this.portMappings) {
const p = portMapping.protocol || Protocol.TCP;
const c = portMapping.containerPort;
if (c === containerPort && p === protocol) {
return portMapping;
}
}
return undefined;
}
/**
* The inbound rules associated with the security group the task or service will use.
*
* This property is only used for tasks that use the awsvpc network mode.
*/
get ingressPort() {
if (this.portMappings.length === 0) {
throw new Error(`Container ${this.containerName} hasn't defined any ports. Call addPortMappings().`);
}
const defaultPortMapping = this.portMappings[0];
if (defaultPortMapping.hostPort !== undefined && defaultPortMapping.hostPort !== 0) {
return defaultPortMapping.hostPort;
}
if (this.taskDefinition.networkMode === task_definition_1.NetworkMode.BRIDGE) {
return 0;
}
return defaultPortMapping.containerPort;
}
/**
* The port the container will listen on.
*/
get containerPort() {
if (this.portMappings.length === 0) {
throw new Error(`Container ${this.containerName} hasn't defined any ports. Call addPortMappings().`);
}
const defaultPortMapping = this.portMappings[0];
return defaultPortMapping.containerPort;
}
/**
* Render this container definition to a CloudFormation object
*
* @param _taskDefinition [disable-awslint:ref-via-interface] (unused but kept to avoid breaking change)
*/
renderContainerDefinition(_taskDefinition) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_ecs_TaskDefinition(_taskDefinition);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.renderContainerDefinition);
}
throw error;
}
return {
command: this.props.command,
cpu: this.props.cpu,
disableNetworking: this.props.disableNetworking,
dependsOn: cdk.Lazy.any({ produce: () => this.containerDependencies.map(renderContainerDependency) }, { omitEmptyArray: true }),
dnsSearchDomains: this.props.dnsSearchDomains,
dnsServers: this.props.dnsServers,
dockerLabels: this.props.dockerLabels,
dockerSecurityOptions: this.props.dockerSecurityOptions,
entryPoint: this.props.entryPoint,
essential: this.essential,
hostname: this.props.hostname,
image: this.imageConfig.imageName,
memory: this.props.memoryLimitMiB,
memoryReservation: this.props.memoryReservationMiB,
mountPoints: cdk.Lazy.any({ produce: () => this.mountPoints.map(renderMountPoint) }, { omitEmptyArray: true }),
name: this.containerName,
portMappings: cdk.Lazy.any({ produce: () => this.portMappings.map(renderPortMapping) }, { omitEmptyArray: true }),
privileged: this.props.privileged,
readonlyRootFilesystem: this.props.readonlyRootFilesystem,
repositoryCredentials: this.imageConfig.repositoryCredentials,
startTimeout: this.props.startTimeout && this.props.startTimeout.toSeconds(),
stopTimeout: this.props.stopTimeout && this.props.stopTimeout.toSeconds(),
ulimits: cdk.Lazy.any({ produce: () => this.ulimits.map(renderUlimit) }, { omitEmptyArray: true }),
user: this.props.user,
volumesFrom: cdk.Lazy.any({ produce: () => this.volumesFrom.map(renderVolumeFrom) }, { omitEmptyArray: true }),
workingDirectory: this.props.workingDirectory,
logConfiguration: this.logDriverConfig,
environment: this.environment && Object.keys(this.environment).length ? renderKV(this.environment, 'name', 'value') : undefined,
environmentFiles: this.environmentFiles && renderEnvironmentFiles(cdk.Stack.of(this).partition, this.environmentFiles),
secrets: this.secrets,
extraHosts: this.props.extraHosts && renderKV(this.props.extraHosts, 'hostname', 'ipAddress'),
healthCheck: this.props.healthCheck && renderHealthCheck(this.props.healthCheck),
links: cdk.Lazy.list({ produce: () => this.links }, { omitEmpty: true }),
linuxParameters: this.linuxParameters && this.linuxParameters.renderLinuxParameters(),
resourceRequirements: (!this.props.gpuCount && this.inferenceAcceleratorResources.length == 0) ? undefined :
renderResourceRequirements(this.props.gpuCount, this.inferenceAcceleratorResources),
systemControls: this.props.systemControls && renderSystemControls(this.props.systemControls),
};
}
}
exports.ContainerDefinition = ContainerDefinition;
_b = JSII_RTTI_SYMBOL_1;
ContainerDefinition[_b] = { fqn: "@aws-cdk/aws-ecs.ContainerDefinition", version: "1.204.0" };
function renderKV(env, keyName, valueName) {
const ret = [];
for (const [key, value] of Object.entries(env)) {
ret.push({ [keyName]: key, [valueName]: value });
}
return ret;
}
function renderEnvironmentFiles(partition, environmentFiles) {
const ret = [];
for (const environmentFile of environmentFiles) {
const s3Location = environmentFile.s3Location;
if (!s3Location) {
throw Error('Environment file must specify an S3 location');
}
ret.push({
type: environmentFile.fileType,
value: `arn:${partition}:s3:::${s3Location.bucketName}/${s3Location.objectKey}`,
});
}
return ret;
}
function renderHealthCheck(hc) {
return {
command: getHealthCheckCommand(hc),
interval: hc.interval?.toSeconds() ?? 30,
retries: hc.retries ?? 3,
startPeriod: hc.startPeriod?.toSeconds(),
timeout: hc.timeout?.toSeconds() ?? 5,
};
}
function getHealthCheckCommand(hc) {
const cmd = hc.command;
const hcCommand = new Array();
if (cmd.length === 0) {
throw new Error('At least one argument must be supplied for health check command.');
}
if (cmd.length === 1) {
hcCommand.push('CMD-SHELL', cmd[0]);
return hcCommand;
}
if (cmd[0] !== 'CMD' && cmd[0] !== 'CMD-SHELL') {
hcCommand.push('CMD');
}
return hcCommand.concat(cmd);
}
function renderResourceRequirements(gpuCount = 0, inferenceAcceleratorResources = []) {
const ret = [];
for (const resource of inferenceAcceleratorResources) {
ret.push({
type: 'InferenceAccelerator',
value: resource,
});
}
if (gpuCount > 0) {
ret.push({
type: 'GPU',
value: gpuCount.toString(),
});
}
return ret;
}
/**
* Type of resource to set a limit on
*/
var UlimitName;
(function (UlimitName) {
UlimitName["CORE"] = "core";
UlimitName["CPU"] = "cpu";
UlimitName["DATA"] = "data";
UlimitName["FSIZE"] = "fsize";
UlimitName["LOCKS"] = "locks";
UlimitName["MEMLOCK"] = "memlock";
UlimitName["MSGQUEUE"] = "msgqueue";
UlimitName["NICE"] = "nice";
UlimitName["NOFILE"] = "nofile";
UlimitName["NPROC"] = "nproc";
UlimitName["RSS"] = "rss";
UlimitName["RTPRIO"] = "rtprio";
UlimitName["RTTIME"] = "rttime";
UlimitName["SIGPENDING"] = "sigpending";
UlimitName["STACK"] = "stack";
})(UlimitName = exports.UlimitName || (exports.UlimitName = {}));
function renderUlimit(ulimit) {
return {
name: ulimit.name,
softLimit: ulimit.softLimit,
hardLimit: ulimit.hardLimit,
};
}
var ContainerDependencyCondition;
(function (ContainerDependencyCondition) {
/**
* This condition emulates the behavior of links and volumes today.
* It validates that a dependent container is started before permitting other containers to start.
*/
ContainerDependencyCondition["START"] = "START";
/**
* This condition validates that a dependent container runs to completion (exits) before permitting other containers to start.
* This can be useful for nonessential containers that run a script and then exit.
*/
ContainerDependencyCondition["COMPLETE"] = "COMPLETE";
/**
* This condition is the same as COMPLETE, but it also requires that the container exits with a zero status.
*/
ContainerDependencyCondition["SUCCESS"] = "SUCCESS";
/**
* This condition validates that the dependent container passes its Docker health check before permitting other containers to start.
* This requires that the dependent container has health checks configured. This condition is confirmed only at task startup.
*/
ContainerDependencyCondition["HEALTHY"] = "HEALTHY";
})(ContainerDependencyCondition = exports.ContainerDependencyCondition || (exports.ContainerDependencyCondition = {}));
function renderContainerDependency(containerDependency) {
return {
containerName: containerDependency.container.containerName,
condition: containerDependency.condition || ContainerDependencyCondition.HEALTHY,
};
}
/**
* Network protocol
*/
var Protocol;
(function (Protocol) {
/**
* TCP
*/
Protocol["TCP"] = "tcp";
/**
* UDP
*/
Protocol["UDP"] = "udp";
})(Protocol = exports.Protocol || (exports.Protocol = {}));
function renderPortMapping(pm) {
return {
containerPort: pm.containerPort,
hostPort: pm.hostPort,
protocol: pm.protocol || Protocol.TCP,
};
}
function renderMountPoint(mp) {
return {
containerPath: mp.containerPath,
readOnly: mp.readOnly,
sourceVolume: mp.sourceVolume,
};
}
function renderVolumeFrom(vf) {
return {
sourceContainer: vf.sourceContainer,
readOnly: vf.readOnly,
};
}
function renderSystemControls(systemControls) {
return systemControls.map(sc => ({
namespace: sc.namespace,
value: sc.value,
}));
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGFpbmVyLWRlZmluaXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJjb250YWluZXItZGVmaW5pdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFHQSxxQ0FBcUM7QUFFckMsNERBQXFFO0FBT3JFLGlHQUFpRztBQUNqRyw4REFBOEQ7QUFDOUQsd0NBQTJEO0FBb0IzRDs7R0FFRztBQUNILE1BQXNCLE1BQU07SUFDMUI7OztPQUdHO0lBQ0ksTUFBTSxDQUFDLGdCQUFnQixDQUFDLFNBQXlCO1FBQ3RELE9BQU87WUFDTCxHQUFHLEVBQUUsU0FBUyxDQUFDLFlBQVk7WUFDM0IsU0FBUyxFQUFFLE9BQU8sQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUM7U0FDbkQsQ0FBQztLQUNIO0lBRUQ7Ozs7Ozs7OztPQVNHO0lBQ0ksTUFBTSxDQUFDLGtCQUFrQixDQUFDLE1BQThCLEVBQUUsS0FBYztRQUM3RSxPQUFPO1lBQ0wsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxNQUFNLENBQUMsU0FBUyxJQUFJLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsU0FBUztZQUNoRSxRQUFRLEVBQUUsQ0FBQyxDQUFDLEtBQUs7WUFDakIsU0FBUyxFQUFFLE9BQU8sQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUM7U0FDaEQsQ0FBQztLQUNIO0lBRUQ7Ozs7Ozs7Ozs7T0FVRztJQUNJLE1BQU0sQ0FBQyx5QkFBeUIsQ0FBQyxNQUE4QixFQUFFLFdBQThCLEVBQUUsS0FBYzs7Ozs7Ozs7OztRQUNwSCxPQUFPO1lBQ0wsR0FBRyxFQUFFLEdBQUcsTUFBTSxDQUFDLFNBQVMsSUFBSSxLQUFLLElBQUksRUFBRSxJQUFJLFdBQVcsQ0FBQyxZQUFZLElBQUksRUFBRSxJQUFJLFdBQVcsQ0FBQyxTQUFTLElBQUksRUFBRSxFQUFFO1lBQzFHLFFBQVEs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QUFDSixDQUFDO0FBK0NELFNBQVMsZ0JBQWdCLENBQUMsRUFBYztJQUN0QyxPQUFPO1FBQ0wsYUFBYSxFQUFFLEVBQUUsQ0FBQyxhQUFhO1FBQy9CLFFBQVEsRUFBRSxFQUFFLENBQUMsUUFBUTtRQUNyQixZQUFZLEVBQUUsRUFBRSxDQUFDLFlBQVk7S0FDOUIsQ0FBQztBQUNKLENBQUM7QUFvQkQsU0FBUyxnQkFBZ0IsQ0FBQyxFQUFjO0lBQ3RDLE9BQU87UUFDTCxlQUFlLEVBQUUsRUFBRSxDQUFDLGVBQWU7UUFDbkMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxRQUFRO0tBQ3RCLENBQUM7QUFDSixDQUFDO0FBaUJELFNBQVMsb0JBQW9CLENBQUMsY0FBK0I7SUFDM0QsT0FBTyxjQUFjLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUMvQixTQUFTLEVBQUUsRUFBRSxDQUFDLFNBQVM7UUFDdkIsS0FBSyxFQUFFLEVBQUUsQ0FBQyxLQUFLO0tBQ2hCLENBQUMsQ0FBQyxDQUFDO0FBQ04sQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGlhbSBmcm9tICdAYXdzLWNkay9hd3MtaWFtJztcbmltcG9ydCAqIGFzIHNlY3JldHNtYW5hZ2VyIGZyb20gJ0Bhd3MtY2RrL2F3cy1zZWNyZXRzbWFuYWdlcic7XG5pbXBvcnQgKiBhcyBzc20gZnJvbSAnQGF3cy1jZGsvYXdzLXNzbSc7XG5pbXBvcnQgKiBhcyBjZGsgZnJvbSAnQGF3cy1jZGsvY29yZSc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IE5ldHdvcmtNb2RlLCBUYXNrRGVmaW5pdGlvbiB9IGZyb20gJy4vYmFzZS90YXNrLWRlZmluaXRpb24nO1xuaW1wb3J0IHsgQ29udGFpbmVySW1hZ2UsIENvbnRhaW5lckltYWdlQ29uZmlnIH0gZnJvbSAnLi9jb250YWluZXItaW1hZ2UnO1xuaW1wb3J0IHsgQ2ZuVGFza0RlZmluaXRpb24gfSBmcm9tICcuL2Vjcy5nZW5lcmF0ZWQnO1xuaW1wb3J0IHsgRW52aXJvbm1lbnRGaWxlLCBFbnZpcm9ubWVudEZpbGVDb25maWcgfSBmcm9tICcuL2Vudmlyb25tZW50LWZpbGUnO1xuaW1wb3J0IHsgTGludXhQYXJhbWV0ZXJzIH0gZnJvbSAnLi9saW51eC1wYXJhbWV0ZXJzJztcbmltcG9ydCB7IExvZ0RyaXZlciwgTG9nRHJpdmVyQ29uZmlnIH0gZnJvbSAnLi9sb2ctZHJpdmVycy9sb2ctZHJpdmVyJztcblxuLy8ga2VlcCB0aGlzIGltcG9ydCBzZXBhcmF0ZSBmcm9tIG90aGVyIGltcG9ydHMgdG8gcmVkdWNlIGNoYW5jZSBmb3IgbWVyZ2UgY29uZmxpY3RzIHdpdGggdjItbWFpblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWR1cGxpY2F0ZS1pbXBvcnRzLCBpbXBvcnQvb3JkZXJcbmltcG9ydCB7IENvbnN0cnVjdCBhcyBDb3JlQ29uc3RydWN0IH0gZnJvbSAnQGF3cy1jZGsvY29yZSc7XG5cbi8qKlxuICogU3BlY2lmeSB0aGUgc2VjcmV0J3MgdmVyc2lvbiBpZCBvciB2ZXJzaW9uIHN0YWdlXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2VjcmV0VmVyc2lvbkluZm8ge1xuICAvKipcbiAgICogdmVyc2lvbiBpZCBvZiB0aGUgc2VjcmV0XG4gICAqXG4gICAqIEBkZWZhdWx0IC0gdXNlIGRlZmF1bHQgdmVyc2lvbiBpZFxuICAgKi9cbiAgcmVhZG9ubHkgdmVyc2lvbklkPzogc3RyaW5nO1xuICAvKipcbiAgICogdmVyc2lvbiBzdGFnZSBvZiB0aGUgc2VjcmV0XG4gICAqXG4gICAqIEBkZWZhdWx0IC0gdXNlIGRlZmF1bHQgdmVyc2lvbiBzdGFnZVxuICAgKi9cbiAgcmVhZG9ubHkgdmVyc2lvblN0YWdlPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIEEgc2VjcmV0IGVudmlyb25tZW50IHZhcmlhYmxlLlxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgU2VjcmV0IHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gZW52aXJvbm1lbnQgdmFyaWFibGUgdmFsdWUgZnJvbSBhIHBhcmFtZXRlciBzdG9yZWQgaW4gQVdTXG4gICAqIFN5c3RlbXMgTWFuYWdlciBQYXJhbWV0ZXIgU3RvcmUuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21Tc21QYXJhbWV0ZXIocGFyYW1ldGVyOiBzc20uSVBhcmFtZXRlcik6IFNlY3JldCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGFybjogcGFyYW1ldGVyLnBhcmFtZXRlckFybixcbiAgICAgIGdyYW50UmVhZDogZ3JhbnRlZSA9PiBwYXJhbWV0ZXIuZ3JhbnRSZWFkKGdyYW50ZWUpLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIGVudmlyb25tZW50IHZhcmlhYmxlIHZhbHVlIGZyb20gYSBzZWNyZXQgc3RvcmVkIGluIEFXUyBTZWNyZXRzXG4gICAqIE1hbmFnZXIuXG4gICAqXG4gICAqIEBwYXJhbSBzZWNyZXQgdGhlIHNlY3JldCBzdG9yZWQgaW4gQVdTIFNlY3JldHMgTWFuYWdlclxuICAgKiBAcGFyYW0gZmllbGQgdGhlIG5hbWUgb2YgdGhlIGZpZWxkIHdpdGggdGhlIHZhbHVlIHRoYXQgeW91IHdhbnQgdG8gc2V0IGFzXG4gICAqIHRoZSBlbnZpcm9ubWVudCB2YXJpYWJsZSB2YWx1ZS4gT25seSB2YWx1ZXMgaW4gSlNPTiBmb3JtYXQgYXJlIHN1cHBvcnRlZC5cbiAgICogSWYgeW91IGRvIG5vdCBzcGVjaWZ5IGEgSlNPTiBmaWVsZCwgdGhlbiB0aGUgZnVsbCBjb250ZW50IG9mIHRoZSBzZWNyZXQgaXNcbiAgICogdXNlZC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbVNlY3JldHNNYW5hZ2VyKHNlY3JldDogc2VjcmV0c21hbmFnZXIuSVNlY3JldCwgZmllbGQ/OiBzdHJpbmcpOiBTZWNyZXQge1xuICAgIHJldHVybiB7XG4gICAgICBhcm46IGZpZWxkID8gYCR7c2VjcmV0LnNlY3JldEFybn06JHtmaWVsZH06OmAgOiBzZWNyZXQuc2VjcmV0QXJuLFxuICAgICAgaGFzRmllbGQ6ICEhZmllbGQsXG4gICAgICBncmFudFJlYWQ6IGdyYW50ZWUgPT4gc2VjcmV0LmdyYW50UmVhZChncmFudGVlKSxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBlbnZpcm9ubWVudCB2YXJpYWJsZSB2YWx1ZSBmcm9tIGEgc2VjcmV0IHN0b3JlZCBpbiBBV1MgU2VjcmV0c1xuICAgKiBNYW5hZ2VyLlxuICAgKlxuICAgKiBAcGFyYW0gc2VjcmV0IHRoZSBzZWNyZXQgc3RvcmVkIGluIEFXUyBTZWNyZXRzIE1hbmFnZXJcbiAgICogQHBhcmFtIHZlcnNpb25JbmZvIHRoZSB2ZXJzaW9uIGluZm9ybWF0aW9uIHRvIHJlZmVyZW5jZSB0aGUgc2VjcmV0XG4gICAqIEBwYXJhbSBmaWVsZCB0aGUgbmFtZSBvZiB0aGUgZmllbGQgd2l0aCB0aGUgdmFsdWUgdGhhdCB5b3Ugd2FudCB0byBzZXQgYXNcbiAgICogdGhlIGVudmlyb25tZW50IHZhcmlhYmxlIHZhbHVlLiBPbmx5IHZhbHVlcyBpbiBKU09OIGZvcm1hdCBhcmUgc3VwcG9ydGVkLlxuICAgKiBJZiB5b3UgZG8gbm90IHNwZWNpZnkgYSBKU09OIGZpZWxkLCB0aGVuIHRoZSBmdWxsIGNvbnRlbnQgb2YgdGhlIHNlY3JldCBpc1xuICAgKiB1c2VkLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tU2VjcmV0c01hbmFnZXJWZXJzaW9uKHNlY3JldDogc2VjcmV0c21hbmFnZXIuSVNlY3JldCwgdmVyc2lvbkluZm86IFNlY3JldFZlcnNpb25JbmZvLCBmaWVsZD86IHN0cmluZyk6IFNlY3JldCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGFybjogYCR7c2VjcmV0LnNlY3JldEFybn06JHtmaWVsZCA/PyAnJ306JHt2ZXJzaW9uSW5mby52ZXJzaW9uU3RhZ2UgPz8gJyd9OiR7dmVyc2lvbkluZm8udmVyc2lvbklkID8/ICcnfWAsXG4gICAgICBoYXNGaWVsZDogISFmaWVsZCxcbiAgICAgIGdyYW50UmVhZDogZ3JhbnRlZSA9PiBzZWNyZXQuZ3JhbnRSZWFkKGdyYW50ZWUpLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogVGhlIEFSTiBvZiB0aGUgc2VjcmV0XG4gICAqL1xuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkgYXJuOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhpcyBzZWNyZXQgdXNlcyBhIHNwZWNpZmljIEpTT04gZmllbGRcbiAgICovXG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSBoYXNGaWVsZD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEdyYW50cyByZWFkaW5nIHRoZSBzZWNyZXQgdG8gYSBwcmluY2lwYWxcbiAgICovXG4gIHB1YmxpYyBhYnN0cmFjdCBncmFudFJlYWQoZ3JhbnRlZTogaWFtLklHcmFudGFibGUpOiBpYW0uR3JhbnQ7XG59XG5cbi8qXG4gKiBUaGUgb3B0aW9ucyBmb3IgY3JlYXRpbmcgYSBjb250YWluZXIgZGVmaW5pdGlvbi5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDb250YWluZXJEZWZpbml0aW9uT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgaW1hZ2UgdXNlZCB0byBzdGFydCBhIGNvbnRhaW5lci5cbiAgICpcbiAgICogVGhpcyBzdHJpbmcgaXMgcGFzc2VkIGRpcmVjdGx5IHRvIHRoZSBEb2NrZXIgZGFlbW9uLlxuICAgKiBJbWFnZXMgaW4gdGhlIERvY2tlciBIdWIgcmVnaXN0cnkgYXJlIGF2YWlsYWJsZSBieSBkZWZhdWx0LlxuICAgKiBPdGhlciByZXBvc2l0b3JpZXMgYXJlIHNwZWNpZmllZCB3aXRoIGVpdGhlciByZXBvc2l0b3J5LXVybC9pbWFnZTp0YWcgb3IgcmVwb3NpdG9yeS11cmwvaW1hZ2VAZGlnZXN0LlxuICAgKiBUT0RPOiBVcGRhdGUgdGhlc2UgdG8gc3BlY2lmeSB1c2luZyBjbGFzc2VzIG9mIElDb250YWluZXJJbWFnZVxuICAgKi9cbiAgcmVhZG9ubHkgaW1hZ2U6IENvbnRhaW5lckltYWdlO1xuXG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgY29udGFpbmVyLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIGlkIG9mIG5vZGUgYXNzb2NpYXRlZCB3aXRoIENvbnRhaW5lckRlZmluaXRpb24uXG4gICAqL1xuICByZWFkb25seSBjb250YWluZXJOYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgY29tbWFuZCB0aGF0IGlzIHBhc3NlZCB0byB0aGUgY29udGFpbmVyLlxuICAgKlxuICAgKiBJZiB5b3UgcHJvdmlkZSBhIHNoZWxsIGNvbW1hbmQgYXMgYSBzaW5nbGUgc3RyaW5nLCB5b3UgaGF2ZSB0byBxdW90ZSBjb21tYW5kLWxpbmUgYXJndW1lbnRzLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIENNRCB2YWx1ZSBidWlsdCBpbnRvIGNvbnRhaW5lciBpbWFnZS5cbiAgICovXG4gIHJlYWRvbmx5IGNvbW1hbmQ/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogVGhlIG1pbmltdW0gbnVtYmVyIG9mIENQVSB1bml0cyB0byByZXNlcnZlIGZvciB0aGUgY29udGFpbmVyLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIG1pbmltdW0gQ1BVIHVuaXRzIHJlc2VydmVkLlxuICAgKi9cbiAgcmVhZG9ubHkgY3B1PzogbnVtYmVyO1xuXG4gIC8qKlxuICAgKiBTcGVjaWZpZXMgd2hldGhlciBuZXR3b3JraW5nIGlzIGRpc2FibGVkIHdpdGhpbiB0aGUgY29udGFpbmVyLlxuICAgKlxuICAgKiBXaGVuIHRoaXMgcGFyYW1ldGVyIGlzIHRydWUsIG5ldHdvcmtpbmcgaXMgZGlzYWJsZWQgd2l0aGluIHRoZSBjb250YWluZXIuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBkaXNhYmxlTmV0d29ya2luZz86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEEgbGlzdCBvZiBETlMgc2VhcmNoIGRvbWFpbnMgdGhhdCBhcmUgcHJlc2VudGVkIHRvIHRoZSBjb250YWluZXIuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gc2VhcmNoIGRvbWFpbnMuXG4gICAqL1xuICByZWFkb25seSBkbnNTZWFyY2hEb21haW5zPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIEEgbGlzdCBvZiBETlMgc2VydmVycyB0aGF0IGFyZSBwcmVzZW50ZWQgdG8gdGhlIGNvbnRhaW5lci5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBEZWZhdWx0IEROUyBzZXJ2ZXJzLlxuICAgKi9cbiAgcmVhZG9ubHkgZG5zU2VydmVycz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBBIGtleS92YWx1ZSBtYXAgb2YgbGFiZWxzIHRvIGFkZCB0byB0aGUgY29udGFpbmVyLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIGxhYmVscy5cbiAgICovXG4gIHJlYWRvbmx5IGRvY2tlckxhYmVscz86IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH07XG5cbiAgLyoqXG4gICAqIEEgbGlzdCBvZiBzdHJpbmdzIHRvIHByb3ZpZGUgY3VzdG9tIGxhYmVscyBmb3IgU0VMaW51eCBhbmQgQXBwQXJtb3IgbXVsdGktbGV2ZWwgc2VjdXJpdHkgc3lzdGVtcy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBzZWN1cml0eSBsYWJlbHMuXG4gICAqL1xuICByZWFkb25seSBkb2NrZXJTZWN1cml0eU9wdGlvbnM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogVGhlIEVOVFJZUE9JTlQgdmFsdWUgdG8gcGFzcyB0byB0aGUgY29udGFpbmVyLlxuICAgKlxuICAgKiBAc2VlIGh0dHBzOi8vZG9jcy5kb2NrZXIuY29tL2VuZ2luZS9yZWZlcmVuY2UvYnVpbGRlci8jZW50cnlwb2ludFxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEVudHJ5IHBvaW50IGNvbmZpZ3VyZWQgaW4gY29udGFpbmVyLlxuICAgKi9cbiAgcmVhZG9ubHkgZW50cnlQb2ludD86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBUaGUgZW52aXJvbm1lbnQgdmFyaWFibGVzIHRvIHBhc3MgdG8gdGhlIGNvbnRhaW5lci5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBlbnZpcm9ubWVudCB2YXJpYWJsZXMuXG4gICAqL1xuICByZWFkb25seSBlbnZpcm9ubWVudD86IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH07XG5cbiAgLyoqXG4gICAqIFRoZSBlbnZpcm9ubWVudCBmaWxlcyB0byBwYXNzIHRvIHRoZSBjb250YWluZXIuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FtYXpvbkVDUy9sYXRlc3QvZGV2ZWxvcGVyZ3VpZGUvdGFza2RlZi1lbnZmaWxlcy5odG1sXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gZW52aXJvbm1lbnQgZmlsZXMuXG4gICAqL1xuICByZWFkb25seSBlbnZpcm9ubWVudEZpbGVzPzogRW52aXJvbm1lbnRGaWxlW107XG5cbiAgLyoqXG4gICAqIFRoZSBzZWNyZXQgZW52aXJvbm1lbnQgdmFyaWFibGVzIHRvIHBhc3MgdG8gdGhlIGNvbnRhaW5lci5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBzZWNyZXQgZW52aXJvbm1lbnQgdmFyaWFibGVzLlxuICAgKi9cbiAgcmVhZG9ubHkgc2VjcmV0cz86IHsgW2tleTogc3RyaW5nXTogU2VjcmV0IH07XG5cbiAgLyoqXG4gICAqIFRpbWUgZHVyYXRpb24gKGluIHNlY29uZHMpIHRvIHdhaXQgYmVmb3JlIGdpdmluZyB1cCBvbiByZXNvbHZpbmcgZGVwZW5