UNPKG

@aws-solutions-constructs/core

Version:
192 lines 30.8 kB
"use strict"; /** * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance * with the License. A copy of the License is located at * * http://www.apache.org/licenses/LICENSE-2.0 * * or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES * OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions * and limitations under the License. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.CreateFargateService = CreateFargateService; exports.CheckFargateProps = CheckFargateProps; exports.CheckForConflictingServiceProps = CheckForConflictingServiceProps; exports.CheckForInvalidVpcs = CheckForInvalidVpcs; exports.getServiceVpcSecurityGroupIds = getServiceVpcSecurityGroupIds; const ec2 = require("aws-cdk-lib/aws-ec2"); const ecs = require("aws-cdk-lib/aws-ecs"); const ecr = require("aws-cdk-lib/aws-ecr"); const defaults = require(".."); const __1 = require(".."); /** * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. */ function CreateFargateService(scope, id, props) { defaults.AddAwsServiceEndpoint(scope, props.constructVpc, defaults.ServiceEndpointTypes.ECR_API); defaults.AddAwsServiceEndpoint(scope, props.constructVpc, defaults.ServiceEndpointTypes.ECR_DKR); defaults.AddAwsServiceEndpoint(scope, props.constructVpc, defaults.ServiceEndpointTypes.S3); const constructContainerDefinitionProps = {}; const constructFargateServiceDefinitionProps = {}; if (!props.clientFargateServiceProps?.cluster) { // Construct Fargate Service constructFargateServiceDefinitionProps.cluster = CreateCluster(scope, `${id}-cluster`, props.constructVpc, props.clientClusterProps); } // Set up the Fargate service if (!props.clientContainerDefinitionProps?.image) { constructContainerDefinitionProps.image = CreateImage(scope, id, props.ecrRepositoryArn, props.ecrImageVersion); } // Create the Fargate Service const createTaskDefinitionResponse = CreateTaskDefinition(scope, id, props.clientFargateTaskDefinitionProps, props.clientContainerDefinitionProps, constructContainerDefinitionProps); constructFargateServiceDefinitionProps.taskDefinition = createTaskDefinitionResponse.taskDefinition; const newContainerDefinition = createTaskDefinitionResponse.containerDefinition; if (!props.clientFargateServiceProps?.vpcSubnets) { if (props.constructVpc.isolatedSubnets.length) { constructFargateServiceDefinitionProps.vpcSubnets = { subnets: props.constructVpc.isolatedSubnets, }; } else { constructFargateServiceDefinitionProps.vpcSubnets = { subnets: props.constructVpc.privateSubnets, }; } } let defaultFargateServiceProps; if (!props.clientFargateServiceProps?.securityGroups) { const serviceSecurityGroup = new ec2.SecurityGroup(scope, `${id}-sg`, { allowAllOutbound: true, disableInlineRules: false, vpc: props.constructVpc, // We add a description here so that this SG can be easily identified in tests description: 'Construct created security group' }); defaultFargateServiceProps = (0, __1.overrideProps)(defaults.DefaultFargateServiceProps(), { securityGroups: [serviceSecurityGroup] }); defaults.addCfnSuppressRules(serviceSecurityGroup, [ { id: 'W5', reason: 'Egress of 0.0.0.0/0 is default and generally considered OK', }, { id: 'W40', reason: 'Egress IPProtocol of -1 is default and generally considered OK', } ]); } else { defaultFargateServiceProps = defaults.DefaultFargateServiceProps(); } const fargateServiceProps = defaults.consolidateProps(defaultFargateServiceProps, props.clientFargateServiceProps, constructFargateServiceDefinitionProps); const newService = new ecs.FargateService(scope, `${id}-service`, fargateServiceProps); return { service: newService, containerDefinition: newContainerDefinition }; } function CreateCluster(scope, id, constructVpc, clientClusterProps) { const constructProps = { vpc: constructVpc }; return new ecs.Cluster(scope, id, defaults.consolidateProps(defaults.DefaultClusterProps(), clientClusterProps, constructProps)); } function CreateImage(scope, id, repositoryArn, imageVersion) { if (repositoryArn) { return ecs.ContainerImage.fromEcrRepository(ecr.Repository.fromRepositoryArn(scope, `${id}-container`, repositoryArn), imageVersion || "latest"); } else { throw new Error("Not Implemented - image without repo name and version"); } } function CreateTaskDefinition(scope, id, clientFargateTaskDefinitionProps, clientContainerDefinitionProps, constructContainerDefinitionProps) { const taskDefinitionProps = defaults.consolidateProps(defaults.DefaultFargateTaskDefinitionProps(), clientFargateTaskDefinitionProps); const taskDefinition = new ecs.FargateTaskDefinition(scope, `${id}-taskdef`, taskDefinitionProps); const defaultContainerDefinitionProps = defaults.consolidateProps(defaults.DefaultContainerDefinitionProps(), {}, { containerName: `${id}-container`, }); const containerDefinitionProps = defaults.consolidateProps(defaultContainerDefinitionProps, clientContainerDefinitionProps, constructContainerDefinitionProps); const containerDefinition = taskDefinition.addContainer(`${id}-container`, containerDefinitionProps); return { taskDefinition, containerDefinition }; } /** * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. */ function CheckFargateProps(props) { let errorMessages = ""; let errorFound = false; if (CheckForConflictingServiceProps(props)) { errorFound = true; errorMessages += "If you provide an existingFargateServiceObject, you cannot provide any props defining a new service\n"; } if (props.existingImageObject && (props.ecrImageVersion || props.ecrRepositoryArn)) { errorFound = true; errorMessages += "If you provide an existingImageObject then you cannot provide an ecrRepositoryArn nor ecrImageVersion\n"; } // Confirm no network information in Target Group Props if (props.targetGroupProps?.vpc) { errorFound = true; errorMessages += "Provide all VPC info at Construct level, not within targetGroupProps\n"; } if (props.fargateServiceProps?.taskDefinition) { errorFound = true; errorMessages += "The construct cannot accept an existing task definition in fargateServiceProps\n"; } if (props.fargateServiceProps?.cluster && props.clusterProps) { errorFound = true; errorMessages += "If you provide a cluster in fargateServiceProps then you cannot provide clusterProps\n"; } if (CheckForInvalidVpcs(props)) { errorFound = true; errorMessages += "Provide all VPC info at Construct level, not within clusterProps nor targetGroupProps\n"; } if ((props.existingFargateServiceObject || props.existingContainerDefinitionObject) && (!props.existingFargateServiceObject || !props.existingContainerDefinitionObject || !props.existingVpc)) { errorFound = true; errorMessages += "If an existing Service is indicated by supplying either existingFargateServiceObject or existingContainerDefinitionObject, then existingFargateServiceObject, existingContainerDefinitionObject, and existingVpc must all be provided\n"; } if (errorFound) { throw new Error(errorMessages); } } /** * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. */ function CheckForConflictingServiceProps(props) { if (props.existingFargateServiceObject && (props.existingImageObject || props.ecrImageVersion || props.containerDefinitionProps || props.fargateTaskDefinitionProps || props.ecrRepositoryArn || props.fargateServiceProps || props.clusterProps)) { return true; } return false; } /** * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. */ function CheckForInvalidVpcs(props) { if (props.clusterProps?.vpc || props.targetGroupProps?.vpc) { return true; } return false; } /** * @internal This is an internal core function and should not be called directly by Solutions Constructs clients. */ function getServiceVpcSecurityGroupIds(service) { const securityGroupIds = []; service.connections.securityGroups.forEach(element => securityGroupIds.push(element.securityGroupId)); return securityGroupIds; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFyZ2F0ZS1oZWxwZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJmYXJnYXRlLWhlbHBlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7Ozs7Ozs7O0dBV0c7O0FBZ0NILG9EQXlHQztBQXlFRCw4Q0EyREM7QUFLRCwwRUFhQztBQUtELGtEQUtDO0FBS0Qsc0VBTUM7QUE1U0QsMkNBQTJDO0FBQzNDLDJDQUEyQztBQUMzQywyQ0FBMkM7QUFDM0MsK0JBQStCO0FBQy9CLDBCQUFtQztBQWlCbkM7O0dBRUc7QUFDSCxTQUFnQixvQkFBb0IsQ0FDbEMsS0FBZ0IsRUFDaEIsRUFBVSxFQUNWLEtBQWdDO0lBRWhDLFFBQVEsQ0FBQyxxQkFBcUIsQ0FDNUIsS0FBSyxFQUNMLEtBQUssQ0FBQyxZQUFZLEVBQ2xCLFFBQVEsQ0FBQyxvQkFBb0IsQ0FBQyxPQUFPLENBQ3RDLENBQUM7SUFDRixRQUFRLENBQUMscUJBQXFCLENBQzVCLEtBQUssRUFDTCxLQUFLLENBQUMsWUFBWSxFQUNsQixRQUFRLENBQUMsb0JBQW9CLENBQUMsT0FBTyxDQUN0QyxDQUFDO0lBQ0YsUUFBUSxDQUFDLHFCQUFxQixDQUM1QixLQUFLLEVBQ0wsS0FBSyxDQUFDLFlBQVksRUFDbEIsUUFBUSxDQUFDLG9CQUFvQixDQUFDLEVBQUUsQ0FDakMsQ0FBQztJQUVGLE1BQU0saUNBQWlDLEdBQVEsRUFBRSxDQUFDO0lBQ2xELE1BQU0sc0NBQXNDLEdBQVEsRUFBRSxDQUFDO0lBRXZELElBQUksQ0FBQyxLQUFLLENBQUMseUJBQXlCLEVBQUUsT0FBTyxFQUFFLENBQUM7UUFDOUMsNEJBQTRCO1FBQzVCLHNDQUFzQyxDQUFDLE9BQU8sR0FBRyxhQUFhLENBQzVELEtBQUssRUFDTCxHQUFHLEVBQUUsVUFBVSxFQUNmLEtBQUssQ0FBQyxZQUFZLEVBQ2xCLEtBQUssQ0FBQyxrQkFBa0IsQ0FDekIsQ0FBQztJQUNKLENBQUM7SUFFRCw2QkFBNkI7SUFDN0IsSUFBSSxDQUFD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QUV0QyxPQUFPLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUM7SUFFdEcsT0FBTyxnQkFBZ0IsQ0FBQztBQUMxQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiAgQ29weXJpZ2h0IEFtYXpvbi5jb20sIEluYy4gb3IgaXRzIGFmZmlsaWF0ZXMuIEFsbCBSaWdodHMgUmVzZXJ2ZWQuXG4gKlxuICogIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIikuIFlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2VcbiAqICB3aXRoIHRoZSBMaWNlbnNlLiBBIGNvcHkgb2YgdGhlIExpY2Vuc2UgaXMgbG9jYXRlZCBhdFxuICpcbiAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXG4gKlxuICogIG9yIGluIHRoZSAnbGljZW5zZScgZmlsZSBhY2NvbXBhbnlpbmcgdGhpcyBmaWxlLiBUaGlzIGZpbGUgaXMgZGlzdHJpYnV0ZWQgb24gYW4gJ0FTIElTJyBCQVNJUywgV0lUSE9VVCBXQVJSQU5USUVTXG4gKiAgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZXhwcmVzcyBvciBpbXBsaWVkLiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnNcbiAqICBhbmQgbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gKi9cblxuLypcbiAqICBUaGUgZnVuY3Rpb25zIGZvdW5kIGhlcmUgaW4gdGhlIGNvcmUgbGlicmFyeSBhcmUgZm9yIGludGVybmFsIHVzZSBhbmQgY2FuIGJlIGNoYW5nZWRcbiAqICBvciByZW1vdmVkIG91dHNpZGUgb2YgYSBtYWpvciByZWxlYXNlLiBXZSByZWNvbW1lbmQgYWdhaW5zdCBjYWxsaW5nIHRoZW0gZGlyZWN0bHkgZnJvbSBjbGllbnQgY29kZS5cbiAqL1xuXG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tIFwiY29uc3RydWN0c1wiO1xuaW1wb3J0ICogYXMgZWMyIGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtZWMyXCI7XG5pbXBvcnQgKiBhcyBlY3MgZnJvbSBcImF3cy1jZGstbGliL2F3cy1lY3NcIjtcbmltcG9ydCAqIGFzIGVjciBmcm9tIFwiYXdzLWNkay1saWIvYXdzLWVjclwiO1xuaW1wb3J0ICogYXMgZGVmYXVsdHMgZnJvbSBcIi4uXCI7XG5pbXBvcnQgeyBvdmVycmlkZVByb3BzIH0gZnJvbSBcIi4uXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ3JlYXRlRmFyZ2F0ZVNlcnZpY2VSZXNwb25zZSB7XG4gIHJlYWRvbmx5IHNlcnZpY2U6IGVjcy5GYXJnYXRlU2VydmljZSxcbiAgcmVhZG9ubHkgY29udGFpbmVyRGVmaW5pdGlvbjogZWNzLkNvbnRhaW5lckRlZmluaXRpb25cbn1cblxuZXhwb3J0IGludGVyZmFjZSBDcmVhdGVGYXJnYXRlU2VydmljZVByb3BzIHtcbiAgcmVhZG9ubHkgY29uc3RydWN0VnBjOiBlYzIuSVZwYyxcbiAgcmVhZG9ubHkgY2xpZW50Q2x1c3RlclByb3BzPzogZWNzLkNsdXN0ZXJQcm9wcyxcbiAgcmVhZG9ubHkgZWNyUmVwb3NpdG9yeUFybj86IHN0cmluZyxcbiAgcmVhZG9ubHkgZWNySW1hZ2VWZXJzaW9uPzogc3RyaW5nLFxuICByZWFkb25seSBjbGllbnRGYXJnYXRlVGFza0RlZmluaXRpb25Qcm9wcz86IGVjcy5GYXJnYXRlVGFza0RlZmluaXRpb25Qcm9wcyB8IGFueSxcbiAgcmVhZG9ubHkgY2xpZW50Q29udGFpbmVyRGVmaW5pdGlvblByb3BzPzogZWNzLkNvbnRhaW5lckRlZmluaXRpb25Qcm9wcyB8IGFueSxcbiAgcmVhZG9ubHkgY2xpZW50RmFyZ2F0ZVNlcnZpY2VQcm9wcz86IGVjcy5GYXJnYXRlU2VydmljZVByb3BzIHwgYW55XG59XG5cbi8qKlxuICogQGludGVybmFsIFRoaXMgaXMgYW4gaW50ZXJuYWwgY29yZSBmdW5jdGlvbiBhbmQgc2hvdWxkIG5vdCBiZSBjYWxsZWQgZGlyZWN0bHkgYnkgU29sdXRpb25zIENvbnN0cnVjdHMgY2xpZW50cy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENyZWF0ZUZhcmdhdGVTZXJ2aWNlKFxuICBzY29wZTogQ29uc3RydWN0LFxuICBpZDogc3RyaW5nLFxuICBwcm9wczogQ3JlYXRlRmFyZ2F0ZVNlcnZpY2VQcm9wc1xuKTogQ3JlYXRlRmFyZ2F0ZVNlcnZpY2VSZXNwb25zZSB7XG4gIGRlZmF1bHRzLkFkZEF3c1NlcnZpY2VFbmRwb2ludChcbiAgICBzY29wZSxcbiAgICBwcm9wcy5jb25zdHJ1Y3RWcGMsXG4gICAgZGVmYXVsdHMuU2VydmljZUVuZHBvaW50VHlwZXMuRUNSX0FQSVxuICApO1xuICBkZWZhdWx0cy5BZGRBd3NTZXJ2aWNlRW5kcG9pbnQoXG4gICAgc2NvcGUsXG4gICAgcHJvcHMuY29uc3RydWN0VnBjLFxuICAgIGRlZmF1bHRzLlNlcnZpY2VFbmRwb2ludFR5cGVzLkVDUl9ES1JcbiAgKTtcbiAgZGVmYXVsdHMuQWRkQXdzU2VydmljZUVuZHBvaW50KFxuICAgIHNjb3BlLFxuICAgIHByb3BzLmNvbnN0cnVjdFZwYyxcbiAgICBkZWZhdWx0cy5TZXJ2aWNlRW5kcG9pbnRUeXBlcy5TM1xuICApO1xuXG4gIGNvbnN0IGNvbnN0cnVjdENvbnRhaW5lckRlZmluaXRpb25Qcm9wczogYW55ID0ge307XG4gIGNvbnN0IGNvbnN0cnVjdEZhcmdhdGVTZXJ2aWNlRGVmaW5pdGlvblByb3BzOiBhbnkgPSB7fTtcblxuICBpZiAoIXByb3BzLmNsaWVudEZhcmdhdGVTZXJ2aWNlUHJvcHM/LmNsdXN0ZXIpIHtcbiAgICAvLyBDb25zdHJ1Y3QgRmFyZ2F0ZSBTZXJ2aWNlXG4gICAgY29uc3RydWN0RmFyZ2F0ZVNlcnZpY2VEZWZpbml0aW9uUHJvcHMuY2x1c3RlciA9IENyZWF0ZUNsdXN0ZXIoXG4gICAgICBzY29wZSxcbiAgICAgIGAke2lkfS1jbHVzdGVyYCxcbiAgICAgIHByb3BzLmNvbnN0cnVjdFZwYyxcbiAgICAgIHByb3BzLmNsaWVudENsdXN0ZXJQcm9wc1xuICAgICk7XG4gIH1cblxuICAvLyBTZXQgdXAgdGhlIEZhcmdhdGUgc2VydmljZVxuICBpZiAoIXByb3BzLmNsaWVudENvbnRhaW5lckRlZmluaXRpb25Qcm9wcz8uaW1hZ2UpIHtcbiAgICBjb25zdHJ1Y3RDb250YWluZXJEZWZpbml0aW9uUHJvcHMuaW1hZ2UgPSBDcmVhdGVJbWFnZShcbiAgICAgIHNjb3BlLFxuICAgICAgaWQsXG4gICAgICBwcm9wcy5lY3JSZXBvc2l0b3J5QXJuLFxuICAgICAgcHJvcHMuZWNySW1hZ2VWZXJzaW9uXG4gICAgKTtcbiAgfVxuXG4gIC8vIENyZWF0ZSB0aGUgRmFyZ2F0ZSBTZXJ2aWNlXG4gIGNvbnN0IGNyZWF0ZVRhc2tEZWZpbml0aW9uUmVzcG9uc2UgPSBDcmVhdGVUYXNrRGVmaW5pdGlvbihcbiAgICBzY29wZSxcbiAgICBpZCxcbiAgICBwcm9wcy5jbGllbnRGYXJnYXRlVGFza0RlZmluaXRpb25Qcm9wcyxcbiAgICBwcm9wcy5jbGllbnRDb250YWluZXJEZWZpbml0aW9uUHJvcHMsXG4gICAgY29uc3RydWN0Q29udGFpbmVyRGVmaW5pdGlvblByb3BzXG4gICk7XG4gIGNvbnN0cnVjdEZhcmdhdGVTZXJ2aWNlRGVmaW5pdGlvblByb3BzLnRhc2tEZWZpbml0aW9uID0gY3JlYXRlVGFza0RlZmluaXRpb25SZXNwb25zZS50YXNrRGVmaW5pdGlvbjtcbiAgY29uc3QgbmV3Q29udGFpbmVyRGVmaW5pdGlvbiA9IGNyZWF0ZVRhc2tEZWZpbml0aW9uUmVzcG9uc2UuY29udGFpbmVyRGVmaW5pdGlvbjtcblxuICBpZiAoIXByb3BzLmNsaWVudEZhcmdhdGVTZXJ2aWNlUHJvcHM/LnZwY1N1Ym5ldHMpIHtcbiAgICBpZiAocHJvcHMuY29uc3RydWN0VnBjLmlzb2xhdGVkU3VibmV0cy5sZW5ndGgpIHtcbiAgICAgIGNvbnN0cnVjdEZhcmdhdGVTZXJ2aWNlRGVmaW5pdGlvblByb3BzLnZwY1N1Ym5ldHMgPSB7XG4gICAgICAgIHN1Ym5ldHM6IHByb3BzLmNvbnN0cnVjdFZwYy5pc29sYXRlZFN1Ym5ldHMsXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdHJ1Y3RGYXJnYXRlU2VydmljZURlZmluaXRpb25Qcm9wcy52cGNTdWJuZXRzID0ge1xuICAgICAgICBzdWJuZXRzOiBwcm9wcy5jb25zdHJ1Y3RWcGMucHJpdmF0ZVN1Ym5ldHMsXG4gICAgICB9O1xuICAgIH1cbiAgfVxuXG4gIGxldCBkZWZhdWx0RmFyZ2F0ZVNlcnZpY2VQcm9wcztcblxuICBpZiAoIXByb3BzLmNsaWVudEZhcmdhdGVTZXJ2aWNlUHJvcHM/LnNlY3VyaXR5R3JvdXBzKSB7XG4gICAgY29uc3Qgc2VydmljZVNlY3VyaXR5R3JvdXAgPSBuZXcgZWMyLlNlY3VyaXR5R3JvdXAoc2NvcGUsIGAke2lkfS1zZ2AsIHtcbiAgICAgIGFsbG93QWxsT3V0Ym91bmQ6IHRydWUsXG4gICAgICBkaXNhYmxlSW5saW5lUnVsZXM6IGZhbHNlLFxuICAgICAgdnBjOiBwcm9wcy5jb25zdHJ1Y3RWcGMsXG4gICAgICAvLyBXZSBhZGQgYSBkZXNjcmlwdGlvbiBoZXJlIHNvIHRoYXQgdGhpcyBTRyBjYW4gYmUgZWFzaWx5IGlkZW50aWZpZWQgaW4gdGVzdHNcbiAgICAgIGRlc2NyaXB0aW9uOiAnQ29uc3RydWN0IGNyZWF0ZWQgc2VjdXJpdHkgZ3JvdXAnXG4gICAgfSk7XG4gICAgZGVmYXVsdEZhcmdhdGVTZXJ2aWNlUHJvcHMgPSBvdmVycmlkZVByb3BzKGRlZmF1bHRzLkRlZmF1bHRGYXJnYXRlU2VydmljZVByb3BzKCksIHsgc2VjdXJpdHlHcm91cHM6IFsgc2VydmljZVNlY3VyaXR5R3JvdXAgXX0pO1xuICAgIGRlZmF1bHRzLmFkZENmblN1cHByZXNzUnVsZXMoc2VydmljZVNlY3VyaXR5R3JvdXAsIFtcbiAgICAgIHtcbiAgICAgICAgaWQ6ICdXNScsXG4gICAgICAgIHJlYXNvbjogJ0VncmVzcyBvZiAwLjAuMC4wLzAgaXMgZGVmYXVsdCBhbmQgZ2VuZXJhbGx5IGNvbnNpZGVyZWQgT0snLFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgaWQ6ICdXNDAnLFxuICAgICAgICByZWFzb246ICdFZ3Jlc3MgSVBQcm90b2NvbCBvZiAtMSBpcyBkZWZhdWx0IGFuZCBnZW5lcmFsbHkgY29uc2lkZXJlZCBPSycsXG4gICAgICB9XG4gICAgXSk7XG4gIH0gZWxzZSB7XG4gICAgZGVmYXVsdEZhcmdhdGVTZXJ2aWNlUHJvcHMgPSBkZWZhdWx0cy5EZWZhdWx0RmFyZ2F0ZVNlcnZpY2VQcm9wcygpO1xuICB9XG5cbiAgY29uc3QgZmFyZ2F0ZVNlcnZpY2VQcm9wcyA9IGRlZmF1bHRzLmNvbnNvbGlkYXRlUHJvcHMoXG4gICAgZGVmYXVsdEZhcmdhdGVTZXJ2aWNlUHJvcHMsXG4gICAgcHJvcHMuY2xpZW50RmFyZ2F0ZVNlcnZpY2VQcm9wcyxcbiAgICBjb25zdHJ1Y3RGYXJnYXRlU2VydmljZURlZmluaXRpb25Qcm9wc1xuICApO1xuXG4gIGNvbnN0IG5ld1NlcnZpY2UgPSBuZXcgZWNzLkZhcmdhdGVTZXJ2aWNlKFxuICAgIHNjb3BlLFxuICAgIGAke2lkfS1zZXJ2aWNlYCxcbiAgICBmYXJnYXRlU2VydmljZVByb3BzLFxuICApO1xuXG4gIHJldHVybiB7IHNlcnZpY2U6IG5ld1NlcnZpY2UsIGNvbnRhaW5lckRlZmluaXRpb246IG5ld0NvbnRhaW5lckRlZmluaXRpb24gfTtcbn1cblxuZnVuY3Rpb24gQ3JlYXRlQ2x1c3RlcihcbiAgc2NvcGU6IENvbnN0cnVjdCxcbiAgaWQ6IHN0cmluZyxcbiAgY29uc3RydWN0VnBjOiBlYzIuSVZwYyxcbiAgY2xpZW50Q2x1c3RlclByb3BzPzogZWNzLkNsdXN0ZXJQcm9wc1xuKTogZWNzLklDbHVzdGVyIHtcbiAgY29uc3QgY29uc3RydWN0UHJvcHMgPSB7IHZwYzogY29uc3RydWN0VnBjIH07XG4gIHJldHVybiBuZXcgZWNzLkNsdXN0ZXIoXG4gICAgc2NvcGUsXG4gICAgaWQsXG4gICAgZGVmYXVsdHMuY29uc29saWRhdGVQcm9wcyhcbiAgICAgIGRlZmF1bHRzLkRlZmF1bHRDbHVzdGVyUHJvcHMoKSxcbiAgICAgIGNsaWVudENsdXN0ZXJQcm9wcyxcbiAgICAgIGNvbnN0cnVjdFByb3BzXG4gICAgKVxuICApO1xufVxuXG5mdW5jdGlvbiBDcmVhdGVJbWFnZShcbiAgc2NvcGU6IENvbnN0cnVjdCxcbiAgaWQ6IHN0cmluZyxcbiAgcmVwb3NpdG9yeUFybj86IHN0cmluZyxcbiAgaW1hZ2VWZXJzaW9uPzogc3RyaW5nXG4pOiBlY3MuQ29udGFpbmVySW1hZ2Uge1xuICBpZiAocmVwb3NpdG9yeUFybikge1xuICAgIHJldHVybiBlY3MuQ29udGFpbmVySW1hZ2UuZnJvbUVjclJlcG9zaXRvcnkoXG4gICAgICBlY3IuUmVwb3NpdG9yeS5mcm9tUmVwb3NpdG9yeUFybihzY29wZSwgYCR7aWR9LWNvbnRhaW5lcmAsIHJlcG9zaXRvcnlBcm4pLFxuICAgICAgaW1hZ2VWZXJzaW9uIHx8IFwibGF0ZXN0XCJcbiAgICApO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBFcnJvcihcIk5vdCBJbXBsZW1lbnRlZCAtIGltYWdlIHdpdGhvdXQgcmVwbyBuYW1lIGFuZCB2ZXJzaW9uXCIpO1xuICB9XG59XG5cbmludGVyZmFjZSBDcmVhdGVUYXNrRGVmaW5pdGlvblJlc3BvbnNlIHtcbiAgdGFza0RlZmluaXRpb246IGVjcy5GYXJnYXRlVGFza0RlZmluaXRpb25cbiAgY29udGFpbmVyRGVmaW5pdGlvbjogZWNzLkNvbnRhaW5lckRlZmluaXRpb25cbn1cblxuZnVuY3Rpb24gQ3JlYXRlVGFza0RlZmluaXRpb24oXG4gIHNjb3BlOiBDb25zdHJ1Y3QsXG4gIGlkOiBzdHJpbmcsXG4gIGNsaWVudEZhcmdhdGVUYXNrRGVmaW5pdGlvblByb3BzPzogZWNzLkZhcmdhdGVUYXNrRGVmaW5pdGlvblByb3BzLFxuICBjbGllbnRDb250YWluZXJEZWZpbml0aW9uUHJvcHM/OiBlY3MuQ29udGFpbmVyRGVmaW5pdGlvblByb3BzLFxuICBjb25zdHJ1Y3RDb250YWluZXJEZWZpbml0aW9uUHJvcHM/OiBlY3MuQ29udGFpbmVyRGVmaW5pdGlvblByb3BzXG4pOiBDcmVhdGVUYXNrRGVmaW5pdGlvblJlc3BvbnNlIHtcbiAgY29uc3QgdGFza0RlZmluaXRpb25Qcm9wcyA9IGRlZmF1bHRzLmNvbnNvbGlkYXRlUHJvcHMoXG4gICAgZGVmYXVsdHMuRGVmYXVsdEZhcmdhdGVUYXNrRGVmaW5pdGlvblByb3BzKCksXG4gICAgY2xpZW50RmFyZ2F0ZVRhc2tEZWZpbml0aW9uUHJvcHNcbiAgKTtcbiAgY29uc3QgdGFza0RlZmluaXRpb24gPSBuZXcgZWNzLkZhcmdhdGVUYXNrRGVmaW5pdGlvbihcbiAgICBzY29wZSxcbiAgICBgJHtpZH0tdGFza2RlZmAsXG4gICAgdGFza0RlZmluaXRpb25Qcm9wc1xuICApO1xuXG4gIGNvbnN0IGRlZmF1bHRDb250YWluZXJEZWZpbml0aW9uUHJvcHMgPSBkZWZhdWx0cy5jb25zb2xpZGF0ZVByb3BzKGRlZmF1bHRzLkRlZmF1bHRDb250YWluZXJEZWZpbml0aW9uUHJvcHMoKSwge30sIHtcbiAgICBjb250YWluZXJOYW1lOiBgJHtpZH0tY29udGFpbmVyYCxcbiAgfSk7XG4gIGNvbnN0IGNvbnRhaW5lckRlZmluaXRpb25Qcm9wcyA9IGRlZmF1bHRzLmNvbnNvbGlkYXRlUHJvcHMoXG4gICAgZGVmYXVsdENvbnRhaW5lckRlZmluaXRpb25Qcm9wcyxcbiAgICBjbGllbnRDb250YWluZXJEZWZpbml0aW9uUHJvcHMsXG4gICAgY29uc3RydWN0Q29udGFpbmVyRGVmaW5pdGlvblByb3BzLFxuICApO1xuICBjb25zdCBjb250YWluZXJEZWZpbml0aW9uID0gdGFza0RlZmluaXRpb24uYWRkQ29udGFpbmVyKGAke2lkfS1jb250YWluZXJgLCBjb250YWluZXJEZWZpbml0aW9uUHJvcHMpO1xuICByZXR1cm4geyB0YXNrRGVmaW5pdGlvbiwgY29udGFpbmVyRGVmaW5pdGlvbiB9O1xufVxuXG4vKipcbiAqIEBpbnRlcm5hbCBUaGlzIGlzIGFuIGludGVybmFsIGNvcmUgZnVuY3Rpb24gYW5kIHNob3VsZCBub3QgYmUgY2FsbGVkIGRpcmVjdGx5IGJ5IFNvbHV0aW9ucyBDb25zdHJ1Y3RzIGNsaWVudHMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBDaGVja0ZhcmdhdGVQcm9wcyhwcm9wczogYW55KSB7XG4gIGxldCBlcnJvck1lc3NhZ2VzID0gXCJcIjtcbiAgbGV0IGVycm9yRm91bmQgPSBmYWxzZTtcblxuICBpZiAoQ2hlY2tGb3JDb25mbGljdGluZ1NlcnZpY2VQcm9wcyhwcm9wcykpIHtcbiAgICBlcnJvckZvdW5kID0gdHJ1ZTtcbiAgICBlcnJvck1lc3NhZ2VzICs9XG4gICAgICBcIklmIHlvdSBwcm92aWRlIGFuIGV4aXN0aW5nRmFyZ2F0ZVNlcnZpY2VPYmplY3QsIHlvdSBjYW5ub3QgcHJvdmlkZSBhbnkgcHJvcHMgZGVmaW5pbmcgYSBuZXcgc2VydmljZVxcblwiO1xuICB9XG5cbiAgaWYgKFxuICAgIHByb3BzLmV4aXN0aW5nSW1hZ2VPYmplY3QgJiZcbiAgICAocHJvcHMuZWNySW1hZ2VWZXJzaW9uIHx8IHByb3BzLmVjclJlcG9zaXRvcnlBcm4pXG4gICkge1xuICAgIGVycm9yRm91bmQgPSB0cnVlO1xuICAgIGVycm9yTWVzc2FnZXMgKz1cbiAgICAgIFwiSWYgeW91IHByb3ZpZGUgYW4gZXhpc3RpbmdJbWFnZU9iamVjdCB0aGVuIHlvdSBjYW5ub3QgcHJvdmlkZSBhbiBlY3JSZXBvc2l0b3J5QXJuIG5vciBlY3JJbWFnZVZlcnNpb25cXG5cIjtcbiAgfVxuXG4gIC8vIENvbmZpcm0gbm8gbmV0d29yayBpbmZvcm1hdGlvbiBpbiBUYXJnZXQgR3JvdXAgUHJvcHNcbiAgaWYgKHByb3BzLnRhcmdldEdyb3VwUHJvcHM/LnZwYykge1xuICAgIGVycm9yRm91bmQgPSB0cnVlO1xuICAgIGVycm9yTWVzc2FnZXMgKz1cbiAgICAgIFwiUHJvdmlkZSBhbGwgVlBDIGluZm8gYXQgQ29uc3RydWN0IGxldmVsLCBub3Qgd2l0aGluIHRhcmdldEdyb3VwUHJvcHNcXG5cIjtcbiAgfVxuXG4gIGlmIChwcm9wcy5mYXJnYXRlU2VydmljZVByb3BzPy50YXNrRGVmaW5pdGlvbikge1xuICAgIGVycm9yRm91bmQgPSB0cnVlO1xuICAgIGVycm9yTWVzc2FnZXMgKz1cbiAgICAgIFwiVGhlIGNvbnN0cnVjdCBjYW5ub3QgYWNjZXB0IGFuIGV4aXN0aW5nIHRhc2sgZGVmaW5pdGlvbiBpbiBmYXJnYXRlU2VydmljZVByb3BzXFxuXCI7XG4gIH1cblxuICBpZiAocHJvcHMuZmFyZ2F0ZVNlcnZpY2VQcm9wcz8uY2x1c3RlciAmJiBwcm9wcy5jbHVzdGVyUHJvcHMpIHtcbiAgICBlcnJvckZvdW5kID0gdHJ1ZTtcbiAgICBlcnJvck1lc3NhZ2VzICs9XG4gICAgICBcIklmIHlvdSBwcm92aWRlIGEgY2x1c3RlciBpbiBmYXJnYXRlU2VydmljZVByb3BzIHRoZW4geW91IGNhbm5vdCBwcm92aWRlIGNsdXN0ZXJQcm9wc1xcblwiO1xuICB9XG5cbiAgaWYgKENoZWNrRm9ySW52YWxpZFZwY3MocHJvcHMpKSB7XG4gICAgZXJyb3JGb3VuZCA9IHRydWU7XG4gICAgZXJyb3JNZXNzYWdlcyArPVxuICAgICAgXCJQcm92aWRlIGFsbCBWUEMgaW5mbyBhdCBDb25zdHJ1Y3QgbGV2ZWwsIG5vdCB3aXRoaW4gY2x1c3RlclByb3BzIG5vciB0YXJnZXRHcm91cFByb3BzXFxuXCI7XG4gIH1cblxuICBpZiAoXG4gICAgKHByb3BzLmV4aXN0aW5nRmFyZ2F0ZVNlcnZpY2VPYmplY3QgfHxcbiAgICAgIHByb3BzLmV4aXN0aW5nQ29udGFpbmVyRGVmaW5pdGlvbk9iamVjdCkgJiZcbiAgICAoIXByb3BzLmV4aXN0aW5nRmFyZ2F0ZVNlcnZpY2VPYmplY3QgfHxcbiAgICAgICFwcm9wcy5leGlzdGluZ0NvbnRhaW5lckRlZmluaXRpb25PYmplY3QgfHxcbiAgICAgICFwcm9wcy5leGlzdGluZ1ZwYylcbiAgKSB7XG4gICAgZXJyb3JGb3VuZCA9IHRydWU7XG4gICAgZXJyb3JNZXNzYWdlcyArPVxuICAgICAgXCJJZiBhbiBleGlzdGluZyBTZXJ2aWNlIGlzIGluZGljYXRlZCBieSBzdXBwbHlpbmcgZWl0aGVyIGV4aXN0aW5nRmFyZ2F0ZVNlcnZpY2VPYmplY3Qgb3IgZXhpc3RpbmdDb250YWluZXJEZWZpbml0aW9uT2JqZWN0LCB0aGVuIGV4aXN0aW5nRmFyZ2F0ZVNlcnZpY2VPYmplY3QsIGV4aXN0aW5nQ29udGFpbmVyRGVmaW5pdGlvbk9iamVjdCwgYW5kIGV4aXN0aW5nVnBjIG11c3QgYWxsIGJlIHByb3ZpZGVkXFxuXCI7XG4gIH1cblxuICBpZiAoZXJyb3JGb3VuZCkge1xuICAgIHRocm93IG5ldyBFcnJvcihlcnJvck1lc3NhZ2VzKTtcbiAgfVxufVxuXG4vKipcbiAqIEBpbnRlcm5hbCBUaGlzIGlzIGFuIGludGVybmFsIGNvcmUgZnVuY3Rpb24gYW5kIHNob3VsZCBub3QgYmUgY2FsbGVkIGRpcmVjdGx5IGJ5IFNvbHV0aW9ucyBDb25zdHJ1Y3RzIGNsaWVudHMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBDaGVja0ZvckNvbmZsaWN0aW5nU2VydmljZVByb3BzKHByb3BzOiBhbnkpOiBib29sZWFuIHtcbiAgaWYgKHByb3BzLmV4aXN0aW5nRmFyZ2F0ZVNlcnZpY2VPYmplY3QgJiZcbiAgICAocHJvcHMuZXhpc3RpbmdJbWFnZU9iamVjdCB8fFxuICAgICAgcHJvcHMuZWNySW1hZ2VWZXJzaW9uIHx8XG4gICAgICBwcm9wcy5jb250YWluZXJEZWZpbml0aW9uUHJvcHMgfHxcbiAgICAgIHByb3BzLmZhcmdhdGVUYXNrRGVmaW5pdGlvblByb3BzIHx8XG4gICAgICBwcm9wcy5lY3JSZXBvc2l0b3J5QXJuIHx8XG4gICAgICBwcm9wcy5mYXJnYXRlU2VydmljZVByb3BzIHx8XG4gICAgICBwcm9wcy5jbHVzdGVyUHJvcHMpXG4gICkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuLyoqXG4gKiBAaW50ZXJuYWwgVGhpcyBpcyBhbiBpbnRlcm5hbCBjb3JlIGZ1bmN0aW9uIGFuZCBzaG91bGQgbm90IGJlIGNhbGxlZCBkaXJlY3RseSBieSBTb2x1dGlvbnMgQ29uc3RydWN0cyBjbGllbnRzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gQ2hlY2tGb3JJbnZhbGlkVnBjcyhwcm9wczogYW55KTogYm9vbGVhbiB7XG4gIGlmIChwcm9wcy5jbHVzdGVyUHJvcHM/LnZwYyB8fCBwcm9wcy50YXJnZXRHcm91cFByb3BzPy52cGMpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG5cbi8qKlxuICogQGludGVybmFsIFRoaXMgaXMgYW4gaW50ZXJuYWwgY29yZSBmdW5jdGlvbiBhbmQgc2hvdWxkIG5vdCBiZSBjYWxsZWQgZGlyZWN0bHkgYnkgU29sdXRpb25zIENvbnN0cnVjdHMgY2xpZW50cy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFNlcnZpY2VWcGNTZWN1cml0eUdyb3VwSWRzKHNlcnZpY2U6IGVjcy5GYXJnYXRlU2VydmljZSk6IHN0cmluZ1tdIHtcbiAgY29uc3Qgc2VjdXJpdHlHcm91cElkczogc3RyaW5nW10gPSBbXTtcblxuICBzZXJ2aWNlLmNvbm5lY3Rpb25zLnNlY3VyaXR5R3JvdXBzLmZvckVhY2goZWxlbWVudCA9PiBzZWN1cml0eUdyb3VwSWRzLnB1c2goZWxlbWVudC5zZWN1cml0eUdyb3VwSWQpKTtcblxuICByZXR1cm4gc2VjdXJpdHlHcm91cElkcztcbn1cbiJdfQ==