UNPKG

eks-spot-blocks

Version:
222 lines 31 kB
"use strict"; var _a, _b; Object.defineProperty(exports, "__esModule", { value: true }); exports.SpotFleet = exports.EksSpotCluster = exports.InstanceInterruptionBehavior = exports.BlockDuration = void 0; const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const ec2 = require("@aws-cdk/aws-ec2"); const eks = require("@aws-cdk/aws-eks"); const iam = require("@aws-cdk/aws-iam"); const core_1 = require("@aws-cdk/core"); const launch_template_1 = require("./launch-template"); const user_data_1 = require("./user-data"); const DEFAULT_INSTANCE_TYPE = 't3.large'; /** * @stability stable */ var BlockDuration; (function (BlockDuration) { BlockDuration[BlockDuration["ONE_HOUR"] = 60] = "ONE_HOUR"; BlockDuration[BlockDuration["TWO_HOURS"] = 120] = "TWO_HOURS"; BlockDuration[BlockDuration["THREE_HOURS"] = 180] = "THREE_HOURS"; BlockDuration[BlockDuration["FOUR_HOURS"] = 240] = "FOUR_HOURS"; BlockDuration[BlockDuration["FIVE_HOURS"] = 300] = "FIVE_HOURS"; BlockDuration[BlockDuration["SIX_HOURS"] = 360] = "SIX_HOURS"; })(BlockDuration = exports.BlockDuration || (exports.BlockDuration = {})); /** * @stability stable */ var InstanceInterruptionBehavior; (function (InstanceInterruptionBehavior) { InstanceInterruptionBehavior["HIBERNATE"] = "hibernate"; InstanceInterruptionBehavior["STOP"] = "stop"; InstanceInterruptionBehavior["TERMINATE"] = "terminate"; })(InstanceInterruptionBehavior = exports.InstanceInterruptionBehavior || (exports.InstanceInterruptionBehavior = {})); /** * @stability stable */ class EksSpotCluster extends core_1.Resource { /** * @stability stable */ constructor(scope, id, props) { super(scope, id); // this.cluster = props.cluster; this.clusterVersion = props.clusterVersion; // use an existing vpc or create a new one this.vpc = this.node.tryGetContext('use_default_vpc') === '1' ? ec2.Vpc.fromLookup(this, 'Vpc', { isDefault: true }) : this.node.tryGetContext('use_vpc_id') ? ec2.Vpc.fromLookup(this, 'Vpc', { vpcId: this.node.tryGetContext('use_vpc_id') }) : new ec2.Vpc(this, 'Vpc', { maxAzs: 3, natGateways: 1 }); const clusterAdmin = new iam.Role(this, 'AdminRole', { assumedBy: new iam.AccountRootPrincipal(), }); this.cluster = new eks.Cluster(this, 'Cluster', { vpc: this.vpc, mastersRole: clusterAdmin, defaultCapacity: 0, version: this.clusterVersion, }); } /** * @stability stable */ addSpotFleet(id, props) { new SpotFleet(this, id, { cluster: this, ...props, }); } /** * @stability stable */ addDays(date, days) { date.setDate(date.getDate() + days); return date; } /** * @stability stable */ addHours(date, hours) { date.setHours(date.getHours() + hours); return date; } /** * @stability stable */ addMinutes(date, minutes) { date.setMinutes(date.getMinutes() + minutes); return date; } } exports.EksSpotCluster = EksSpotCluster; _a = JSII_RTTI_SYMBOL_1; EksSpotCluster[_a] = { fqn: "eks-spot-blocks.EksSpotCluster", version: "0.2.373" }; /** * @stability stable */ class SpotFleet extends core_1.Resource { /** * @stability stable */ constructor(scope, id, props) { var _c, _d, _e, _f, _g, _h, _j; super(scope, id, props); this.spotFleetId = id; this.clusterStack = props.cluster; this.launchTemplate = (_c = props.launchTemplate) !== null && _c !== void 0 ? _c : new launch_template_1.LaunchTemplate(); this.targetCapacity = props.targetCapacity; this.defaultInstanceType = (_d = props.defaultInstanceType) !== null && _d !== void 0 ? _d : new ec2.InstanceType(DEFAULT_INSTANCE_TYPE); // isntance role this.instanceRole = props.instanceRole || new iam.Role(this, 'InstanceRole', { roleName: core_1.PhysicalName.GENERATE_IF_NEEDED, assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'), }); this.instanceRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEKSWorkerNodePolicy')); this.instanceRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEKS_CNI_Policy')); this.instanceRole.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEC2ContainerRegistryReadOnly')); const instanceProfile = new iam.CfnInstanceProfile(this, 'InstanceProfile', { roles: [this.instanceRole.roleName], }); const sg = new ec2.SecurityGroup(this, 'SpotFleetSg', { vpc: this.clusterStack.cluster.vpc, }); // self rules sg.connections.allowInternally(ec2.Port.allTraffic()); // Cluster to:nodes rules sg.connections.allowFrom(this.clusterStack.cluster, ec2.Port.tcp(443)); sg.connections.allowFrom(this.clusterStack.cluster, ec2.Port.tcpRange(1025, 65535)); // Allow HTTPS from Nodes to Cluster sg.connections.allowTo(this.clusterStack.cluster, ec2.Port.tcp(443)); // Allow all node outbound traffic sg.connections.allowToAnyIpv4(ec2.Port.allTcp()); sg.connections.allowToAnyIpv4(ec2.Port.allUdp()); sg.connections.allowToAnyIpv4(ec2.Port.allIcmp()); const config = this.launchTemplate.bind(this); // const userData = renderAmazonLinuxUserData(cdk.Stack.of(this), this.cluster.clusterName, config.spotfleet); const userData = ec2.UserData.forLinux(); userData.addCommands(...user_data_1.renderAmazonLinuxUserData(core_1.Stack.of(this), this.clusterStack.cluster.clusterName, config.spotfleet)); this.defaultInstanceType = (_e = props.defaultInstanceType) !== null && _e !== void 0 ? _e : new ec2.InstanceType(DEFAULT_INSTANCE_TYPE); const imageId = (_f = props.customAmiId) !== null && _f !== void 0 ? _f : new eks.EksOptimizedImage({ nodeType: nodeTypeForInstanceType(this.defaultInstanceType), kubernetesVersion: props.cluster.clusterVersion.version, }).getImage(this).imageId; const lt = new ec2.CfnLaunchTemplate(this, 'LaunchTemplate', { launchTemplateData: { imageId, instanceType: this.defaultInstanceType.toString(), tagSpecifications: [ { resourceType: 'instance', tags: [ { key: 'Name', value: `${core_1.Stack.of(this).stackName}/Cluster/${this.spotFleetId}`, }, { key: `kubernetes.io/cluster/${this.clusterStack.cluster.clusterName}`, value: 'owned', }, ], }, ], instanceMarketOptions: { marketType: 'spot', spotOptions: { blockDurationMinutes: (_g = props.blockDuration) !== null && _g !== void 0 ? _g : BlockDuration.ONE_HOUR, instanceInterruptionBehavior: (_h = props.instanceInterruptionBehavior) !== null && _h !== void 0 ? _h : InstanceInterruptionBehavior.TERMINATE, }, }, // userData: cdk.Fn.base64(capacityAsg.userData.render()), userData: core_1.Fn.base64(userData.render()), securityGroupIds: sg.connections.securityGroups.map(m => m.securityGroupId), iamInstanceProfile: { arn: instanceProfile.attrArn, }, }, }); const spotFleetRole = new iam.Role(this, 'FleetRole', { assumedBy: new iam.ServicePrincipal('spotfleet.amazonaws.com'), managedPolicies: [ iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonEC2SpotFleetTaggingRole'), ], }); const overrides = []; for (const s of this.clusterStack.cluster.vpc.privateSubnets) { overrides.push({ subnetId: s.subnetId }); } new ec2.CfnSpotFleet(this, id, { spotFleetRequestConfigData: { launchTemplateConfigs: [ { launchTemplateSpecification: { launchTemplateId: lt.ref, version: lt.attrLatestVersionNumber, }, overrides, }, ], iamFleetRole: spotFleetRole.roleArn, targetCapacity: (_j = props.targetCapacity) !== null && _j !== void 0 ? _j : 1, validFrom: props.validFrom, validUntil: props.validUntil, terminateInstancesWithExpiration: props.terminateInstancesWithExpiration, }, }); this.clusterStack.cluster.awsAuth.addRoleMapping(this.instanceRole, { username: 'system:node:{{EC2PrivateDNSName}}', groups: [ 'system:bootstrappers', 'system:nodes', ], }); } } exports.SpotFleet = SpotFleet; _b = JSII_RTTI_SYMBOL_1; SpotFleet[_b] = { fqn: "eks-spot-blocks.SpotFleet", version: "0.2.373" }; const GPU_INSTANCETYPES = ['p2', 'p3', 'g4']; function nodeTypeForInstanceType(instanceType) { return GPU_INSTANCETYPES.includes(instanceType.toString().substring(0, 2)) ? eks.NodeType.GPU : eks.NodeType.STANDARD; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWtzLXNwb3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvZWtzLXNwb3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSx3Q0FBd0M7QUFDeEMsd0NBQXdDO0FBQ3hDLHdDQUF3QztBQUN4Qyx3Q0FBd0c7QUFDeEcsdURBQW9FO0FBQ3BFLDJDQUF3RDtBQUd4RCxNQUFNLHFCQUFxQixHQUFHLFVBQVUsQ0FBQzs7OztBQUV6QyxJQUFZLGFBT1g7QUFQRCxXQUFZLGFBQWE7SUFDdkIsMERBQWEsQ0FBQTtJQUNiLDZEQUFlLENBQUE7SUFDZixpRUFBaUIsQ0FBQTtJQUNqQiwrREFBZ0IsQ0FBQTtJQUNoQiwrREFBZ0IsQ0FBQTtJQUNoQiw2REFBZSxDQUFBO0FBQ2pCLENBQUMsRUFQVyxhQUFhLEdBQWIscUJBQWEsS0FBYixxQkFBYSxRQU94Qjs7OztBQUVELElBQVksNEJBSVg7QUFKRCxXQUFZLDRCQUE0QjtJQUN0Qyx1REFBdUIsQ0FBQTtJQUN2Qiw2Q0FBYSxDQUFBO0lBQ2IsdURBQXVCLENBQUE7QUFDekIsQ0FBQyxFQUpXLDRCQUE0QixHQUE1QixvQ0FBNEIsS0FBNUIsb0NBQTRCLFFBSXZDOzs7O0FBWUQsTUFBYSxjQUFlLFNBQVEsZUFBUTs7OztJQU8xQyxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQTBCO1FBQ2xFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsZ0NBQWdDO1FBQ2hDLElBQUksQ0FBQyxjQUFjLEdBQUcsS0FBSyxDQUFDLGNBQWMsQ0FBQztRQUUzQywwQ0FBMEM7UUFDMUMsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDO1lBQzdELEdBQUcsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFF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RTtZQUNsRSxRQUFRLEVBQUUsbUNBQW1DO1lBQzdDLE1BQU0sRUFBRTtnQkFDTixzQkFBc0I7Z0JBQ3RCLGNBQWM7YUFDZjtTQUNGLENBQUMsQ0FBQztJQUVMLENBQUM7O0FBM0lILDhCQTRJQzs7O0FBRUQsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7QUFFN0MsU0FBUyx1QkFBdUIsQ0FBQyxZQUE4QjtJQUM3RCxPQUFPLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQUMsUUFBUSxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUM7QUFDeEgsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGVjMiBmcm9tICdAYXdzLWNkay9hd3MtZWMyJztcbmltcG9ydCAqIGFzIGVrcyBmcm9tICdAYXdzLWNkay9hd3MtZWtzJztcbmltcG9ydCAqIGFzIGlhbSBmcm9tICdAYXdzLWNkay9hd3MtaWFtJztcbmltcG9ydCB7IFN0YWNrLCBTdGFja1Byb3BzLCBDb25zdHJ1Y3QsIFJlc291cmNlLCBSZXNvdXJjZVByb3BzLCBQaHlzaWNhbE5hbWUsIEZuIH0gZnJvbSAnQGF3cy1jZGsvY29yZSc7XG5pbXBvcnQgeyBMYXVuY2hUZW1wbGF0ZSwgSUxhdW5jaHRlbXBsYXRlIH0gZnJvbSAnLi9sYXVuY2gtdGVtcGxhdGUnO1xuaW1wb3J0IHsgcmVuZGVyQW1hem9uTGludXhVc2VyRGF0YSB9IGZyb20gJy4vdXNlci1kYXRhJztcblxuXG5jb25zdCBERUZBVUxUX0lOU1RBTkNFX1RZUEUgPSAndDMubGFyZ2UnO1xuXG5leHBvcnQgZW51bSBCbG9ja0R1cmF0aW9uIHtcbiAgT05FX0hPVVIgPSA2MCxcbiAgVFdPX0hPVVJTID0gMTIwLFxuICBUSFJFRV9IT1VSUyA9IDE4MCxcbiAgRk9VUl9IT1VSUyA9IDI0MCxcbiAgRklWRV9IT1VSUyA9IDMwMCxcbiAgU0lYX0hPVVJTID0gMzYwXG59XG5cbmV4cG9ydCBlbnVtIEluc3RhbmNlSW50ZXJydXB0aW9uQmVoYXZpb3Ige1xuICBISUJFUk5BVEUgPSAnaGliZXJuYXRlJyxcbiAgU1RPUCA9ICdzdG9wJyxcbiAgVEVSTUlOQVRFID0gJ3Rlcm1pbmF0ZSdcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFa3NTcG90Q2x1c3RlclByb3BzIGV4dGVuZHMgU3RhY2tQcm9wcyB7XG4gIHJlYWRvbmx5IGNsdXN0ZXJBdHRyaWJ1dGVzPzogZWtzLkNsdXN0ZXJBdHRyaWJ1dGVzO1xuICByZWFkb25seSBjbHVzdGVyVmVyc2lvbjogZWtzLkt1YmVybmV0ZXNWZXJzaW9uO1xuICByZWFkb25seSBpbnN0YW5jZVJvbGU/OiBpYW0uSVJvbGU7XG4gIHJlYWRvbmx5IGluc3RhbmNlSW50ZXJydXB0aW9uQmVoYXZpb3I/OiBJbnN0YW5jZUludGVycnVwdGlvbkJlaGF2aW9yO1xuICByZWFkb25seSBrdWJlY3RsRW5hYmxlZD86IGJvb2xlYW47XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXG4gIHJlYWRvbmx5IGN1c3RvbUFtaUlkPzogc3RyaW5nO1xufVxuXG5leHBvcnQgY2xhc3MgRWtzU3BvdENsdXN0ZXIgZXh0ZW5kcyBSZXNvdXJjZSB7XG4gIHJlYWRvbmx5IGNsdXN0ZXI6IGVrcy5DbHVzdGVyO1xuICByZWFkb25seSBjbHVzdGVyVmVyc2lvbjogZWtzLkt1YmVybmV0ZXNWZXJzaW9uO1xuICAvLyByZWFkb25seSBpbnN0YW5jZVJvbGU6IGlhbS5JUm9sZTtcbiAgLy8gcmVhZG9ubHkgaW5zdGFuY2VQcm9maWxlOiBpYW0uQ2ZuSW5zdGFuY2VQcm9maWxlO1xuICByZWFkb25seSB2cGM6IGVjMi5JVnBjO1xuXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBFa3NTcG90Q2x1c3RlclByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIC8vIHRoaXMuY2x1c3RlciA9IHByb3BzLmNsdXN0ZXI7XG4gICAgdGhpcy5jbHVzdGVyVmVyc2lvbiA9IHByb3BzLmNsdXN0ZXJWZXJzaW9uO1xuXG4gICAgLy8gdXNlIGFuIGV4aXN0aW5nIHZwYyBvciBjcmVhdGUgYSBuZXcgb25lXG4gICAgdGhpcy52cGMgPSB0aGlzLm5vZGUudHJ5R2V0Q29udGV4dCgndXNlX2RlZmF1bHRfdnBjJykgPT09ICcxJyA/XG4gICAgICBlYzIuVnBjLmZyb21Mb29rdXAodGhpcywgJ1ZwYycsIHsgaXNEZWZhdWx0OiB0cnVlIH0pIDpcbiAgICAgIHRoaXMubm9kZS50cnlHZXRDb250ZXh0KCd1c2VfdnBjX2lkJykgP1xuICAgICAgICBlYzIuVnBjLmZyb21Mb29rdXAodGhpcywgJ1ZwYycsIHsgdnBjSWQ6IHRoaXMubm9kZS50cnlHZXRDb250ZXh0KCd1c2VfdnBjX2lkJykgfSkgOlxuICAgICAgICBuZXcgZWMyLlZwYyh0aGlzLCAnVnBjJywgeyBtYXhBenM6IDMsIG5hdEdhdGV3YXlzOiAxIH0pO1xuXG4gICAgY29uc3QgY2x1c3RlckFkbWluID0gbmV3IGlhbS5Sb2xlKHRoaXMsICdBZG1pblJvbGUnLCB7XG4gICAgICBhc3N1bWVkQnk6IG5ldyBpYW0uQWNjb3VudFJvb3RQcmluY2lwYWwoKSxcbiAgICB9KTtcblxuICAgIHRoaXMuY2x1c3Rlcj0gbmV3IGVrcy5DbHVzdGVyKHRoaXMsICdDbHVzdGVyJywge1xuICAgICAgdnBjOiB0aGlzLnZwYyxcbiAgICAgIG1hc3RlcnNSb2xlOiBjbHVzdGVyQWRtaW4sXG4gICAgICBkZWZhdWx0Q2FwYWNpdHk6IDAsXG4gICAgICB2ZXJzaW9uOiB0aGlzLmNsdXN0ZXJWZXJzaW9uLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGFkZFNwb3RGbGVldChpZDogc3RyaW5nLCBwcm9wczogQmFzZVNwb3RGbGVldFByb3BzKSB7XG4gICAgbmV3IFNwb3RGbGVldCh0aGlzLCBpZCwge1xuICAgICAgY2x1c3RlcjogdGhpcyxcbiAgICAgIC4uLnByb3BzLFxuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGFkZERheXMoZGF0ZTogRGF0ZSwgZGF5czogbnVtYmVyKTogRGF0ZSB7XG4gICAgZGF0ZS5zZXREYXRlKGRhdGUuZ2V0RGF0ZSgpICsgZGF5cyk7XG4gICAgcmV0dXJuIGRhdGU7XG4gIH1cblxuICBwdWJsaWMgYWRkSG91cnMoZGF0ZTogRGF0ZSwgaG91cnM6IG51bWJlcik6IERhdGUge1xuICAgIGRhdGUuc2V0SG91cnMoZGF0ZS5nZXRIb3VycygpICsgaG91cnMpO1xuICAgIHJldHVybiBkYXRlO1xuICB9XG5cbiAgcHVibGljIGFkZE1pbnV0ZXMoZGF0ZTogRGF0ZSwgbWludXRlczogbnVtYmVyKTogRGF0ZSB7XG4gICAgZGF0ZS5zZXRNaW51dGVzKGRhdGUuZ2V0TWludXRlcygpICsgbWludXRlcyk7XG4gICAgcmV0dXJuIGRhdGU7XG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBCYXNlU3BvdEZsZWV0UHJvcHMgZXh0ZW5kcyBSZXNvdXJjZVByb3BzIHtcbiAgcmVhZG9ubHkgZGVmYXVsdEluc3RhbmNlVHlwZT86IGVjMi5JbnN0YW5jZVR5cGU7XG4gIHJlYWRvbmx5IGJsb2NrRHVyYXRpb24/OiBCbG9ja0R1cmF0aW9uO1xuICByZWFkb25seSBpbnN0YW5jZUludGVycnVwdGlvbkJlaGF2aW9yID86IEluc3RhbmNlSW50ZXJydXB0aW9uQmVoYXZpb3I7XG4gIHJlYWRvbmx5IGluc3RhbmNlUm9sZT86IGlhbS5Sb2xlO1xuICByZWFkb25seSB0YXJnZXRDYXBhY2l0eT86IG51bWJlcjtcbiAgcmVhZG9ubHkgbWFwUm9sZT86IGJvb2xlYW47XG4gIHJlYWRvbmx5IGJvb3RzdHJhcEVuYWJsZWQ/OiBib29sZWFuO1xuICByZWFkb25seSB2YWxpZEZyb20/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHZhbGlkVW50aWw/OiBzdHJpbmc7XG4gIHJlYWRvbmx5IHRlcm1pbmF0ZUluc3RhbmNlc1dpdGhFeHBpcmF0aW9uPzogYm9vbGVhbjtcbiAgcmVhZG9ubHkgY3VzdG9tQW1pSWQ/OiBzdHJpbmc7XG59XG5cblxuZXhwb3J0IGludGVyZmFjZSBTcG90RmxlZXRQcm9wcyBleHRlbmRzIEJhc2VTcG90RmxlZXRQcm9wcyB7XG4gIHJlYWRvbmx5IGNsdXN0ZXI6IEVrc1Nwb3RDbHVzdGVyO1xuICByZWFkb25seSBsYXVuY2hUZW1wbGF0ZT86IElMYXVuY2h0ZW1wbGF0ZTtcbn1cblxuZXhwb3J0IGNsYXNzIFNwb3RGbGVldCBleHRlbmRzIFJlc291cmNlIHtcbiAgcmVhZG9ubHkgaW5zdGFuY2VSb2xlOiBpYW0uSVJvbGU7XG4gIHJlYWRvbmx5IGNsdXN0ZXJTdGFjazogRWtzU3BvdENsdXN0ZXI7XG4gIHJlYWRvbmx5IGRlZmF1bHRJbnN0YW5jZVR5cGU6IGVjMi5JbnN0YW5jZVR5cGU7XG4gIHJlYWRvbmx5IHRhcmdldENhcGFjaXR5PzogbnVtYmVyO1xuICByZWFkb25seSBzcG90RmxlZXRJZDogc3RyaW5nO1xuICByZWFkb25seSBsYXVuY2hUZW1wbGF0ZTogSUxhdW5jaHRlbXBsYXRlO1xuXG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgcHJvcHM6IFNwb3RGbGVldFByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkLCBwcm9wcyk7XG5cbiAgICB0aGlzLnNwb3RGbGVldElkID0gaWQ7XG4gICAgdGhpcy5jbHVzdGVyU3RhY2sgPSBwcm9wcy5jbHVzdGVyO1xuICAgIHRoaXMubGF1bmNoVGVtcGxhdGUgPSBwcm9wcy5sYXVuY2hUZW1wbGF0ZSA/PyBuZXcgTGF1bmNoVGVtcGxhdGUoKTtcbiAgICB0aGlzLnRhcmdldENhcGFjaXR5ID0gcHJvcHMudGFyZ2V0Q2FwYWNpdHk7XG4gICAgdGhpcy5kZWZhdWx0SW5zdGFuY2VUeXBlID0gcHJvcHMuZGVmYXVsdEluc3RhbmNlVHlwZSA/PyBuZXcgZWMyLkluc3RhbmNlVHlwZShERUZBVUxUX0lOU1RBTkNFX1RZUEUpO1xuXG4gICAgLy8gaXNudGFuY2Ugcm9sZVxuICAgIHRoaXMuaW5zdGFuY2VSb2xlID0gcHJvcHMuaW5zdGFuY2VSb2xlIHx8IG5ldyBpYW0uUm9sZSh0aGlzLCAnSW5zdGFuY2VSb2xlJywge1xuICAgICAgcm9sZU5hbWU6IFBoeXNpY2FsTmFtZS5HRU5FUkFURV9JRl9ORUVERUQsXG4gICAgICBhc3N1bWVkQnk6IG5ldyBpYW0uU2VydmljZVByaW5jaXBhbCgnZWMyLmFtYXpvbmF3cy5jb20nKSxcbiAgICB9KTtcblxuICAgIHRoaXMuaW5zdGFuY2VSb2xlLmFkZE1hbmFnZWRQb2xpY3koaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKCdBbWF6b25FS1NXb3JrZXJOb2RlUG9saWN5JykpO1xuICAgIHRoaXMuaW5zdGFuY2VSb2xlLmFkZE1hbmFnZWRQb2xpY3koaWFtLk1hbmFnZWRQb2xpY3kuZnJvbUF3c01hbmFnZWRQb2xpY3lOYW1lKCdBbWF6b25FS1NfQ05JX1BvbGljeScpKTtcbiAgICB0aGlzLmluc3RhbmNlUm9sZS5hZGRNYW5hZ2VkUG9saWN5KGlhbS5NYW5hZ2VkUG9saWN5LmZyb21Bd3NNYW5hZ2VkUG9saWN5TmFtZSgnQW1hem9uRUMyQ29udGFpbmVyUmVnaXN0cnlSZWFkT25seScpKTtcblxuICAgIGNvbnN0IGluc3RhbmNlUHJvZmlsZSA9IG5ldyBpYW0uQ2ZuSW5zdGFuY2VQcm9maWxlKHRoaXMsICdJbnN0YW5jZVByb2ZpbGUnLCB7XG4gICAgICByb2xlczogW3RoaXMuaW5zdGFuY2VSb2xlLnJvbGVOYW1lXSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHNnID0gbmV3IGVjMi5TZWN1cml0eUdyb3VwKHRoaXMsICdTcG90RmxlZXRTZycsIHtcbiAgICAgIHZwYzogdGhpcy5jbHVzdGVyU3RhY2suY2x1c3Rlci52cGMsXG4gICAgfSk7XG5cbiAgICAvLyBzZWxmIHJ1bGVzXG4gICAgc2cuY29ubmVjdGlvbnMuYWxsb3dJbnRlcm5hbGx5KGVjMi5Qb3J0LmFsbFRyYWZmaWMoKSk7XG5cbiAgICAvLyBDbHVzdGVyIHRvOm5vZGVzIHJ1bGVzXG4gICAgc2cuY29ubmVjdGlvbnMuYWxsb3dGcm9tKHRoaXMuY2x1c3RlclN0YWNrLmNsdXN0ZXIsIGVjMi5Qb3J0LnRjcCg0NDMpKTtcbiAgICBzZy5jb25uZWN0aW9ucy5hbGxvd0Zyb20odGhpcy5jbHVzdGVyU3RhY2suY2x1c3RlciwgZWMyLlBvcnQudGNwUmFuZ2UoMTAyNSwgNjU1MzUpKTtcblxuICAgIC8vIEFsbG93IEhUVFBTIGZyb20gTm9kZXMgdG8gQ2x1c3RlclxuICAgIHNnLmNvbm5lY3Rpb25zLmFsbG93VG8odGhpcy5jbHVzdGVyU3RhY2suY2x1c3RlciwgZWMyLlBvcnQudGNwKDQ0MykpO1xuXG4gICAgLy8gQWxsb3cgYWxsIG5vZGUgb3V0Ym91bmQgdHJhZmZpY1xuICAgIHNnLmNvbm5lY3Rpb25zLmFsbG93VG9BbnlJcHY0KGVjMi5Qb3J0LmFsbFRjcCgpKTtcbiAgICBzZy5jb25uZWN0aW9ucy5hbGxvd1RvQW55SXB2NChlYzIuUG9ydC5hbGxVZHAoKSk7XG4gICAgc2cuY29ubmVjdGlvbnMuYWxsb3dUb0FueUlwdjQoZWMyLlBvcnQuYWxsSWNtcCgpKTtcblxuICAgIGNvbnN0IGNvbmZpZyA9IHRoaXMubGF1bmNoVGVtcGxhdGUuYmluZCh0aGlzKTtcblxuICAgIC8vIGNvbnN0IHVzZXJEYXRhID0gcmVuZGVyQW1hem9uTGludXhVc2VyRGF0YShjZGsuU3RhY2sub2YodGhpcyksIHRoaXMuY2x1c3Rlci5jbHVzdGVyTmFtZSwgY29uZmlnLnNwb3RmbGVldCk7XG4gICAgY29uc3QgdXNlckRhdGEgPSBlYzIuVXNlckRhdGEuZm9yTGludXgoKTtcbiAgICB1c2VyRGF0YS5hZGRDb21tYW5kcyguLi5yZW5kZXJBbWF6b25MaW51eFVzZXJEYXRhKFN0YWNrLm9mKHRoaXMpLCB0aGlzLmNsdXN0ZXJTdGFjay5jbHVzdGVyLmNsdXN0ZXJOYW1lLCBjb25maWcuc3BvdGZsZWV0KSk7XG5cbiAgICB0aGlzLmRlZmF1bHRJbnN0YW5jZVR5cGUgPSBwcm9wcy5kZWZhdWx0SW5zdGFuY2VUeXBlID8/IG5ldyBlYzIuSW5zdGFuY2VUeXBlKERFRkFVTFRfSU5TVEFOQ0VfVFlQRSk7XG5cbiAgICBjb25zdCBpbWFnZUlkID0gcHJvcHMuY3VzdG9tQW1pSWQgPz8gbmV3IGVrcy5Fa3NPcHRpbWl6ZWRJbWFnZSh7XG4gICAgICBub2RlVHlwZTogbm9kZVR5cGVGb3JJbnN0YW5jZVR5cGUodGhpcy5kZWZhdWx0SW5zdGFuY2VUeXBlKSxcbiAgICAgIGt1YmVybmV0ZXNWZXJzaW9uOiBwcm9wcy5jbHVzdGVyLmNsdXN0ZXJWZXJzaW9uLnZlcnNpb24sXG4gICAgfSkuZ2V0SW1hZ2UodGhpcykuaW1hZ2VJZDtcblxuICAgIGNvbnN0IGx0ID0gbmV3IGVjMi5DZm5MYXVuY2hUZW1wbGF0ZSh0aGlzLCAnTGF1bmNoVGVtcGxhdGUnLCB7XG4gICAgICBsYXVuY2hUZW1wbGF0ZURhdGE6IHtcbiAgICAgICAgaW1hZ2VJZCxcbiAgICAgICAgaW5zdGFuY2VUeXBlOiB0aGlzLmRlZmF1bHRJbnN0YW5jZVR5cGUudG9TdHJpbmcoKSxcbiAgICAgICAgdGFnU3BlY2lmaWNhdGlvbnM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICByZXNvdXJjZVR5cGU6ICdpbnN0YW5jZScsXG4gICAgICAgICAgICB0YWdzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBrZXk6ICdOYW1lJyxcbiAgICAgICAgICAgICAgICB2YWx1ZTogYCR7U3RhY2sub2YodGhpcykuc3RhY2tOYW1lfS9DbHVzdGVyLyR7dGhpcy5zcG90RmxlZXRJZH1gLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAga2V5OiBga3ViZXJuZXRlcy5pby9jbHVzdGVyLyR7dGhpcy5jbHVzdGVyU3RhY2suY2x1c3Rlci5jbHVzdGVyTmFtZX1gLFxuICAgICAgICAgICAgICAgIHZhbHVlOiAnb3duZWQnLFxuICAgICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBdLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICAgIGluc3RhbmNlTWFya2V0T3B0aW9uczoge1xuICAgICAgICAgIG1hcmtldFR5cGU6ICdzcG90JyxcbiAgICAgICAgICBzcG90T3B0aW9uczoge1xuICAgICAgICAgICAgYmxvY2tEdXJhdGlvbk1pbnV0ZXM6IHByb3BzLmJsb2NrRHVyYXRpb24gPz8gQmxvY2tEdXJhdGlvbi5PTkVfSE9VUixcbiAgICAgICAgICAgIGluc3RhbmNlSW50ZXJydXB0aW9uQmVoYXZpb3I6IHByb3BzLmluc3RhbmNlSW50ZXJydXB0aW9uQmVoYXZpb3IgPz8gSW5zdGFuY2VJbnRlcnJ1cHRpb25CZWhhdmlvci5URVJNSU5BVEUsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgLy8gdXNlckRhdGE6IGNkay5Gbi5iYXNlNjQoY2FwYWNpdHlBc2cudXNlckRhdGEucmVuZGVyKCkpLFxuICAgICAgICB1c2VyRGF0YTogRm4uYmFzZTY0KHVzZXJEYXRhLnJlbmRlcigpKSxcbiAgICAgICAgc2VjdXJpdHlHcm91cElkczogc2cuY29ubmVjdGlvbnMuc2VjdXJpdHlHcm91cHMubWFwKG0gPT4gbS5zZWN1cml0eUdyb3VwSWQpLFxuICAgICAgICBpYW1JbnN0YW5jZVByb2ZpbGU6IHtcbiAgICAgICAgICBhcm46IGluc3RhbmNlUHJvZmlsZS5hdHRyQXJuLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHNwb3RGbGVldFJvbGUgPSBuZXcgaWFtLlJvbGUodGhpcywgJ0ZsZWV0Um9sZScsIHtcbiAgICAgIGFzc3VtZWRCeTogbmV3IGlhbS5TZXJ2aWNlUHJpbmNpcGFsKCdzcG90ZmxlZXQuYW1hem9uYXdzLmNvbScpLFxuICAgICAgbWFuYWdlZFBvbGljaWVzOiBbXG4gICAgICAgIGlhbS5NYW5hZ2VkUG9saWN5LmZyb21Bd3NNYW5hZ2VkUG9saWN5TmFtZSgnc2VydmljZS1yb2xlL0FtYXpvbkVDMlNwb3RGbGVldFRhZ2dpbmdSb2xlJyksXG4gICAgICBdLFxuICAgIH0pO1xuXG5cbiAgICBjb25zdCBvdmVycmlkZXMgPSBbXTtcbiAgICBmb3IgKGNvbnN0IHMgb2YgdGhpcy5jbHVzdGVyU3RhY2suY2x1c3Rlci52cGMucHJpdmF0ZVN1Ym5ldHMpIHtcbiAgICAgIG92ZXJyaWRlcy5wdXNoKHsgc3VibmV0SWQ6IHMuc3VibmV0SWQgfSk7XG4gICAgfVxuICAgIG5ldyBlYzIuQ2ZuU3BvdEZsZWV0KHRoaXMsIGlkLCB7XG4gICAgICBzcG90RmxlZXRSZXF1ZXN0Q29uZmlnRGF0YToge1xuICAgICAgICBsYXVuY2hUZW1wbGF0ZUNvbmZpZ3M6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBsYXVuY2hUZW1wbGF0ZVNwZWNpZmljYXRpb246IHtcbiAgICAgICAgICAgICAgbGF1bmNoVGVtcGxhdGVJZDogbHQucmVmLFxuICAgICAgICAgICAgICB2ZXJzaW9uOiBsdC5hdHRyTGF0ZXN0VmVyc2lvbk51bWJlcixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvdmVycmlkZXMsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgICAgaWFtRmxlZXRSb2xlOiBzcG90RmxlZXRSb2xlLnJvbGVBcm4sXG4gICAgICAgIHRhcmdldENhcGFjaXR5OiBwcm9wcy50YXJnZXRDYXBhY2l0eSA/PyAxLFxuICAgICAgICB2YWxpZEZyb206IHByb3BzLnZhbGlkRnJvbSxcbiAgICAgICAgdmFsaWRVbnRpbDogcHJvcHMudmFsaWRVbnRpbCxcbiAgICAgICAgdGVybWluYXRlSW5zdGFuY2VzV2l0aEV4cGlyYXRpb246IHByb3BzLnRlcm1pbmF0ZUluc3RhbmNlc1dpdGhFeHBpcmF0aW9uLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIHRoaXMuY2x1c3RlclN0YWNrLmNsdXN0ZXIuYXdzQXV0aC5hZGRSb2xlTWFwcGluZyh0aGlzLmluc3RhbmNlUm9sZSwge1xuICAgICAgdXNlcm5hbWU6ICdzeXN0ZW06bm9kZTp7e0VDMlByaXZhdGVETlNOYW1lfX0nLFxuICAgICAgZ3JvdXBzOiBbXG4gICAgICAgICdzeXN0ZW06Ym9vdHN0cmFwcGVycycsXG4gICAgICAgICdzeXN0ZW06bm9kZXMnLFxuICAgICAgXSxcbiAgICB9KTtcblxuICB9XG59XG5cbmNvbnN0IEdQVV9JTlNUQU5DRVRZUEVTID0gWydwMicsICdwMycsICdnNCddO1xuXG5mdW5jdGlvbiBub2RlVHlwZUZvckluc3RhbmNlVHlwZShpbnN0YW5jZVR5cGU6IGVjMi5JbnN0YW5jZVR5cGUpIHtcbiAgcmV0dXJuIEdQVV9JTlNUQU5DRVRZUEVTLmluY2x1ZGVzKGluc3RhbmNlVHlwZS50b1N0cmluZygpLnN1YnN0cmluZygwLCAyKSkgPyBla3MuTm9kZVR5cGUuR1BVIDogZWtzLk5vZGVUeXBlLlNUQU5EQVJEO1xufVxuIl19