UNPKG

32.9 kBJavaScriptView Raw
1"use strict";
2var _a, _b;
3Object.defineProperty(exports, "__esModule", { value: true });
4exports.BuiltInAttributes = exports.Ec2Service = void 0;
5const jsiiDeprecationWarnings = require("../../.warnings.jsii.js");
6const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
7const ec2 = require("@aws-cdk/aws-ec2");
8const core_1 = require("@aws-cdk/core");
9const base_service_1 = require("../base/base-service");
10const from_service_attributes_1 = require("../base/from-service-attributes");
11const task_definition_1 = require("../base/task-definition");
12/**
13 * This creates a service using the EC2 launch type on an ECS cluster.
14 *
15 * @resource AWS::ECS::Service
16 */
17class Ec2Service extends base_service_1.BaseService {
18 /**
19 * Constructs a new instance of the Ec2Service class.
20 */
21 constructor(scope, id, props) {
22 var _c;
23 try {
24 jsiiDeprecationWarnings._aws_cdk_aws_ecs_Ec2ServiceProps(props);
25 }
26 catch (error) {
27 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
28 Error.captureStackTrace(error, this.constructor);
29 }
30 throw error;
31 }
32 if (props.daemon && props.desiredCount !== undefined) {
33 throw new Error('Daemon mode launches one task on every instance. Don\'t supply desiredCount.');
34 }
35 if (props.daemon && props.maxHealthyPercent !== undefined && props.maxHealthyPercent !== 100) {
36 throw new Error('Maximum percent must be 100 for daemon mode.');
37 }
38 if (props.minHealthyPercent !== undefined && props.maxHealthyPercent !== undefined && props.minHealthyPercent >= props.maxHealthyPercent) {
39 throw new Error('Minimum healthy percent must be less than maximum healthy percent.');
40 }
41 if (!props.taskDefinition.isEc2Compatible) {
42 throw new Error('Supplied TaskDefinition is not configured for compatibility with EC2');
43 }
44 if (props.securityGroup !== undefined && props.securityGroups !== undefined) {
45 throw new Error('Only one of SecurityGroup or SecurityGroups can be populated.');
46 }
47 super(scope, id, {
48 ...props,
49 desiredCount: props.desiredCount,
50 maxHealthyPercent: props.daemon && props.maxHealthyPercent === undefined ? 100 : props.maxHealthyPercent,
51 minHealthyPercent: props.daemon && props.minHealthyPercent === undefined ? 0 : props.minHealthyPercent,
52 launchType: base_service_1.LaunchType.EC2,
53 enableECSManagedTags: props.enableECSManagedTags,
54 }, {
55 cluster: props.cluster.clusterName,
56 taskDefinition: ((_c = props.deploymentController) === null || _c === void 0 ? void 0 : _c.type) === base_service_1.DeploymentControllerType.EXTERNAL ? undefined : props.taskDefinition.taskDefinitionArn,
57 placementConstraints: core_1.Lazy.any({ produce: () => this.constraints }, { omitEmptyArray: true }),
58 placementStrategies: core_1.Lazy.any({ produce: () => this.strategies }, { omitEmptyArray: true }),
59 schedulingStrategy: props.daemon ? 'DAEMON' : 'REPLICA',
60 }, props.taskDefinition);
61 this.constraints = [];
62 this.strategies = [];
63 this.daemon = props.daemon || false;
64 let securityGroups;
65 if (props.securityGroup !== undefined) {
66 securityGroups = [props.securityGroup];
67 }
68 else if (props.securityGroups !== undefined) {
69 securityGroups = props.securityGroups;
70 }
71 if (props.taskDefinition.networkMode === task_definition_1.NetworkMode.AWS_VPC) {
72 this.configureAwsVpcNetworkingWithSecurityGroups(props.cluster.vpc, props.assignPublicIp, props.vpcSubnets, securityGroups);
73 }
74 else {
75 // Either None, Bridge or Host networking. Copy SecurityGroups from ASG.
76 // We have to be smart here -- by default future Security Group rules would be created
77 // in the Cluster stack. However, if the Cluster is in a different stack than us,
78 // that will lead to a cyclic reference (we point to that stack for the cluster name,
79 // but that stack will point to the ALB probably created right next to us).
80 //
81 // In that case, reference the same security groups but make sure new rules are
82 // created in the current scope (i.e., this stack)
83 validateNoNetworkingProps(props);
84 this.connections.addSecurityGroup(...securityGroupsInThisStack(this, props.cluster.connections.securityGroups));
85 }
86 this.addPlacementConstraints(...props.placementConstraints || []);
87 this.addPlacementStrategies(...props.placementStrategies || []);
88 this.node.addValidation({
89 validate: () => !this.taskDefinition.defaultContainer ? ['A TaskDefinition must have at least one essential container'] : [],
90 });
91 }
92 /**
93 * Imports from the specified service ARN.
94 */
95 static fromEc2ServiceArn(scope, id, ec2ServiceArn) {
96 class Import extends core_1.Resource {
97 constructor() {
98 super(...arguments);
99 this.serviceArn = ec2ServiceArn;
100 this.serviceName = core_1.Stack.of(scope).splitArn(ec2ServiceArn, core_1.ArnFormat.SLASH_RESOURCE_NAME).resourceName;
101 }
102 }
103 return new Import(scope, id);
104 }
105 /**
106 * Imports from the specified service attrributes.
107 */
108 static fromEc2ServiceAttributes(scope, id, attrs) {
109 try {
110 jsiiDeprecationWarnings._aws_cdk_aws_ecs_Ec2ServiceAttributes(attrs);
111 }
112 catch (error) {
113 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
114 Error.captureStackTrace(error, this.fromEc2ServiceAttributes);
115 }
116 throw error;
117 }
118 return from_service_attributes_1.fromServiceAtrributes(scope, id, attrs);
119 }
120 /**
121 * Adds one or more placement strategies to use for tasks in the service. For more information, see
122 * [Amazon ECS Task Placement Strategies](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-placement-strategies.html).
123 */
124 addPlacementStrategies(...strategies) {
125 try {
126 jsiiDeprecationWarnings._aws_cdk_aws_ecs_PlacementStrategy(strategies);
127 }
128 catch (error) {
129 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
130 Error.captureStackTrace(error, this.addPlacementStrategies);
131 }
132 throw error;
133 }
134 if (strategies.length > 0 && this.daemon) {
135 throw new Error("Can't configure placement strategies when daemon=true");
136 }
137 for (const strategy of strategies) {
138 this.strategies.push(...strategy.toJson());
139 }
140 }
141 /**
142 * Adds one or more placement constraints to use for tasks in the service. For more information, see
143 * [Amazon ECS Task Placement Constraints](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-placement-constraints.html).
144 */
145 addPlacementConstraints(...constraints) {
146 try {
147 jsiiDeprecationWarnings._aws_cdk_aws_ecs_PlacementConstraint(constraints);
148 }
149 catch (error) {
150 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
151 Error.captureStackTrace(error, this.addPlacementConstraints);
152 }
153 throw error;
154 }
155 for (const constraint of constraints) {
156 this.constraints.push(...constraint.toJson());
157 }
158 }
159 /**
160 * Validates this Ec2Service.
161 */
162 validate() {
163 const ret = super.validate();
164 if (!this.cluster.hasEc2Capacity) {
165 ret.push('Cluster for this service needs Ec2 capacity. Call addXxxCapacity() on the cluster.');
166 }
167 return ret;
168 }
169}
170exports.Ec2Service = Ec2Service;
171_a = JSII_RTTI_SYMBOL_1;
172Ec2Service[_a] = { fqn: "@aws-cdk/aws-ecs.Ec2Service", version: "1.156.1" };
173/**
174 * Validate combinations of networking arguments.
175 */
176function validateNoNetworkingProps(props) {
177 if (props.vpcSubnets !== undefined
178 || props.securityGroup !== undefined
179 || props.securityGroups !== undefined
180 || props.assignPublicIp) {
181 throw new Error('vpcSubnets, securityGroup(s) and assignPublicIp can only be used in AwsVpc networking mode');
182 }
183}
184/**
185 * Force security group rules to be created in this stack.
186 *
187 * For every security group, if the scope and the group are in different stacks, return
188 * a fake "imported" security group instead. This will behave as the original security group,
189 * but new Ingress and Egress rule resources will be added in the current stack instead of the
190 * other one.
191 */
192function securityGroupsInThisStack(scope, groups) {
193 const thisStack = core_1.Stack.of(scope);
194 let i = 1;
195 return groups.map(group => {
196 if (thisStack === core_1.Stack.of(group)) {
197 return group;
198 } // Simple case, just return the original one
199 return ec2.SecurityGroup.fromSecurityGroupId(scope, `SecurityGroup${i++}`, group.securityGroupId, {
200 allowAllOutbound: group.allowAllOutbound,
201 mutable: true,
202 });
203 });
204}
205/**
206 * The built-in container instance attributes
207 */
208class BuiltInAttributes {
209}
210exports.BuiltInAttributes = BuiltInAttributes;
211_b = JSII_RTTI_SYMBOL_1;
212BuiltInAttributes[_b] = { fqn: "@aws-cdk/aws-ecs.BuiltInAttributes", version: "1.156.1" };
213/**
214 * The id of the instance.
215 */
216BuiltInAttributes.INSTANCE_ID = 'instanceId';
217/**
218 * The AvailabilityZone where the instance is running in.
219 */
220BuiltInAttributes.AVAILABILITY_ZONE = 'attribute:ecs.availability-zone';
221/**
222 * The AMI id the instance is using.
223 */
224BuiltInAttributes.AMI_ID = 'attribute:ecs.ami-id';
225/**
226 * The EC2 instance type.
227 */
228BuiltInAttributes.INSTANCE_TYPE = 'attribute:ecs.instance-type';
229/**
230 * The operating system of the instance.
231 *
232 * Either 'linux' or 'windows'.
233 */
234BuiltInAttributes.OS_TYPE = 'attribute:ecs.os-type';
235//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZWMyLXNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJlYzItc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7QUFBQSx3Q0FBd0M7QUFDeEMsd0NBQWlFO0FBRWpFLHVEQUFxSTtBQUNySSw2RUFBd0U7QUFDeEUsNkRBQXNFO0FBZ0h0RTs7OztHQUlHO0FBQ0gsTUFBYSxVQUFXLFNBQVEsMEJBQVc7SUF3QnpDOztPQUVHO0lBQ0gsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUFzQjs7Ozs7Ozs7Ozs7UUFDOUQsSUFBSSxLQUFLLENBQUMsTUFBTSxJQUFJLEtBQUssQ0FBQyxZQUFZLEtBQUssU0FBUyxFQUFFO1lBQ3BELE1BQU0sSUFBSSxLQUFLLENBQUMsOEVBQThFLENBQUMsQ0FBQztTQUNqRztRQUVELElBQUksS0FBSyxDQUFDLE1BQU0sSUFBSSxLQUFLLENBQUMsaUJBQWlCLEtBQUssU0FBUyxJQUFJLEtBQUssQ0FBQyxpQkFBaUIsS0FBSyxHQUFHLEVBQUU7WUFDNUYsTUFBTSxJQUFJLEtBQUssQ0FBQyw4Q0FBOEMsQ0FBQyxDQUFDO1NBQ2pFO1FBRUQsSUFBSSxLQUFLLENBQUMsaUJBQWlCLEtBQUssU0FBUyxJQUFJLEtBQUssQ0FBQyxpQkFBaUIsS0FBSyxTQUFTLElBQUksS0FBSyxDQUFDLGlCQUFpQixJQUFJLEtBQUssQ0FBQyxpQkFBaUIsRUFBRTtZQUN4SSxNQUFNLElBQUksS0FBSyxDQUFDLG9FQUFvRSxDQUFDLENBQUM7U0FDdkY7UUFFRCxJQUFJLENBQUMsS0FBSyxDQUFDLGNBQWMsQ0FBQyxlQUFlLEVBQUU7WUFDekMsTUFBTSxJQUFJLEtBQUssQ0FBQyxzRUFBc0UsQ0FBQyxDQUFDO1NBQ3pGO1FBRUQsSUFBSSxLQUFLLENBQUMsYUFBYSxLQUFLLFNBQVMsSUFBSSxLQUFLLENBQUMsY0FBYyxLQUFLLFNBQVMsRUFBRTtZQUMzRSxNQUFNLElBQUksS0FBSyxDQUFDLCtEQUErRCxDQUFDLENB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UUFFakcsT0FBTyxHQUFHLENBQUMsYUFBYSxDQUFDLG1CQUFtQixDQUFDLEtBQUssRUFBRSxnQkFBZ0IsQ0FBQyxFQUFFLEVBQUUsRUFBRSxLQUFLLENBQUMsZUFBZSxFQUFFO1lBQ2hHLGdCQUFnQixFQUFFLEtBQUssQ0FBQyxnQkFBZ0I7WUFDeEMsT0FBTyxFQUFFLElBQUk7U0FDZCxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRDs7R0FFRztBQUNILE1BQWEsaUJBQWlCOztBQUE5Qiw4Q0EyQkM7OztBQTFCQzs7R0FFRztBQUNvQiw2QkFBVyxHQUFHLFlBQVksQ0FBQztBQUVsRDs7R0FFRztBQUNvQixtQ0FBaUIsR0FBRyxpQ0FBaUMsQ0FBQztBQUU3RTs7R0FFRztBQUNvQix3QkFBTSxHQUFHLHNCQUFzQixDQUFDO0FBRXZEOztHQUVHO0FBQ29CLCtCQUFhLEdBQUcsNkJBQTZCLENBQUM7QUFFckU7Ozs7R0FJRztBQUNvQix5QkFBTyxHQUFHLHVCQUF1QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgZWMyIGZyb20gJ0Bhd3MtY2RrL2F3cy1lYzInO1xuaW1wb3J0IHsgQXJuRm9ybWF0LCBMYXp5LCBSZXNvdXJjZSwgU3RhY2sgfSBmcm9tICdAYXdzLWNkay9jb3JlJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgQmFzZVNlcnZpY2UsIEJhc2VTZXJ2aWNlT3B0aW9ucywgRGVwbG95bWVudENvbnRyb2xsZXJUeXBlLCBJQmFzZVNlcnZpY2UsIElTZXJ2aWNlLCBMYXVuY2hUeXBlIH0gZnJvbSAnLi4vYmFzZS9iYXNlLXNlcnZpY2UnO1xuaW1wb3J0IHsgZnJvbVNlcnZpY2VBdHJyaWJ1dGVzIH0gZnJvbSAnLi4vYmFzZS9mcm9tLXNlcnZpY2UtYXR0cmlidXRlcyc7XG5pbXBvcnQgeyBOZXR3b3JrTW9kZSwgVGFza0RlZmluaXRpb24gfSBmcm9tICcuLi9iYXNlL3Rhc2stZGVmaW5pdGlvbic7XG5pbXBvcnQgeyBJQ2x1c3RlciB9IGZyb20gJy4uL2NsdXN0ZXInO1xuaW1wb3J0IHsgQ2ZuU2VydmljZSB9IGZyb20gJy4uL2Vjcy5nZW5lcmF0ZWQnO1xuaW1wb3J0IHsgUGxhY2VtZW50Q29uc3RyYWludCwgUGxhY2VtZW50U3RyYXRlZ3kgfSBmcm9tICcuLi9wbGFjZW1lbnQnO1xuXG4vKipcbiAqIFRoZSBwcm9wZXJ0aWVzIGZvciBkZWZpbmluZyBhIHNlcnZpY2UgdXNpbmcgdGhlIEVDMiBsYXVuY2ggdHlwZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBFYzJTZXJ2aWNlUHJvcHMgZXh0ZW5kcyBCYXNlU2VydmljZU9wdGlvbnMge1xuICAvKipcbiAgICogVGhlIHRhc2sgZGVmaW5pdGlvbiB0byB1c2UgZm9yIHRhc2tzIGluIHRoZSBzZXJ2aWNlLlxuICAgKlxuICAgKiBbZGlzYWJsZS1hd3NsaW50OnJlZi12aWEtaW50ZXJmYWNlXVxuICAgKi9cbiAgcmVhZG9ubHkgdGFza0RlZmluaXRpb246IFRhc2tEZWZpbml0aW9uO1xuXG4gIC8qKlxuICAgKiBTcGVjaWZpZXMgd2hldGhlciB0aGUgdGFzaydzIGVsYXN0aWMgbmV0d29yayBpbnRlcmZhY2UgcmVjZWl2ZXMgYSBwdWJsaWMgSVAgYWRkcmVzcy5cbiAgICogSWYgdHJ1ZSwgZWFjaCB0YXNrIHdpbGwgcmVjZWl2ZSBhIHB1YmxpYyBJUCBhZGRyZXNzLlxuICAgKlxuICAgKiBUaGlzIHByb3BlcnR5IGlzIG9ubHkgdXNlZCBmb3IgdGFza3MgdGhhdCB1c2UgdGhlIGF3c3ZwYyBuZXR3b3JrIG1vZGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IGZhbHNlXG4gICAqL1xuICByZWFkb25seSBhc3NpZ25QdWJsaWNJcD86IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIFRoZSBzdWJuZXRzIHRvIGFzc29jaWF0ZSB3aXRoIHRoZSBzZXJ2aWNlLlxuICAgKlxuICAgKiBUaGlzIHByb3BlcnR5IGlzIG9ubHkgdXNlZCBmb3IgdGFza3MgdGhhdCB1c2UgdGhlIGF3c3ZwYyBuZXR3b3JrIG1vZGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gUHVibGljIHN1Ym5ldHMgaWYgYGFzc2lnblB1YmxpY0lwYCBpcyBzZXQsIG90aGVyd2lzZSB0aGUgZmlyc3QgYXZhaWxhYmxlIG9uZSBvZiBQcml2YXRlLCBJc29sYXRlZCwgUHVibGljLCBpbiB0aGF0IG9yZGVyLlxuICAgKi9cbiAgcmVhZG9ubHkgdnBjU3VibmV0cz86IGVjMi5TdWJuZXRTZWxlY3Rpb247XG5cbiAgLyoqXG4gICAqIFRoZSBzZWN1cml0eSBncm91cHMgdG8gYXNzb2NpYXRlIHdpdGggdGhlIHNlcnZpY2UuIElmIHlvdSBkbyBub3Qgc3BlY2lmeSBhIHNlY3VyaXR5IGdyb3VwLCBhIG5ldyBzZWN1cml0eSBncm91cCBpcyBjcmVhdGVkLlxuICAgKlxuICAgKiBUaGlzIHByb3BlcnR5IGlzIG9ubHkgdXNlZCBmb3IgdGFza3MgdGhhdCB1c2UgdGhlIGF3c3ZwYyBuZXR3b3JrIG1vZGUuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gQSBuZXcgc2VjdXJpdHkgZ3JvdXAgaXMgY3JlYXRlZC5cbiAgICogQGRlcHJlY2F0ZWQgdXNlIHNlY3VyaXR5R3JvdXBzIGluc3RlYWQuXG4gICAqL1xuICByZWFkb25seSBzZWN1cml0eUdyb3VwPzogZWMyLklTZWN1cml0eUdyb3VwO1xuXG4gIC8qKlxuICAgKiBUaGUgc2VjdXJpdHkgZ3JvdXBzIHRvIGFzc29jaWF0ZSB3aXRoIHRoZSBzZXJ2aWNlLiBJZiB5b3UgZG8gbm90IHNwZWNpZnkgYSBzZWN1cml0eSBncm91cCwgYSBuZXcgc2VjdXJpdHkgZ3JvdXAgaXMgY3JlYXRlZC5cbiAgICpcbiAgICogVGhpcyBwcm9wZXJ0eSBpcyBvbmx5IHVzZWQgZm9yIHRhc2tzIHRoYXQgdXNlIHRoZSBhd3N2cGMgbmV0d29yayBtb2RlLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEEgbmV3IHNlY3VyaXR5IGdyb3VwIGlzIGNyZWF0ZWQuXG4gICAqL1xuICByZWFkb25seSBzZWN1cml0eUdyb3Vwcz86IGVjMi5JU2VjdXJpdHlHcm91cFtdO1xuXG4gIC8qKlxuICAgKiBUaGUgcGxhY2VtZW50IGNvbnN0cmFpbnRzIHRvIHVzZSBmb3IgdGFza3MgaW4gdGhlIHNlcnZpY2UuIEZvciBtb3JlIGluZm9ybWF0aW9uLCBzZWVcbiAgICogW0FtYXpvbiBFQ1MgVGFzayBQbGFjZW1lbnQgQ29uc3RyYWludHNdKGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BbWF6b25FQ1MvbGF0ZXN0L2RldmVsb3Blcmd1aWRlL3Rhc2stcGxhY2VtZW50LWNvbnN0cmFpbnRzLmh0bWwpLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIGNvbnN0cmFpbnRzLlxuICAgKi9cbiAgcmVhZG9ubHkgcGxhY2VtZW50Q29uc3RyYWludHM/OiBQbGFjZW1lbnRDb25zdHJhaW50W107XG5cbiAgLyoqXG4gICAqIFRoZSBwbGFjZW1lbnQgc3RyYXRlZ2llcyB0byB1c2UgZm9yIHRhc2tzIGluIHRoZSBzZXJ2aWNlLiBGb3IgbW9yZSBpbmZvcm1hdGlvbiwgc2VlXG4gICAqIFtBbWF6b24gRUNTIFRhc2sgUGxhY2VtZW50IFN0cmF0ZWdpZXNdKGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BbWF6b25FQ1MvbGF0ZXN0L2RldmVsb3Blcmd1aWRlL3Rhc2stcGxhY2VtZW50LXN0cmF0ZWdpZXMuaHRtbCkuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gc3RyYXRlZ2llcy5cbiAgICovXG4gIHJlYWRvbmx5IHBsYWNlbWVudFN0cmF0ZWdpZXM/OiBQbGFjZW1lbnRTdHJhdGVneVtdO1xuXG4gIC8qKlxuICAgKiBTcGVjaWZpZXMgd2hldGhlciB0aGUgc2VydmljZSB3aWxsIHVzZSB0aGUgZGFlbW9uIHNjaGVkdWxpbmcgc3RyYXRlZ3kuXG4gICAqIElmIHRydWUsIHRoZSBzZXJ2aWNlIHNjaGVkdWxlciBkZXBsb3lzIGV4YWN0bHkgb25lIHRhc2sgb24gZWFjaCBjb250YWluZXIgaW5zdGFuY2UgaW4geW91ciBjbHVzdGVyLlxuICAgKlxuICAgKiBXaGVuIHlvdSBhcmUgdXNpbmcgdGhpcyBzdHJhdGVneSwgZG8gbm90IHNwZWNpZnkgYSBkZXNpcmVkIG51bWJlciBvZiB0YXNrcyBvcmFueSB0YXNrIHBsYWNlbWVudCBzdHJhdGVnaWVzLlxuICAgKlxuICAgKiBAZGVmYXVsdCBmYWxzZVxuICAgKi9cbiAgcmVhZG9ubHkgZGFlbW9uPzogYm9vbGVhbjtcbn1cblxuLyoqXG4gKiBUaGUgaW50ZXJmYWNlIGZvciBhIHNlcnZpY2UgdXNpbmcgdGhlIEVDMiBsYXVuY2ggdHlwZSBvbiBhbiBFQ1MgY2x1c3Rlci5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBJRWMyU2VydmljZSBleHRlbmRzIElTZXJ2aWNlIHtcblxufVxuXG4vKipcbiAqIFRoZSBwcm9wZXJ0aWVzIHRvIGltcG9ydCBmcm9tIHRoZSBzZXJ2aWNlIHVzaW5nIHRoZSBFQzIgbGF1bmNoIHR5cGUuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRWMyU2VydmljZUF0dHJpYnV0ZXMge1xuICAvKipcbiAgICogVGhlIGNsdXN0ZXIgdGhhdCBob3N0cyB0aGUgc2VydmljZS5cbiAgICovXG4gIHJlYWRvbmx5IGNsdXN0ZXI6IElDbHVzdGVyO1xuXG4gIC8qKlxuICAgKiBUaGUgc2VydmljZSBBUk4uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gZWl0aGVyIHRoaXMsIG9yIHtAbGluayBzZXJ2aWNlTmFtZX0sIGlzIHJlcXVpcmVkXG4gICAqL1xuICByZWFkb25seSBzZXJ2aWNlQXJuPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgc2VydmljZS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBlaXRoZXIgdGhpcywgb3Ige0BsaW5rIHNlcnZpY2VBcm59LCBpcyByZXF1aXJlZFxuICAgKi9cbiAgcmVhZG9ubHkgc2VydmljZU5hbWU/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogVGhpcyBjcmVhdGVzIGEgc2VydmljZSB1c2luZyB0aGUgRUMyIGxhdW5jaCB0eXBlIG9uIGFuIEVDUyBjbHVzdGVyLlxuICpcbiAqIEByZXNvdXJjZSBBV1M6OkVDUzo6U2VydmljZVxuICovXG5leHBvcnQgY2xhc3MgRWMyU2VydmljZSBleHRlbmRzIEJhc2VTZXJ2aWNlIGltcGxlbWVudHMgSUVjMlNlcnZpY2Uge1xuXG4gIC8qKlxuICAgKiBJbXBvcnRzIGZyb20gdGhlIHNwZWNpZmllZCBzZXJ2aWNlIEFSTi5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZnJvbUVjMlNlcnZpY2VBcm4oc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgZWMyU2VydmljZUFybjogc3RyaW5nKTogSUVjMlNlcnZpY2Uge1xuICAgIGNsYXNzIEltcG9ydCBleHRlbmRzIFJlc291cmNlIGltcGxlbWVudHMgSUVjMlNlcnZpY2Uge1xuICAgICAgcHVibGljIHJlYWRvbmx5IHNlcnZpY2VBcm4gPSBlYzJTZXJ2aWNlQXJuO1xuICAgICAgcHVibGljIHJlYWRvbmx5IHNlcnZpY2VOYW1lID0gU3RhY2sub2Yoc2NvcGUpLnNwbGl0QXJuKGVjMlNlcnZpY2VBcm4sIEFybkZvcm1hdC5TTEFTSF9SRVNPVVJDRV9OQU1FKS5yZXNvdXJjZU5hbWUgYXMgc3RyaW5nO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IEltcG9ydChzY29wZSwgaWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEltcG9ydHMgZnJvbSB0aGUgc3BlY2lmaWVkIHNlcnZpY2UgYXR0cnJpYnV0ZXMuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGZyb21FYzJTZXJ2aWNlQXR0cmlidXRlcyhzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBhdHRyczogRWMyU2VydmljZUF0dHJpYnV0ZXMpOiBJQmFzZVNlcnZpY2Uge1xuICAgIHJldHVybiBmcm9tU2VydmljZUF0cnJpYnV0ZXMoc2NvcGUsIGlkLCBhdHRycyk7XG4gIH1cblxuICBwcml2YXRlIHJlYWRvbmx5IGNvbnN0cmFpbnRzOiBDZm5TZXJ2aWNlLlBsYWNlbWVudENvbnN0cmFpbnRQcm9wZXJ0eVtdO1xuICBwcml2YXRlIHJlYWRvbmx5IHN0cmF0ZWdpZXM6IENmblNlcnZpY2UuUGxhY2VtZW50U3RyYXRlZ3lQcm9wZXJ0eVtdO1xuICBwcml2YXRlIHJlYWRvbmx5IGRhZW1vbjogYm9vbGVhbjtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIG5ldyBpbnN0YW5jZSBvZiB0aGUgRWMyU2VydmljZSBjbGFzcy5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBFYzJTZXJ2aWNlUHJvcHMpIHtcbiAgICBpZiAocHJvcHMuZGFlbW9uICYmIHByb3BzLmRlc2lyZWRDb3VudCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0RhZW1vbiBtb2RlIGxhdW5jaGVzIG9uZSB0YXNrIG9uIGV2ZXJ5IGluc3RhbmNlLiBEb25cXCd0IHN1cHBseSBkZXNpcmVkQ291bnQuJyk7XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLmRhZW1vbiAmJiBwcm9wcy5tYXhIZWFsdGh5UGVyY2VudCAhPT0gdW5kZWZpbmVkICYmIHByb3BzLm1heEhlYWx0aHlQZXJjZW50ICE9PSAxMDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTWF4aW11bSBwZXJjZW50IG11c3QgYmUgMTAwIGZvciBkYWVtb24gbW9kZS4nKTtcbiAgICB9XG5cbiAgICBpZiAocHJvcHMubWluSGVhbHRoeVBlcmNlbnQgIT09IHVuZGVmaW5lZCAmJiBwcm9wcy5tYXhIZWFsdGh5UGVyY2VudCAhPT0gdW5kZWZpbmVkICYmIHByb3BzLm1pbkhlYWx0aHlQZXJjZW50ID49IHByb3BzLm1heEhlYWx0aHlQZXJjZW50KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ01pbmltdW0gaGVhbHRoeSBwZXJjZW50IG11c3QgYmUgbGVzcyB0aGFuIG1heGltdW0gaGVhbHRoeSBwZXJjZW50LicpO1xuICAgIH1cblxuICAgIGlmICghcHJvcHMudGFza0RlZmluaXRpb24uaXNFYzJDb21wYXRpYmxlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ1N1cHBsaWVkIFRhc2tEZWZpbml0aW9uIGlzIG5vdCBjb25maWd1cmVkIGZvciBjb21wYXRpYmlsaXR5IHdpdGggRUMyJyk7XG4gICAgfVxuXG4gICAgaWYgKHByb3BzLnNlY3VyaXR5R3JvdXAgIT09IHVuZGVmaW5lZCAmJiBwcm9wcy5zZWN1cml0eUdyb3VwcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ09ubHkgb25lIG9mIFNlY3VyaXR5R3JvdXAgb3IgU2VjdXJpdHlHcm91cHMgY2FuIGJlIHBvcHVsYXRlZC4nKTtcbiAgICB9XG5cbiAgICBzdXBlcihzY29wZSwgaWQsIHtcbiAgICAgIC4uLnByb3BzLFxuICAgICAgZGVzaXJlZENvdW50OiBwcm9wcy5kZXNpcmVkQ291bnQsXG4gICAgICBtYXhIZWFsdGh5UGVyY2VudDogcHJvcHMuZGFlbW9uICYmIHByb3BzLm1heEhlYWx0aHlQZXJjZW50ID09PSB1bmRlZmluZWQgPyAxMDAgOiBwcm9wcy5tYXhIZWFsdGh5UGVyY2VudCxcbiAgICAgIG1pbkhlYWx0aHlQZXJjZW50OiBwcm9wcy5kYWVtb24gJiYgcHJvcHMubWluSGVhbHRoeVBlcmNlbnQgPT09IHVuZGVmaW5lZCA/IDAgOiBwcm9wcy5taW5IZWFsdGh5UGVyY2VudCxcbiAgICAgIGxhdW5jaFR5cGU6IExhdW5jaFR5cGUuRUMyLFxuICAgICAgZW5hYmxlRUNTTWFuYWdlZFRhZ3M6IHByb3BzLmVuYWJsZUVDU01hbmFnZWRUYWdzLFxuICAgIH0sXG4gICAge1xuICAgICAgY2x1c3RlcjogcHJvcHMuY2x1c3Rlci5jbHVzdGVyTmFtZSxcbiAgICAgIHRhc2tEZWZpbml0aW9uOiBwcm9wcy5kZXBsb3ltZW50Q29udHJvbGxlcj8udHlwZSA9PT0gRGVwbG95bWVudENvbnRyb2xsZXJUeXBlLkVYVEVSTkFMID8gdW5kZWZpbmVkIDogcHJvcHMudGFza0RlZmluaXRpb24udGFza0RlZmluaXRpb25Bcm4sXG4gICAgICBwbGFjZW1lbnRDb25zdHJhaW50czogTGF6eS5hbnkoeyBwcm9kdWNlOiAoKSA9PiB0aGlzLmNvbnN0cmFpbnRzIH0sIHsgb21pdEVtcHR5QXJyYXk6IHRydWUgfSksXG4gICAgICBwbGFjZW1lbnRTdHJhdGVnaWVzOiBMYXp5LmFueSh7IHByb2R1Y2U6ICgpID0+IHRoaXMuc3RyYXRlZ2llcyB9LCB7IG9taXRFbXB0eUFycmF5OiB0cnVlIH0pLFxuICAgICAgc2NoZWR1bGluZ1N0cmF0ZWd5OiBwcm9wcy5kYWVtb24gPyAnREFFTU9OJyA6ICdSRVBMSUNBJyxcbiAgICB9LCBwcm9wcy50YXNrRGVmaW5pdGlvbik7XG5cbiAgICB0aGlzLmNvbnN0cmFpbnRzID0gW107XG4gICAgdGhpcy5zdHJhdGVnaWVzID0gW107XG4gICAgdGhpcy5kYWVtb24gPSBwcm9wcy5kYWVtb24gfHwgZmFsc2U7XG5cbiAgICBsZXQgc2VjdXJpdHlHcm91cHM7XG4gICAgaWYgKHByb3BzLnNlY3VyaXR5R3JvdXAgIT09IHVuZGVmaW5lZCkge1xuICAgICAgc2VjdXJpdHlHcm91cHMgPSBbcHJvcHMuc2VjdXJpdHlHcm91cF07XG4gICAgfSBlbHNlIGlmIChwcm9wcy5zZWN1cml0eUdyb3VwcyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBzZWN1cml0eUdyb3VwcyA9IHByb3BzLnNlY3VyaXR5R3JvdXBzO1xuICAgIH1cblxuICAgIGlmIChwcm9wcy50YXNrRGVmaW5pdGlvbi5uZXR3b3JrTW9kZSA9PT0gTmV0d29ya01vZGUuQVdTX1ZQQykge1xuICAgICAgdGhpcy5jb25maWd1cmVBd3NWcGNOZXR3b3JraW5nV2l0aFNlY3VyaXR5R3JvdXBzKHByb3BzLmNsdXN0ZXIudnBjLCBwcm9wcy5hc3NpZ25QdWJsaWNJcCwgcHJvcHMudnBjU3VibmV0cywgc2VjdXJpdHlHcm91cHMpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBFaXRoZXIgTm9uZSwgQnJpZGdlIG9yIEhvc3QgbmV0d29ya2luZy4gQ29weSBTZWN1cml0eUdyb3VwcyBmcm9tIEFTRy5cbiAgICAgIC8vIFdlIGhhdmUgdG8gYmUgc21hcnQgaGVyZSAtLSBieSBkZWZhdWx0IGZ1dHVyZSBTZWN1cml0eSBHcm91cCBydWxlcyB3b3VsZCBiZSBjcmVhdGVkXG4gICAgICAvLyBpbiB0aGUgQ2x1c3RlciBzdGFjay4gSG93ZXZlciwgaWYgdGhlIENsdXN0ZXIgaXMgaW4gYSBkaWZmZXJlbnQgc3RhY2sgdGhhbiB1cyxcbiAgICAgIC8vIHRoYXQgd2lsbCBsZWFkIHRvIGEgY3ljbGljIHJlZmVyZW5jZSAod2UgcG9pbnQgdG8gdGhhdCBzdGFjayBmb3IgdGhlIGNsdXN0ZXIgbmFtZSxcbiAgICAgIC8vIGJ1dCB0aGF0IHN0YWNrIHdpbGwgcG9pbnQgdG8gdGhlIEFMQiBwcm9iYWJseSBjcmVhdGVkIHJpZ2h0IG5leHQgdG8gdXMpLlxuICAgICAgLy9cbiAgICAgIC8vIEluIHRoYXQgY2FzZSwgcmVmZXJlbmNlIHRoZSBzYW1lIHNlY3VyaXR5IGdyb3VwcyBidXQgbWFrZSBzdXJlIG5ldyBydWxlcyBhcmVcbiAgICAgIC8vIGNyZWF0ZWQgaW4gdGhlIGN1cnJlbnQgc2NvcGUgKGkuZS4sIHRoaXMgc3RhY2spXG4gICAgICB2YWxpZGF0ZU5vTmV0d29ya2luZ1Byb3BzKHByb3BzKTtcbiAgICAgIHRoaXMuY29ubmVjdGlvbnMuYWRkU2VjdXJpdHlHcm91cCguLi5zZWN1cml0eUdyb3Vwc0luVGhpc1N0YWNrKHRoaXMsIHByb3BzLmNsdXN0ZXIuY29ubmVjdGlvbnMuc2VjdXJpdHlHcm91cHMpKTtcbiAgICB9XG5cbiAgICB0aGlzLmFkZFBsYWNlbWVudENvbnN0cmFpbnRzKC4uLnByb3BzLnBsYWNlbWVudENvbnN0cmFpbnRzIHx8IFtdKTtcbiAgICB0aGlzLmFkZFBsYWNlbWVudFN0cmF0ZWdpZXMoLi4ucHJvcHMucGxhY2VtZW50U3RyYXRlZ2llcyB8fCBbXSk7XG5cbiAgICB0aGlzLm5vZGUuYWRkVmFsaWRhdGlvbih7XG4gICAgICB2YWxpZGF0ZTogKCkgPT4gIXRoaXMudGFza0RlZmluaXRpb24uZGVmYXVsdENvbnRhaW5lciA/IFsnQSBUYXNrRGVmaW5pdGlvbiBtdXN0IGhhdmUgYXQgbGVhc3Qgb25lIGVzc2VudGlhbCBjb250YWluZXInXSA6IFtdLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgb25lIG9yIG1vcmUgcGxhY2VtZW50IHN0cmF0ZWdpZXMgdG8gdXNlIGZvciB0YXNrcyBpbiB0aGUgc2VydmljZS4gRm9yIG1vcmUgaW5mb3JtYXRpb24sIHNlZVxuICAgKiBbQW1hem9uIEVDUyBUYXNrIFBsYWNlbWVudCBTdHJhdGVnaWVzXShodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uRUNTL2xhdGVzdC9kZXZlbG9wZXJndWlkZS90YXNrLXBsYWNlbWVudC1zdHJhdGVnaWVzLmh0bWwpLlxuICAgKi9cbiAgcHVibGljIGFkZFBsYWNlbWVudFN0cmF0ZWdpZXMoLi4uc3RyYXRlZ2llczogUGxhY2VtZW50U3RyYXRlZ3lbXSkge1xuICAgIGlmIChzdHJhdGVnaWVzLmxlbmd0aCA+IDAgJiYgdGhpcy5kYWVtb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkNhbid0IGNvbmZpZ3VyZSBwbGFjZW1lbnQgc3RyYXRlZ2llcyB3aGVuIGRhZW1vbj10cnVlXCIpO1xuICAgIH1cblxuICAgIGZvciAoY29uc3Qgc3RyYXRlZ3kgb2Ygc3RyYXRlZ2llcykge1xuICAgICAgdGhpcy5zdHJhdGVnaWVzLnB1c2goLi4uc3RyYXRlZ3kudG9Kc29uKCkpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIG9uZSBvciBtb3JlIHBsYWNlbWVudCBjb25zdHJhaW50cyB0byB1c2UgZm9yIHRhc2tzIGluIHRoZSBzZXJ2aWNlLiBGb3IgbW9yZSBpbmZvcm1hdGlvbiwgc2VlXG4gICAqIFtBbWF6b24gRUNTIFRhc2sgUGxhY2VtZW50IENvbnN0cmFpbnRzXShodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uRUNTL2xhdGVzdC9kZXZlbG9wZXJndWlkZS90YXNrLXBsYWNlbWVudC1jb25zdHJhaW50cy5odG1sKS5cbiAgICovXG4gIHB1YmxpYyBhZGRQbGFjZW1lbnRDb25zdHJhaW50cyguLi5jb25zdHJhaW50czogUGxhY2VtZW50Q29uc3RyYWludFtdKSB7XG4gICAgZm9yIChjb25zdCBjb25zdHJhaW50IG9mIGNvbnN0cmFpbnRzKSB7XG4gICAgICB0aGlzLmNvbnN0cmFpbnRzLnB1c2goLi4uY29uc3RyYWludC50b0pzb24oKSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFZhbGlkYXRlcyB0aGlzIEVjMlNlcnZpY2UuXG4gICAqL1xuICBwcm90ZWN0ZWQgdmFsaWRhdGUoKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IHJldCA9IHN1cGVyLnZhbGlkYXRlKCk7XG4gICAgaWYgKCF0aGlzLmNsdXN0ZXIuaGFzRWMyQ2FwYWNpdHkpIHtcbiAgICAgIHJldC5wdXNoKCdDbHVzdGVyIGZvciB0aGlzIHNlcnZpY2UgbmVlZHMgRWMyIGNhcGFjaXR5LiBDYWxsIGFkZFh4eENhcGFjaXR5KCkgb24gdGhlIGNsdXN0ZXIuJyk7XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG4gIH1cbn1cblxuLyoqXG4gKiBWYWxpZGF0ZSBjb21iaW5hdGlvbnMgb2YgbmV0d29ya2luZyBhcmd1bWVudHMuXG4gKi9cbmZ1bmN0aW9uIHZhbGlkYXRlTm9OZXR3b3JraW5nUHJvcHMocHJvcHM6IEVjMlNlcnZpY2VQcm9wcykge1xuICBpZiAocHJvcHMudnBjU3VibmV0cyAhPT0gdW5kZWZpbmVkXG4gICAgfHwgcHJvcHMuc2VjdXJpdHlHcm91cCAhPT0gdW5kZWZpbmVkXG4gICAgfHwgcHJvcHMuc2VjdXJpdHlHcm91cHMgIT09IHVuZGVmaW5lZFxuICAgIHx8IHByb3BzLmFzc2lnblB1YmxpY0lwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCd2cGNTdWJuZXRzLCBzZWN1cml0eUdyb3VwKHMpIGFuZCBhc3NpZ25QdWJsaWNJcCBjYW4gb25seSBiZSB1c2VkIGluIEF3c1ZwYyBuZXR3b3JraW5nIG1vZGUnKTtcbiAgfVxufVxuXG4vKipcbiAqIEZvcmNlIHNlY3VyaXR5IGdyb3VwIHJ1bGVzIHRvIGJlIGNyZWF0ZWQgaW4gdGhpcyBzdGFjay5cbiAqXG4gKiBGb3IgZXZlcnkgc2VjdXJpdHkgZ3JvdXAsIGlmIHRoZSBzY29wZSBhbmQgdGhlIGdyb3VwIGFyZSBpbiBkaWZmZXJlbnQgc3RhY2tzLCByZXR1cm5cbiAqIGEgZmFrZSBcImltcG9ydGVkXCIgc2VjdXJpdHkgZ3JvdXAgaW5zdGVhZC4gVGhpcyB3aWxsIGJlaGF2ZSBhcyB0aGUgb3JpZ2luYWwgc2VjdXJpdHkgZ3JvdXAsXG4gKiBidXQgbmV3IEluZ3Jlc3MgYW5kIEVncmVzcyBydWxlIHJlc291cmNlcyB3aWxsIGJlIGFkZGVkIGluIHRoZSBjdXJyZW50IHN0YWNrIGluc3RlYWQgb2YgdGhlXG4gKiBvdGhlciBvbmUuXG4gKi9cbmZ1bmN0aW9uIHNlY3VyaXR5R3JvdXBzSW5UaGlzU3RhY2soc2NvcGU6IENvbnN0cnVjdCwgZ3JvdXBzOiBlYzIuSVNlY3VyaXR5R3JvdXBbXSk6IGVjMi5JU2VjdXJpdHlHcm91cFtdIHtcbiAgY29uc3QgdGhpc1N0YWNrID0gU3RhY2sub2Yoc2NvcGUpO1xuXG4gIGxldCBpID0gMTtcbiAgcmV0dXJuIGdyb3Vwcy5tYXAoZ3JvdXAgPT4ge1xuICAgIGlmICh0aGlzU3RhY2sgPT09IFN0YWNrLm9mKGdyb3VwKSkgeyByZXR1cm4gZ3JvdXA7IH0gLy8gU2ltcGxlIGNhc2UsIGp1c3QgcmV0dXJuIHRoZSBvcmlnaW5hbCBvbmVcblxuICAgIHJldHVybiBlYzIuU2VjdXJpdHlHcm91cC5mcm9tU2VjdXJpdHlHcm91cElkKHNjb3BlLCBgU2VjdXJpdHlHcm91cCR7aSsrfWAsIGdyb3VwLnNlY3VyaXR5R3JvdXBJZCwge1xuICAgICAgYWxsb3dBbGxPdXRib3VuZDogZ3JvdXAuYWxsb3dBbGxPdXRib3VuZCxcbiAgICAgIG11dGFibGU6IHRydWUsXG4gICAgfSk7XG4gIH0pO1xufVxuXG4vKipcbiAqIFRoZSBidWlsdC1pbiBjb250YWluZXIgaW5zdGFuY2UgYXR0cmlidXRlc1xuICovXG5leHBvcnQgY2xhc3MgQnVpbHRJbkF0dHJpYnV0ZXMge1xuICAvKipcbiAgICogVGhlIGlkIG9mIHRoZSBpbnN0YW5jZS5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgSU5TVEFOQ0VfSUQgPSAnaW5zdGFuY2VJZCc7XG5cbiAgLyoqXG4gICAqIFRoZSBBdmFpbGFiaWxpdHlab25lIHdoZXJlIHRoZSBpbnN0YW5jZSBpcyBydW5uaW5nIGluLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyByZWFkb25seSBBVkFJTEFCSUxJVFlfWk9ORSA9ICdhdHRyaWJ1dGU6ZWNzLmF2YWlsYWJpbGl0eS16b25lJztcblxuICAvKipcbiAgICogVGhlIEFNSSBpZCB0aGUgaW5zdGFuY2UgaXMgdXNpbmcuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IEFNSV9JRCA9ICdhdHRyaWJ1dGU6ZWNzLmFtaS1pZCc7XG5cbiAgLyoqXG4gICAqIFRoZSBFQzIgaW5zdGFuY2UgdHlwZS5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgSU5TVEFOQ0VfVFlQRSA9ICdhdHRyaWJ1dGU6ZWNzLmluc3RhbmNlLXR5cGUnO1xuXG4gIC8qKlxuICAgKiBUaGUgb3BlcmF0aW5nIHN5c3RlbSBvZiB0aGUgaW5zdGFuY2UuXG4gICAqXG4gICAqIEVpdGhlciAnbGludXgnIG9yICd3aW5kb3dzJy5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgT1NfVFlQRSA9ICdhdHRyaWJ1dGU6ZWNzLm9zLXR5cGUnO1xufVxuIl19
\No newline at end of file