UNPKG

@aws-cdk/aws-ecs

Version:

The CDK Construct Library for AWS::ECS

521 lines 88.1 kB
"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) { var _c, _d; jsiiDeprecationWarnings._aws_cdk_aws_ecs_SecretVersionInfo(versionInfo); return { arn: `${secret.secretArn}:${field !== null && field !== void 0 ? field : ''}:${(_c = versionInfo.versionStage) !== null && _c !== void 0 ? _c : ''}:${(_d = versionInfo.versionId) !== null && _d !== void 0 ? _d : ''}`, 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.149.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) { var _c, _d; 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(); jsiiDeprecationWarnings._aws_cdk_aws_ecs_ContainerDefinitionProps(props); if (props.memoryLimitMiB !== undefined && props.memoryReservationMiB !== undefined) { if (props.memoryLimitMiB < props.memoryReservationMiB) { throw new Error('MemoryLimitMiB should not be less than MemoryReservationMiB.'); } } this.essential = (_c = props.essential) !== null && _c !== void 0 ? _c : true; this.taskDefinition = props.taskDefinition; this.memoryLimitSpecified = props.memoryLimitMiB !== undefined || props.memoryReservationMiB !== undefined; this.linuxParameters = props.linuxParameters; this.containerName = (_d = props.containerName) !== null && _d !== void 0 ? _d : 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) { jsiiDeprecationWarnings._aws_cdk_aws_ecs_ContainerDefinition(container); 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) { jsiiDeprecationWarnings._aws_cdk_aws_ecs_MountPoint(mountPoints); 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) { jsiiDeprecationWarnings._aws_cdk_aws_ecs_ScratchSpace(scratch); 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) { jsiiDeprecationWarnings._aws_cdk_aws_ecs_PortMapping(portMappings); 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) { jsiiDeprecationWarnings._aws_cdk_aws_ecs_Ulimit(ulimits); this.ulimits.push(...ulimits); } /** * This method adds one or more container dependencies to the container. */ addContainerDependencies(...containerDependencies) { jsiiDeprecationWarnings._aws_cdk_aws_ecs_ContainerDependency(containerDependencies); this.containerDependencies.push(...containerDependencies); } /** * This method adds one or more volumes to the container. */ addVolumesFrom(...volumesFrom) { jsiiDeprecationWarnings._aws_cdk_aws_ecs_VolumeFrom(volumesFrom); 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) { jsiiDeprecationWarnings._aws_cdk_aws_ecs_Protocol(protocol); 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) { jsiiDeprecationWarnings._aws_cdk_aws_ecs_TaskDefinition(_taskDefinition); 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.149.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) { var _c, _d, _e, _f, _g, _h; return { command: getHealthCheckCommand(hc), interval: (_d = (_c = hc.interval) === null || _c === void 0 ? void 0 : _c.toSeconds()) !== null && _d !== void 0 ? _d : 30, retries: (_e = hc.retries) !== null && _e !== void 0 ? _e : 3, startPeriod: (_f = hc.startPeriod) === null || _f === void 0 ? void 0 : _f.toSeconds(), timeout: (_h = (_g = hc.timeout) === null || _g === void 0 ? void 0 : _g.toSeconds()) !== null && _h !== void 0 ? _h : 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGFpbmVyLWRlZmluaXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJjb250YWluZXItZGVmaW5pdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFHQSxxQ0FBcUM7QUFFckMsNERBQXFFO0FBT3JFLGlHQUFpRztBQUNqRyw4REFBOEQ7QUFDOUQsd0NBQTJEO0FBb0IzRDs7R0FFRztBQUNILE1BQXNCLE1BQU07SUFDMUI7OztPQUdHO0lBQ0ksTUFBTSxDQUFDLGdCQUFnQixDQUFDLFNBQXlCO1FBQ3RELE9BQU87WUFDTCxHQUFHLEVBQUUsU0FBUyxDQUFDLFlBQVk7WUFDM0IsU0FBUyxFQUFFLE9BQU8sQ0FBQyxFQUFFLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUM7U0FDbkQsQ0FBQztLQUNIO0lBRUQ7Ozs7Ozs7OztPQVNHO0lBQ0ksTUFBTSxDQUFDLGtCQUFrQixDQUFDLE1BQThCLEVBQUUsS0FBYztRQUM3RSxPQUFPO1lBQ0wsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxNQUFNLENBQUMsU0FBUyxJQUFJLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsU0FBUztZQUNoRSxRQUFRLEVBQUUsQ0FBQyxDQUFDLEtBQUs7WUFDakIsU0FBUyxFQUFFLE9BQU8sQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUM7U0FDaEQsQ0FBQztLQUNIO0lBRUQ7Ozs7Ozs7Ozs7T0FVRztJQUNJLE1BQU0sQ0FBQyx5QkFBeUIsQ0FBQyxNQUE4QixFQUFFLFdBQThCLEVBQUUsS0FBYzs7O1FBQ3BILE9BQU87WUFDTCxHQUFHLEVBQUUsR0FBRyxNQUFNLENBQUMsU0FBUyxJQUFJLEtBQUssYUFBTCxLQUFLLGNBQUwsS0FBSyxHQUFJLEVBQUUsSUFBSSxNQUFBLFdBQVcsQ0FBQyxZQUFZLG1DQUFJLEVBQUUsSUFBSSxNQUFBLFdBQVcsQ0FBQyxTQUFTLG1D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QUFDLGFBQWE7UUFDL0IsUUFBUSxFQUFFLEVBQUUsQ0FBQyxRQUFRO1FBQ3JCLFlBQVksRUFBRSxFQUFFLENBQUMsWUFBWTtLQUM5QixDQUFDO0FBQ0osQ0FBQztBQW9CRCxTQUFTLGdCQUFnQixDQUFDLEVBQWM7SUFDdEMsT0FBTztRQUNMLGVBQWUsRUFBRSxFQUFFLENBQUMsZUFBZTtRQUNuQyxRQUFRLEVBQUUsRUFBRSxDQUFDLFFBQVE7S0FDdEIsQ0FBQztBQUNKLENBQUM7QUFpQkQsU0FBUyxvQkFBb0IsQ0FBQyxjQUErQjtJQUMzRCxPQUFPLGNBQWMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQy9CLFNBQVMsRUFBRSxFQUFFLENBQUMsU0FBUztRQUN2QixLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUs7S0FDaEIsQ0FBQyxDQUFDLENBQUM7QUFDTixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgaWFtIGZyb20gJ0Bhd3MtY2RrL2F3cy1pYW0nO1xuaW1wb3J0ICogYXMgc2VjcmV0c21hbmFnZXIgZnJvbSAnQGF3cy1jZGsvYXdzLXNlY3JldHNtYW5hZ2VyJztcbmltcG9ydCAqIGFzIHNzbSBmcm9tICdAYXdzLWNkay9hd3Mtc3NtJztcbmltcG9ydCAqIGFzIGNkayBmcm9tICdAYXdzLWNkay9jb3JlJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgTmV0d29ya01vZGUsIFRhc2tEZWZpbml0aW9uIH0gZnJvbSAnLi9iYXNlL3Rhc2stZGVmaW5pdGlvbic7XG5pbXBvcnQgeyBDb250YWluZXJJbWFnZSwgQ29udGFpbmVySW1hZ2VDb25maWcgfSBmcm9tICcuL2NvbnRhaW5lci1pbWFnZSc7XG5pbXBvcnQgeyBDZm5UYXNrRGVmaW5pdGlvbiB9IGZyb20gJy4vZWNzLmdlbmVyYXRlZCc7XG5pbXBvcnQgeyBFbnZpcm9ubWVudEZpbGUsIEVudmlyb25tZW50RmlsZUNvbmZpZyB9IGZyb20gJy4vZW52aXJvbm1lbnQtZmlsZSc7XG5pbXBvcnQgeyBMaW51eFBhcmFtZXRlcnMgfSBmcm9tICcuL2xpbnV4LXBhcmFtZXRlcnMnO1xuaW1wb3J0IHsgTG9nRHJpdmVyLCBMb2dEcml2ZXJDb25maWcgfSBmcm9tICcuL2xvZy1kcml2ZXJzL2xvZy1kcml2ZXInO1xuXG4vLyBrZWVwIHRoaXMgaW1wb3J0IHNlcGFyYXRlIGZyb20gb3RoZXIgaW1wb3J0cyB0byByZWR1Y2UgY2hhbmNlIGZvciBtZXJnZSBjb25mbGljdHMgd2l0aCB2Mi1tYWluXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tZHVwbGljYXRlLWltcG9ydHMsIGltcG9ydC9vcmRlclxuaW1wb3J0IHsgQ29uc3RydWN0IGFzIENvcmVDb25zdHJ1Y3QgfSBmcm9tICdAYXdzLWNkay9jb3JlJztcblxuLyoqXG4gKiBTcGVjaWZ5IHRoZSBzZWNyZXQncyB2ZXJzaW9uIGlkIG9yIHZlcnNpb24gc3RhZ2VcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTZWNyZXRWZXJzaW9uSW5mbyB7XG4gIC8qKlxuICAgKiB2ZXJzaW9uIGlkIG9mIHRoZSBzZWNyZXRcbiAgICpcbiAgICogQGRlZmF1bHQgLSB1c2UgZGVmYXVsdCB2ZXJzaW9uIGlkXG4gICAqL1xuICByZWFkb25seSB2ZXJzaW9uSWQ/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiB2ZXJzaW9uIHN0YWdlIG9mIHRoZSBzZWNyZXRcbiAgICpcbiAgICogQGRlZmF1bHQgLSB1c2UgZGVmYXVsdCB2ZXJzaW9uIHN0YWdlXG4gICAqL1xuICByZWFkb25seSB2ZXJzaW9uU3RhZ2U/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogQSBzZWNyZXQgZW52aXJvbm1lbnQgdmFyaWFibGUuXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBTZWNyZXQge1xuICAvKipcbiAgICogQ3JlYXRlcyBhbiBlbnZpcm9ubWVudCB2YXJpYWJsZSB2YWx1ZSBmcm9tIGEgcGFyYW1ldGVyIHN0b3JlZCBpbiBBV1NcbiAgICogU3lzdGVtcyBNYW5hZ2VyIFBhcmFtZXRlciBTdG9yZS5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbVNzbVBhcmFtZXRlcihwYXJhbWV0ZXI6IHNzbS5JUGFyYW1ldGVyKTogU2VjcmV0IHtcbiAgICByZXR1cm4ge1xuICAgICAgYXJuOiBwYXJhbWV0ZXIucGFyYW1ldGVyQXJuLFxuICAgICAgZ3JhbnRSZWFkOiBncmFudGVlID0+IHBhcmFtZXRlci5ncmFudFJlYWQoZ3JhbnRlZSksXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGVzIGEgZW52aXJvbm1lbnQgdmFyaWFibGUgdmFsdWUgZnJvbSBhIHNlY3JldCBzdG9yZWQgaW4gQVdTIFNlY3JldHNcbiAgICogTWFuYWdlci5cbiAgICpcbiAgICogQHBhcmFtIHNlY3JldCB0aGUgc2VjcmV0IHN0b3JlZCBpbiBBV1MgU2VjcmV0cyBNYW5hZ2VyXG4gICAqIEBwYXJhbSBmaWVsZCB0aGUgbmFtZSBvZiB0aGUgZmllbGQgd2l0aCB0aGUgdmFsdWUgdGhhdCB5b3Ugd2FudCB0byBzZXQgYXNcbiAgICogdGhlIGVudmlyb25tZW50IHZhcmlhYmxlIHZhbHVlLiBPbmx5IHZhbHVlcyBpbiBKU09OIGZvcm1hdCBhcmUgc3VwcG9ydGVkLlxuICAgKiBJZiB5b3UgZG8gbm90IHNwZWNpZnkgYSBKU09OIGZpZWxkLCB0aGVuIHRoZSBmdWxsIGNvbnRlbnQgb2YgdGhlIHNlY3JldCBpc1xuICAgKiB1c2VkLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tU2VjcmV0c01hbmFnZXIoc2VjcmV0OiBzZWNyZXRzbWFuYWdlci5JU2VjcmV0LCBmaWVsZD86IHN0cmluZyk6IFNlY3JldCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGFybjogZmllbGQgPyBgJHtzZWNyZXQuc2VjcmV0QXJufToke2ZpZWxkfTo6YCA6IHNlY3JldC5zZWNyZXRBcm4sXG4gICAgICBoYXNGaWVsZDogISFmaWVsZCxcbiAgICAgIGdyYW50UmVhZDogZ3JhbnRlZSA9PiBzZWNyZXQuZ3JhbnRSZWFkKGdyYW50ZWUpLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhIGVudmlyb25tZW50IHZhcmlhYmxlIHZhbHVlIGZyb20gYSBzZWNyZXQgc3RvcmVkIGluIEFXUyBTZWNyZXRzXG4gICAqIE1hbmFnZXIuXG4gICAqXG4gICAqIEBwYXJhbSBzZWNyZXQgdGhlIHNlY3JldCBzdG9yZWQgaW4gQVdTIFNlY3JldHMgTWFuYWdlclxuICAgKiBAcGFyYW0gdmVyc2lvbkluZm8gdGhlIHZlcnNpb24gaW5mb3JtYXRpb24gdG8gcmVmZXJlbmNlIHRoZSBzZWNyZXRcbiAgICogQHBhcmFtIGZpZWxkIHRoZSBuYW1lIG9mIHRoZSBmaWVsZCB3aXRoIHRoZSB2YWx1ZSB0aGF0IHlvdSB3YW50IHRvIHNldCBhc1xuICAgKiB0aGUgZW52aXJvbm1lbnQgdmFyaWFibGUgdmFsdWUuIE9ubHkgdmFsdWVzIGluIEpTT04gZm9ybWF0IGFyZSBzdXBwb3J0ZWQuXG4gICAqIElmIHlvdSBkbyBub3Qgc3BlY2lmeSBhIEpTT04gZmllbGQsIHRoZW4gdGhlIGZ1bGwgY29udGVudCBvZiB0aGUgc2VjcmV0IGlzXG4gICAqIHVzZWQuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21TZWNyZXRzTWFuYWdlclZlcnNpb24oc2VjcmV0OiBzZWNyZXRzbWFuYWdlci5JU2VjcmV0LCB2ZXJzaW9uSW5mbzogU2VjcmV0VmVyc2lvbkluZm8sIGZpZWxkPzogc3RyaW5nKTogU2VjcmV0IHtcbiAgICByZXR1cm4ge1xuICAgICAgYXJuOiBgJHtzZWNyZXQuc2VjcmV0QXJufToke2ZpZWxkID8/ICcnfToke3ZlcnNpb25JbmZvLnZlcnNpb25TdGFnZSA/PyAnJ306JHt2ZXJzaW9uSW5mby52ZXJzaW9uSWQgPz8gJyd9YCxcbiAgICAgIGhhc0ZpZWxkOiAhIWZpZWxkLFxuICAgICAgZ3JhbnRSZWFkOiBncmFudGVlID0+IHNlY3JldC5ncmFudFJlYWQoZ3JhbnRlZSksXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgQVJOIG9mIHRoZSBzZWNyZXRcbiAgICovXG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSBhcm46IHN0cmluZztcblxuICAvKipcbiAgICogV2hldGhlciB0aGlzIHNlY3JldCB1c2VzIGEgc3BlY2lmaWMgSlNPTiBmaWVsZFxuICAgKi9cbiAgcHVibGljIGFic3RyYWN0IHJlYWRvbmx5IGhhc0ZpZWxkPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogR3JhbnRzIHJlYWRpbmcgdGhlIHNlY3JldCB0byBhIHByaW5jaXBhbFxuICAgKi9cbiAgcHVibGljIGFic3RyYWN0IGdyYW50UmVhZChncmFudGVlOiBpYW0uSUdyYW50YWJsZSk6IGlhbS5HcmFudDtcbn1cblxuLypcbiAqIFRoZSBvcHRpb25zIGZvciBjcmVhdGluZyBhIGNvbnRhaW5lciBkZWZpbml0aW9uLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIENvbnRhaW5lckRlZmluaXRpb25PcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSBpbWFnZSB1c2VkIHRvIHN0YXJ0IGEgY29udGFpbmVyLlxuICAgKlxuICAgKiBUaGlzIHN0cmluZyBpcyBwYXNzZWQgZGlyZWN0bHkgdG8gdGhlIERvY2tlciBkYWVtb24uXG4gICAqIEltYWdlcyBpbiB0aGUgRG9ja2VyIEh1YiByZWdpc3RyeSBhcmUgYXZhaWxhYmxlIGJ5IGRlZmF1bHQuXG4gICAqIE90aGVyIHJlcG9zaXRvcmllcyBhcmUgc3BlY2lmaWVkIHdpdGggZWl0aGVyIHJlcG9zaXRvcnktdXJsL2ltYWdlOnRhZyBvciByZXBvc2l0b3J5LXVybC9pbWFnZUBkaWdlc3QuXG4gICAqIFRPRE86IFVwZGF0ZSB0aGVzZSB0byBzcGVjaWZ5IHVzaW5nIGNsYXNzZXMgb2YgSUNvbnRhaW5lckltYWdlXG4gICAqL1xuICByZWFkb25seSBpbWFnZTogQ29udGFpbmVySW1hZ2U7XG5cbiAgLyoqXG4gICAqIFRoZSBuYW1lIG9mIHRoZSBjb250YWluZXIuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gaWQgb2Ygbm9kZSBhc3NvY2lhdGVkIHdpdGggQ29udGFpbmVyRGVmaW5pdGlvbi5cbiAgICovXG4gIHJlYWRvbmx5IGNvbnRhaW5lck5hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBjb21tYW5kIHRoYXQgaXMgcGFzc2VkIHRvIHRoZSBjb250YWluZXIuXG4gICAqXG4gICAqIElmIHlvdSBwcm92aWRlIGEgc2hlbGwgY29tbWFuZCBhcyBhIHNpbmdsZSBzdHJpbmcsIHlvdSBoYXZlIHRvIHF1b3RlIGNvbW1hbmQtbGluZSBhcmd1bWVudHMuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gQ01EIHZhbHVlIGJ1aWx0IGludG8gY29udGFpbmVyIGltYWdlLlxuICAgKi9cbiAgcmVhZG9ubHkgY29tbWFuZD86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBUaGUgbWluaW11bSBudW1iZXIgb2YgQ1BVIHVuaXRzIHRvIHJlc2VydmUgZm9yIHRoZSBjb250YWluZXIuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gbWluaW11bSBDUFUgdW5pdHMgcmVzZXJ2ZWQuXG4gICAqL1xuICByZWFkb25seSBjcHU/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIFNwZWNpZmllcyB3aGV0aGVyIG5ldHdvcmtpbmcgaXMgZGlzYWJsZWQgd2l0aGluIHRoZSBjb250YWluZXIuXG4gICAqXG4gICAqIFdoZW4gdGhpcyBwYXJhbWV0ZXIgaXMgdHJ1ZSwgbmV0d29ya2luZyBpcyBkaXNhYmxlZCB3aXRoaW4gdGhlIGNvbnRhaW5lci5cbiAgICpcbiAgICogQGRlZmF1bHQgZmFsc2VcbiAgICovXG4gIHJlYWRvbmx5IGRpc2FibGVOZXR3b3JraW5nPzogYm9vbGVhbjtcblxuICAvKipcbiAgICogQSBsaXN0IG9mIEROUyBzZWFyY2ggZG9tYWlucyB0aGF0IGFyZSBwcmVzZW50ZWQgdG8gdGhlIGNvbnRhaW5lci5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBzZWFyY2ggZG9tYWlucy5cbiAgICovXG4gIHJlYWRvbmx5IGRuc1NlYXJjaERvbWFpbnM/OiBzdHJpbmdbXTtcblxuICAvKipcbiAgICogQSBsaXN0IG9mIEROUyBzZXJ2ZXJzIHRoYXQgYXJlIHByZXNlbnRlZCB0byB0aGUgY29udGFpbmVyLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIERlZmF1bHQgRE5TIHNlcnZlcnMuXG4gICAqL1xuICByZWFkb25seSBkbnNTZXJ2ZXJzPzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIEEga2V5L3ZhbHVlIG1hcCBvZiBsYWJlbHMgdG8gYWRkIHRvIHRoZSBjb250YWluZXIuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gbGFiZWxzLlxuICAgKi9cbiAgcmVhZG9ubHkgZG9ja2VyTGFiZWxzPzogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfTtcblxuICAvKipcbiAgICogQSBsaXN0IG9mIHN0cmluZ3MgdG8gcHJvdmlkZSBjdXN0b20gbGFiZWxzIGZvciBTRUxpbnV4IGFuZCBBcHBBcm1vciBtdWx0aS1sZXZlbCBzZWN1cml0eSBzeXN0ZW1zLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIHNlY3VyaXR5IGxhYmVscy5cbiAgICovXG4gIHJlYWRvbmx5IGRvY2tlclNlY3VyaXR5T3B0aW9ucz86IHN0cmluZ1tdO1xuXG4gIC8qKlxuICAgKiBUaGUgRU5UUllQT0lOVCB2YWx1ZSB0byBwYXNzIHRvIHRoZSBjb250YWluZXIuXG4gICAqXG4gICAqIEBzZWUgaHR0cHM6Ly9kb2NzLmRvY2tlci5jb20vZW5naW5lL3JlZmVyZW5jZS9idWlsZGVyLyNlbnRyeXBvaW50XG4gICAqXG4gICAqIEBkZWZhdWx0IC0gRW50cnkgcG9pbnQgY29uZmlndXJlZCBpbiBjb250YWluZXIuXG4gICAqL1xuICByZWFkb25seSBlbnRyeVBvaW50Pzogc3RyaW5nW107XG5cbiAgLyoqXG4gICAqIFRoZSBlbnZpcm9ubWVudCB2YXJpYWJsZXMgdG8gcGFzcyB0byB0aGUgY29udGFpbmVyLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIGVudmlyb25tZW50IHZhcmlhYmxlcy5cbiAgICovXG4gIHJlYWRvbmx5IGVudmlyb25tZW50PzogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfTtcblxuICAvKipcbiAgICogVGhlIGVudmlyb25tZW50IGZpbGVzIHRvIHBhc3MgdG8gdGhlIGNvbnRhaW5lci5cbiAgICpcbiAgICogQHNlZSBodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uRUNTL2xhdGVzdC9kZXZlbG9wZXJndWlkZS90YXNrZGVmLWVudmZpbGVzLmh0bWxcbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBlbnZpcm9ubWVudCBmaWxlcy5cbiAgICovXG4gIHJlYWRvbmx5IGVudmlyb25tZW50RmlsZXM/OiBFbnZpcm9ubWVudEZpbGVbXTtcblxuICAvKipcbiAgICogVGhlIHNlY3JldCBlbnZpcm9ubWVudCB2YXJpYWJsZXMgdG8gcGFzcyB0byB0aGUgY29udGFpbmVyLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIHNlY3JldCBlbnZpcm9ubWVudCB2YXJpYWJsZXMuXG4gICAqL1xuICByZWFkb25seSBzZWNyZXRzPzogeyBba2V5OiBzdHJpbmddOiBTZWNyZXQgfTtcblxuICAvKipcbiAgICogVGltZSBkdXJhdGlvbiAoaW4gc2Vjb25kcykgdG8gd2FpdCBiZWZvcmUgZ2l2aW5nIHVwIG9uIHJlc29sdmluZyBkZXBlbmRlbmNpZXMgZm9yIGEgY29udGFpbmVyLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIG5vbmVcbiAgICovXG4gIHJlYWRvbmx5IHN0YXJ0VGltZW91dD86IGNkay5EdXJhdGlvbjtcblxuICAvKipcbiAgICogVGltZSBkdXJhdGlvbiAoaW4gc2Vjb25kcykgdG8gd2FpdCBiZWZvcmUgdGhlIGNvbnRhaW5lciBpcyBmb3JjZWZ1bGx5IGtpbGxlZCBpZiBpdCBkb2Vzbid0IGV4aXQgbm9ybWFsbHkgb24gaXRzIG93bi5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBub25lXG4gICAqL1xuICByZWFkb25seSBzdG9wVGltZW91dD86IGNkay5EdXJhdGlvbjtcblxuICAvKipcbiAgICogU3BlY2lmaWVzIHdoZXRoZXIgdGhlIGNvbnRhaW5lciBpcyBtYXJrZWQgZXNzZW50aWFsLlxuICAgKlxuICAgKiBJZiB0aGUgZXNzZW50aWFsIHBhcmFtZXRlciBvZiBhIGNvbnRhaW5lciBpcyBtYXJrZWQgYXMgdHJ1ZSwgYW5kIHRoYXQgY29udGFpbmVyIGZhaWxzXG4gICAqIG9yIHN0b3BzIGZvciBhbnkgcmVhc29uLCBhbGwgb3RoZXIgY29udGFpbmVycyB0aGF0IGFyZSBwYXJ0IG9mIHRoZSB0YXNrIGFyZSBzdG9wcGVkLlxuICAgKiBJZiB0aGUgZXNzZW50aWFsIHBhcmFtZXRlciBvZiBhIGNvbnRhaW5lciBpcyBtYXJrZWQgYXMgZmFsc2UsIHRoZW4gaXRzIGZhaWx1cmUgZG9lcyBub3RcbiAgICogYWZmZWN0IHRoZSByZXN0IG9mIHRoZSBjb250YWluZXJzIGluIGEgdGFzay4gQWxsIHRhc2tzIG11c3QgaGF2ZSBhdCBsZWFzdCBvbmUgZXNzZW50aWFsIGNvbnRhaW5lci5cbiAgICpcbiAgICogSWYgdGhpcyBwYXJhbWV0ZXIgaXMgb21pdHRlZCwgYSBjb250YWluZXIgaXMgYXNzdW1lZCB0byBiZSBlc3NlbnRpYWwuXG4gICAqXG4gICAqIEBkZWZhdWx0IHRydWVcbiAgICovXG4gIHJlYWRvbmx5IGVzc2VudGlhbD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIEEgbGlzdCBvZiBob3N0bmFtZXMgYW5kIElQIGFkZHJlc3MgbWFwcGluZ3MgdG8gYXBwZW5kIHRvIHRoZSAvZXRjL2hvc3RzIGZpbGUgb24gdGhlIGNvbnRhaW5lci5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBleHRyYSBob3N0cy5cbiAgICovXG4gIHJlYWRvbmx5IGV4dHJhSG9zdHM/OiB7IFtuYW1lOiBzdHJpbmddOiBzdHJpbmcgfTtcblxuICAvKipcbiAgICogVGhlIGhlYWx0aCBjaGVjayBjb21tYW5kIGFuZCBhc3NvY2lhdGVkIGNvbmZpZ3VyYXRpb24gcGFyYW1ldGVycyBmb3IgdGhlIGNvbnRhaW5lci5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBIZWFsdGggY2hlY2sgY29uZmlndXJhdGlvbiBmcm9tIGNvbnRhaW5lci5cbiAgICovXG4gIHJlYWRvbmx5IGhlYWx0aENoZWNrPzogSGVhbHRoQ2hlY2s7XG5cbiAgLyoqXG4gICAqIFRoZSBob3N0bmFtZSB0byB1c2UgZm9yIHlvdXIgY29udGFpbmVyLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEF1dG9tYXRpYyBob3N0bmFtZS5cbiAgICovXG4gIHJlYWRvbmx5IGhvc3RuYW1lPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgYW1vdW50IChpbiBNaUIpIG9mIG1lbW9yeSB0byBwcmVzZW50IHRvIHRoZSBjb250YWluZXIuXG4gICAqXG4gICAqIElmIHlvdXIgY29udGFpbmVyIGF0dGVtcHRzIHRvIGV4Y2VlZCB0aGUgYWxsb2NhdGVkIG1lbW9yeSwgdGhlIGNvbnRhaW5lclxuICAgKiBpcyB0ZXJtaW5hdGVkLlxuICAgKlxuICAgKiBBdCBsZWFzdCBvbmUgb2YgbWVtb3J5TGltaXRNaUIgYW5kIG1lbW9yeVJlc2VydmF0aW9uTWlCIGlzIHJlcXVpcmVkIGZvciBub24tRmFyZ2F0ZSBzZXJ2aWNlcy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBtZW1vcnkgbGltaXQuXG4gICAqL1xuICByZWFkb25seSBtZW1vcnlMaW1pdE1p