UNPKG

@aws-cdk/aws-ecs

Version:

The CDK Construct Library for AWS::ECS

606 lines 90.5 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) { 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