UNPKG

37.1 kBJavaScriptView Raw
1"use strict";
2var _a;
3Object.defineProperty(exports, "__esModule", { value: true });
4exports.LogGroup = exports.RetentionDays = void 0;
5const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
6const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
7const cloudwatch = require("@aws-cdk/aws-cloudwatch");
8const iam = require("@aws-cdk/aws-iam");
9const core_1 = require("@aws-cdk/core");
10const log_stream_1 = require("./log-stream");
11const logs_generated_1 = require("./logs.generated");
12const metric_filter_1 = require("./metric-filter");
13const pattern_1 = require("./pattern");
14const policy_1 = require("./policy");
15const subscription_filter_1 = require("./subscription-filter");
16/**
17 * An CloudWatch Log Group
18 */
19class LogGroupBase extends core_1.Resource {
20 /**
21 * Create a new Log Stream for this Log Group
22 *
23 * @param id Unique identifier for the construct in its parent
24 * @param props Properties for creating the LogStream
25 */
26 addStream(id, props = {}) {
27 return new log_stream_1.LogStream(this, id, {
28 logGroup: this,
29 ...props,
30 });
31 }
32 /**
33 * Create a new Subscription Filter on this Log Group
34 *
35 * @param id Unique identifier for the construct in its parent
36 * @param props Properties for creating the SubscriptionFilter
37 */
38 addSubscriptionFilter(id, props) {
39 return new subscription_filter_1.SubscriptionFilter(this, id, {
40 logGroup: this,
41 ...props,
42 });
43 }
44 /**
45 * Create a new Metric Filter on this Log Group
46 *
47 * @param id Unique identifier for the construct in its parent
48 * @param props Properties for creating the MetricFilter
49 */
50 addMetricFilter(id, props) {
51 return new metric_filter_1.MetricFilter(this, id, {
52 logGroup: this,
53 ...props,
54 });
55 }
56 /**
57 * Extract a metric from structured log events in the LogGroup
58 *
59 * Creates a MetricFilter on this LogGroup that will extract the value
60 * of the indicated JSON field in all records where it occurs.
61 *
62 * The metric will be available in CloudWatch Metrics under the
63 * indicated namespace and name.
64 *
65 * @param jsonField JSON field to extract (example: '$.myfield')
66 * @param metricNamespace Namespace to emit the metric under
67 * @param metricName Name to emit the metric under
68 * @returns A Metric object representing the extracted metric
69 */
70 extractMetric(jsonField, metricNamespace, metricName) {
71 new metric_filter_1.MetricFilter(this, `${metricNamespace}_${metricName}`, {
72 logGroup: this,
73 metricNamespace,
74 metricName,
75 filterPattern: pattern_1.FilterPattern.exists(jsonField),
76 metricValue: jsonField,
77 });
78 return new cloudwatch.Metric({ metricName, namespace: metricNamespace }).attachTo(this);
79 }
80 /**
81 * Give permissions to create and write to streams in this log group
82 */
83 grantWrite(grantee) {
84 return this.grant(grantee, 'logs:CreateLogStream', 'logs:PutLogEvents');
85 }
86 /**
87 * Give the indicated permissions on this log group and all streams
88 */
89 grant(grantee, ...actions) {
90 return iam.Grant.addToPrincipalOrResource({
91 grantee,
92 actions,
93 // A LogGroup ARN out of CloudFormation already includes a ':*' at the end to include the log streams under the group.
94 // See https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-logs-loggroup.html#w2ab1c21c10c63c43c11
95 resourceArns: [this.logGroupArn],
96 resource: this,
97 });
98 }
99 /**
100 * Public method to get the physical name of this log group
101 * @returns Physical name of log group
102 */
103 logGroupPhysicalName() {
104 return this.physicalName;
105 }
106 /**
107 * Adds a statement to the resource policy associated with this log group.
108 * A resource policy will be automatically created upon the first call to `addToResourcePolicy`.
109 *
110 * Any ARN Principals inside of the statement will be converted into AWS Account ID strings
111 * because CloudWatch Logs Resource Policies do not accept ARN principals.
112 *
113 * @param statement The policy statement to add
114 */
115 addToResourcePolicy(statement) {
116 if (!this.policy) {
117 this.policy = new policy_1.ResourcePolicy(this, 'Policy');
118 }
119 this.policy.document.addStatements(statement.copy({
120 principals: statement.principals.map(p => this.convertArnPrincpalToAccountId(p)),
121 }));
122 return { statementAdded: true, policyDependable: this.policy };
123 }
124 convertArnPrincpalToAccountId(principal) {
125 if (principal.principalAccount) {
126 // we use ArnPrincipal here because the constructor inserts the argument
127 // into the template without mutating it, which means that there is no
128 // ARN created by this call.
129 return new iam.ArnPrincipal(principal.principalAccount);
130 }
131 if (principal instanceof iam.ArnPrincipal) {
132 const parsedArn = core_1.Arn.split(principal.arn, core_1.ArnFormat.SLASH_RESOURCE_NAME);
133 if (parsedArn.account) {
134 return new iam.ArnPrincipal(parsedArn.account);
135 }
136 }
137 return principal;
138 }
139}
140/**
141 * How long, in days, the log contents will be retained.
142 */
143var RetentionDays;
144(function (RetentionDays) {
145 /**
146 * 1 day
147 */
148 RetentionDays[RetentionDays["ONE_DAY"] = 1] = "ONE_DAY";
149 /**
150 * 3 days
151 */
152 RetentionDays[RetentionDays["THREE_DAYS"] = 3] = "THREE_DAYS";
153 /**
154 * 5 days
155 */
156 RetentionDays[RetentionDays["FIVE_DAYS"] = 5] = "FIVE_DAYS";
157 /**
158 * 1 week
159 */
160 RetentionDays[RetentionDays["ONE_WEEK"] = 7] = "ONE_WEEK";
161 /**
162 * 2 weeks
163 */
164 RetentionDays[RetentionDays["TWO_WEEKS"] = 14] = "TWO_WEEKS";
165 /**
166 * 1 month
167 */
168 RetentionDays[RetentionDays["ONE_MONTH"] = 30] = "ONE_MONTH";
169 /**
170 * 2 months
171 */
172 RetentionDays[RetentionDays["TWO_MONTHS"] = 60] = "TWO_MONTHS";
173 /**
174 * 3 months
175 */
176 RetentionDays[RetentionDays["THREE_MONTHS"] = 90] = "THREE_MONTHS";
177 /**
178 * 4 months
179 */
180 RetentionDays[RetentionDays["FOUR_MONTHS"] = 120] = "FOUR_MONTHS";
181 /**
182 * 5 months
183 */
184 RetentionDays[RetentionDays["FIVE_MONTHS"] = 150] = "FIVE_MONTHS";
185 /**
186 * 6 months
187 */
188 RetentionDays[RetentionDays["SIX_MONTHS"] = 180] = "SIX_MONTHS";
189 /**
190 * 1 year
191 */
192 RetentionDays[RetentionDays["ONE_YEAR"] = 365] = "ONE_YEAR";
193 /**
194 * 13 months
195 */
196 RetentionDays[RetentionDays["THIRTEEN_MONTHS"] = 400] = "THIRTEEN_MONTHS";
197 /**
198 * 18 months
199 */
200 RetentionDays[RetentionDays["EIGHTEEN_MONTHS"] = 545] = "EIGHTEEN_MONTHS";
201 /**
202 * 2 years
203 */
204 RetentionDays[RetentionDays["TWO_YEARS"] = 731] = "TWO_YEARS";
205 /**
206 * 5 years
207 */
208 RetentionDays[RetentionDays["FIVE_YEARS"] = 1827] = "FIVE_YEARS";
209 /**
210 * 6 years
211 */
212 RetentionDays[RetentionDays["SIX_YEARS"] = 2192] = "SIX_YEARS";
213 /**
214 * 7 years
215 */
216 RetentionDays[RetentionDays["SEVEN_YEARS"] = 2557] = "SEVEN_YEARS";
217 /**
218 * 8 years
219 */
220 RetentionDays[RetentionDays["EIGHT_YEARS"] = 2922] = "EIGHT_YEARS";
221 /**
222 * 9 years
223 */
224 RetentionDays[RetentionDays["NINE_YEARS"] = 3288] = "NINE_YEARS";
225 /**
226 * 10 years
227 */
228 RetentionDays[RetentionDays["TEN_YEARS"] = 3653] = "TEN_YEARS";
229 /**
230 * Retain logs forever
231 */
232 RetentionDays[RetentionDays["INFINITE"] = 9999] = "INFINITE";
233})(RetentionDays = exports.RetentionDays || (exports.RetentionDays = {}));
234/**
235 * Define a CloudWatch Log Group
236 */
237class LogGroup extends LogGroupBase {
238 constructor(scope, id, props = {}) {
239 super(scope, id, {
240 physicalName: props.logGroupName,
241 });
242 try {
243 jsiiDeprecationWarnings._aws_cdk_aws_logs_LogGroupProps(props);
244 }
245 catch (error) {
246 if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
247 Error.captureStackTrace(error, LogGroup);
248 }
249 throw error;
250 }
251 let retentionInDays = props.retention;
252 if (retentionInDays === undefined) {
253 retentionInDays = RetentionDays.TWO_YEARS;
254 }
255 if (retentionInDays === Infinity || retentionInDays === RetentionDays.INFINITE) {
256 retentionInDays = undefined;
257 }
258 if (retentionInDays !== undefined && !core_1.Token.isUnresolved(retentionInDays) && retentionInDays <= 0) {
259 throw new Error(`retentionInDays must be positive, got ${retentionInDays}`);
260 }
261 const resource = new logs_generated_1.CfnLogGroup(this, 'Resource', {
262 kmsKeyId: props.encryptionKey?.keyArn,
263 logGroupName: this.physicalName,
264 retentionInDays,
265 });
266 resource.applyRemovalPolicy(props.removalPolicy);
267 this.logGroupArn = this.getResourceArnAttribute(resource.attrArn, {
268 service: 'logs',
269 resource: 'log-group',
270 resourceName: this.physicalName,
271 arnFormat: core_1.ArnFormat.COLON_RESOURCE_NAME,
272 });
273 this.logGroupName = this.getResourceNameAttribute(resource.ref);
274 }
275 /**
276 * Import an existing LogGroup given its ARN
277 */
278 static fromLogGroupArn(scope, id, logGroupArn) {
279 const baseLogGroupArn = logGroupArn.replace(/:\*$/, '');
280 class Import extends LogGroupBase {
281 constructor() {
282 super(...arguments);
283 this.logGroupArn = `${baseLogGroupArn}:*`;
284 this.logGroupName = core_1.Stack.of(scope).splitArn(baseLogGroupArn, core_1.ArnFormat.COLON_RESOURCE_NAME).resourceName;
285 }
286 }
287 return new Import(scope, id, {
288 environmentFromArn: baseLogGroupArn,
289 });
290 }
291 /**
292 * Import an existing LogGroup given its name
293 */
294 static fromLogGroupName(scope, id, logGroupName) {
295 const baseLogGroupName = logGroupName.replace(/:\*$/, '');
296 class Import extends LogGroupBase {
297 constructor() {
298 super(...arguments);
299 this.logGroupName = baseLogGroupName;
300 this.logGroupArn = core_1.Stack.of(scope).formatArn({
301 service: 'logs',
302 resource: 'log-group',
303 arnFormat: core_1.ArnFormat.COLON_RESOURCE_NAME,
304 resourceName: baseLogGroupName + ':*',
305 });
306 }
307 }
308 return new Import(scope, id);
309 }
310}
311exports.LogGroup = LogGroup;
312_a = JSII_RTTI_SYMBOL_1;
313LogGroup[_a] = { fqn: "@aws-cdk/aws-logs.LogGroup", version: "1.204.0" };
314//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibG9nLWdyb3VwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibG9nLWdyb3VwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLHNEQUFzRDtBQUN0RCx3Q0FBd0M7QUFFeEMsd0NBQXNGO0FBRXRGLDZDQUF5QztBQUN6QyxxREFBK0M7QUFDL0MsbURBQStDO0FBQy9DLHVDQUEwRDtBQUMxRCxxQ0FBMEM7QUFDMUMsK0RBQXdGO0FBd0V4Rjs7R0FFRztBQUNILE1BQWUsWUFBYSxTQUFRLGVBQVE7SUFjMUM7Ozs7O09BS0c7SUFDSSxTQUFTLENBQUMsRUFBVSxFQUFFLFFBQXVCLEVBQUU7UUFDcEQsT0FBTyxJQUFJLHNCQUFTLENBQUMsSUFBSSxFQUFFLEVBQUUsRUFBRTtZQUM3QixRQUFRLEVBQUUsSUFBSTtZQUNkLEdBQUcsS0FBSztTQUNULENBQUMsQ0FBQztLQUNKO0lBRUQ7Ozs7O09BS0c7SUFDSSxxQkFBcUIsQ0FBQyxFQUFVLEVBQUUsS0FBZ0M7UUFDdkUsT0FBTyxJQUFJLHdDQUFrQixDQUFDLElBQUksRUFBRSxFQUFFLEVBQUU7WUFDdEMsUUFBUSxFQUFFLElBQUk7WUFDZCxHQUFHLEtBQUs7U0FDVCxDQUFDLENBQUM7S0FDSjtJQUVEOzs7OztPQUtHO0lBQ0ksZUFBZSxDQUFDLEVBQVUsRUFBRSxLQUEwQjtRQUMzRCxPQUFPLElBQUksNEJBQVksQ0FBQyxJQUFJLEVBQUUsRUFBRSxFQUFFO1lBQ2hDLFFBQVEsRUFBRSxJQUFJO1lBQ2QsR0FBRyxLQUFLO1NBQ1QsQ0FBQyxDQUFDO0tBQ0o7SUFFRDs7Ozs7Ozs7Ozs7OztPQWFHO0lBQ0ksYUFBYSxDQUFDLFNBQWlCLEVBQUUsZUFBdUIsRUFBRSxVQUFrQjtRQUNqRixJQUFJLDRCQUFZLENBQUMsSUFBSSxFQUFFLEdBQUcsZUFBZSxJQUFJLFVBQVUsRUFBRSxFQUFFO1lBQ3pELFFBQVEsRUFBRSxJQUFJO1lBQ2QsZUFBZTtZQUNmLFVBQVU7WUFDVixhQUFhLEVBQUUsdUJB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QUFVLEVBQUUsWUFBb0I7UUFDL0UsTUFBTSxnQkFBZ0IsR0FBRyxZQUFZLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQztRQUUxRCxNQUFNLE1BQU8sU0FBUSxZQUFZO1lBQWpDOztnQkFDa0IsaUJBQVksR0FBRyxnQkFBZ0IsQ0FBQztnQkFDaEMsZ0JBQVcsR0FBRyxZQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLFNBQVMsQ0FBQztvQkFDdEQsT0FBTyxFQUFFLE1BQU07b0JBQ2YsUUFBUSxFQUFFLFdBQVc7b0JBQ3JCLFNBQVMsRUFBRSxnQkFBUyxDQUFDLG1CQUFtQjtvQkFDeEMsWUFBWSxFQUFFLGdCQUFnQixHQUFHLElBQUk7aUJBQ3RDLENBQUMsQ0FBQztZQUNMLENBQUM7U0FBQTtRQUVELE9BQU8sSUFBSSxNQUFNLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0tBQzlCOztBQWxDSCw0QkEyRUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBjbG91ZHdhdGNoIGZyb20gJ0Bhd3MtY2RrL2F3cy1jbG91ZHdhdGNoJztcbmltcG9ydCAqIGFzIGlhbSBmcm9tICdAYXdzLWNkay9hd3MtaWFtJztcbmltcG9ydCAqIGFzIGttcyBmcm9tICdAYXdzLWNkay9hd3Mta21zJztcbmltcG9ydCB7IEFybiwgQXJuRm9ybWF0LCBSZW1vdmFsUG9saWN5LCBSZXNvdXJjZSwgU3RhY2ssIFRva2VuIH0gZnJvbSAnQGF3cy1jZGsvY29yZSc7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IExvZ1N0cmVhbSB9IGZyb20gJy4vbG9nLXN0cmVhbSc7XG5pbXBvcnQgeyBDZm5Mb2dHcm91cCB9IGZyb20gJy4vbG9ncy5nZW5lcmF0ZWQnO1xuaW1wb3J0IHsgTWV0cmljRmlsdGVyIH0gZnJvbSAnLi9tZXRyaWMtZmlsdGVyJztcbmltcG9ydCB7IEZpbHRlclBhdHRlcm4sIElGaWx0ZXJQYXR0ZXJuIH0gZnJvbSAnLi9wYXR0ZXJuJztcbmltcG9ydCB7IFJlc291cmNlUG9saWN5IH0gZnJvbSAnLi9wb2xpY3knO1xuaW1wb3J0IHsgSUxvZ1N1YnNjcmlwdGlvbkRlc3RpbmF0aW9uLCBTdWJzY3JpcHRpb25GaWx0ZXIgfSBmcm9tICcuL3N1YnNjcmlwdGlvbi1maWx0ZXInO1xuXG5leHBvcnQgaW50ZXJmYWNlIElMb2dHcm91cCBleHRlbmRzIGlhbS5JUmVzb3VyY2VXaXRoUG9saWN5IHtcbiAgLyoqXG4gICAqIFRoZSBBUk4gb2YgdGhpcyBsb2cgZ3JvdXAsIHdpdGggJzoqJyBhcHBlbmRlZFxuICAgKlxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICByZWFkb25seSBsb2dHcm91cEFybjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGlzIGxvZyBncm91cFxuICAgKiBAYXR0cmlidXRlXG4gICAqL1xuICByZWFkb25seSBsb2dHcm91cE5hbWU6IHN0cmluZztcblxuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IExvZyBTdHJlYW0gZm9yIHRoaXMgTG9nIEdyb3VwXG4gICAqXG4gICAqIEBwYXJhbSBpZCBVbmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIGNvbnN0cnVjdCBpbiBpdHMgcGFyZW50XG4gICAqIEBwYXJhbSBwcm9wcyBQcm9wZXJ0aWVzIGZvciBjcmVhdGluZyB0aGUgTG9nU3RyZWFtXG4gICAqL1xuICBhZGRTdHJlYW0oaWQ6IHN0cmluZywgcHJvcHM/OiBTdHJlYW1PcHRpb25zKTogTG9nU3RyZWFtO1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgU3Vic2NyaXB0aW9uIEZpbHRlciBvbiB0aGlzIExvZyBHcm91cFxuICAgKlxuICAgKiBAcGFyYW0gaWQgVW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoZSBjb25zdHJ1Y3QgaW4gaXRzIHBhcmVudFxuICAgKiBAcGFyYW0gcHJvcHMgUHJvcGVydGllcyBmb3IgY3JlYXRpbmcgdGhlIFN1YnNjcmlwdGlvbkZpbHRlclxuICAgKi9cbiAgYWRkU3Vic2NyaXB0aW9uRmlsdGVyKGlkOiBzdHJpbmcsIHByb3BzOiBTdWJzY3JpcHRpb25GaWx0ZXJPcHRpb25zKTogU3Vic2NyaXB0aW9uRmlsdGVyO1xuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgTWV0cmljIEZpbHRlciBvbiB0aGlzIExvZyBHcm91cFxuICAgKlxuICAgKiBAcGFyYW0gaWQgVW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoZSBjb25zdHJ1Y3QgaW4gaXRzIHBhcmVudFxuICAgKiBAcGFyYW0gcHJvcHMgUHJvcGVydGllcyBmb3IgY3JlYXRpbmcgdGhlIE1ldHJpY0ZpbHRlclxuICAgKi9cbiAgYWRkTWV0cmljRmlsdGVyKGlkOiBzdHJpbmcsIHByb3BzOiBNZXRyaWNGaWx0ZXJPcHRpb25zKTogTWV0cmljRmlsdGVyO1xuXG4gIC8qKlxuICAgKiBFeHRyYWN0IGEgbWV0cmljIGZyb20gc3RydWN0dXJlZCBsb2cgZXZlbnRzIGluIHRoZSBMb2dHcm91cFxuICAgKlxuICAgKiBDcmVhdGVzIGEgTWV0cmljRmlsdGVyIG9uIHRoaXMgTG9nR3JvdXAgdGhhdCB3aWxsIGV4dHJhY3QgdGhlIHZhbHVlXG4gICAqIG9mIHRoZSBpbmRpY2F0ZWQgSlNPTiBmaWVsZCBpbiBhbGwgcmVjb3JkcyB3aGVyZSBpdCBvY2N1cnMuXG4gICAqXG4gICAqIFRoZSBtZXRyaWMgd2lsbCBiZSBhdmFpbGFibGUgaW4gQ2xvdWRXYXRjaCBNZXRyaWNzIHVuZGVyIHRoZVxuICAgKiBpbmRpY2F0ZWQgbmFtZXNwYWNlIGFuZCBuYW1lLlxuICAgKlxuICAgKiBAcGFyYW0ganNvbkZpZWxkIEpTT04gZmllbGQgdG8gZXh0cmFjdCAoZXhhbXBsZTogJyQubXlmaWVsZCcpXG4gICAqIEBwYXJhbSBtZXRyaWNOYW1lc3BhY2UgTmFtZXNwYWNlIHRvIGVtaXQgdGhlIG1ldHJpYyB1bmRlclxuICAgKiBAcGFyYW0gbWV0cmljTmFtZSBOYW1lIHRvIGVtaXQgdGhlIG1ldHJpYyB1bmRlclxuICAgKiBAcmV0dXJucyBBIE1ldHJpYyBvYmplY3QgcmVwcmVzZW50aW5nIHRoZSBleHRyYWN0ZWQgbWV0cmljXG4gICAqL1xuICBleHRyYWN0TWV0cmljKGpzb25GaWVsZDogc3RyaW5nLCBtZXRyaWNOYW1lc3BhY2U6IHN0cmluZywgbWV0cmljTmFtZTogc3RyaW5nKTogY2xvdWR3YXRjaC5NZXRyaWM7XG5cbiAgLyoqXG4gICAqIEdpdmUgcGVybWlzc2lvbnMgdG8gd3JpdGUgdG8gY3JlYXRlIGFuZCB3cml0ZSB0byBzdHJlYW1zIGluIHRoaXMgbG9nIGdyb3VwXG4gICAqL1xuICBncmFudFdyaXRlKGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50O1xuXG4gIC8qKlxuICAgKiBHaXZlIHRoZSBpbmRpY2F0ZWQgcGVybWlzc2lvbnMgb24gdGhpcyBsb2cgZ3JvdXAgYW5kIGFsbCBzdHJlYW1zXG4gICAqL1xuICBncmFudChncmFudGVlOiBpYW0uSUdyYW50YWJsZSwgLi4uYWN0aW9uczogc3RyaW5nW10pOiBpYW0uR3JhbnQ7XG5cbiAgLyoqXG4gICAqIFB1YmxpYyBtZXRob2QgdG8gZ2V0IHRoZSBwaHlzaWNhbCBuYW1lIG9mIHRoaXMgbG9nIGdyb3VwXG4gICAqL1xuICBsb2dHcm91cFBoeXNpY2FsTmFtZSgpOiBzdHJpbmc7XG59XG5cbi8qKlxuICogQW4gQ2xvdWRXYXRjaCBMb2cgR3JvdXBcbiAqL1xuYWJzdHJhY3QgY2xhc3MgTG9nR3JvdXBCYXNlIGV4dGVuZHMgUmVzb3VyY2UgaW1wbGVtZW50cyBJTG9nR3JvdXAge1xuICAvKipcbiAgICogVGhlIEFSTiBvZiB0aGlzIGxvZyBncm91cCwgd2l0aCAnOionIGFwcGVuZGVkXG4gICAqL1xuICBwdWJsaWMgYWJzdHJhY3QgcmVhZG9ubHkgbG9nR3JvdXBBcm46IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhpcyBsb2cgZ3JvdXBcbiAgICovXG4gIHB1YmxpYyBhYnN0cmFjdCByZWFkb25seSBsb2dHcm91cE5hbWU6IHN0cmluZztcblxuXG4gIHByaXZhdGUgcG9saWN5PzogUmVzb3VyY2VQb2xpY3k7XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIG5ldyBMb2cgU3RyZWFtIGZvciB0aGlzIExvZyBHcm91cFxuICAgKlxuICAgKiBAcGFyYW0gaWQgVW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoZSBjb25zdHJ1Y3QgaW4gaXRzIHBhcmVudFxuICAgKiBAcGFyYW0gcHJvcHMgUHJvcGVydGllcyBmb3IgY3JlYXRpbmcgdGhlIExvZ1N0cmVhbVxuICAgKi9cbiAgcHVibGljIGFkZFN0cmVhbShpZDogc3RyaW5nLCBwcm9wczogU3RyZWFtT3B0aW9ucyA9IHt9KTogTG9nU3RyZWFtIHtcbiAgICByZXR1cm4gbmV3IExvZ1N0cmVhbSh0aGlzLCBpZCwge1xuICAgICAgbG9nR3JvdXA6IHRoaXMsXG4gICAgICAuLi5wcm9wcyxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgU3Vic2NyaXB0aW9uIEZpbHRlciBvbiB0aGlzIExvZyBHcm91cFxuICAgKlxuICAgKiBAcGFyYW0gaWQgVW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoZSBjb25zdHJ1Y3QgaW4gaXRzIHBhcmVudFxuICAgKiBAcGFyYW0gcHJvcHMgUHJvcGVydGllcyBmb3IgY3JlYXRpbmcgdGhlIFN1YnNjcmlwdGlvbkZpbHRlclxuICAgKi9cbiAgcHVibGljIGFkZFN1YnNjcmlwdGlvbkZpbHRlcihpZDogc3RyaW5nLCBwcm9wczogU3Vic2NyaXB0aW9uRmlsdGVyT3B0aW9ucyk6IFN1YnNjcmlwdGlvbkZpbHRlciB7XG4gICAgcmV0dXJuIG5ldyBTdWJzY3JpcHRpb25GaWx0ZXIodGhpcywgaWQsIHtcbiAgICAgIGxvZ0dyb3VwOiB0aGlzLFxuICAgICAgLi4ucHJvcHMsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgbmV3IE1ldHJpYyBGaWx0ZXIgb24gdGhpcyBMb2cgR3JvdXBcbiAgICpcbiAgICogQHBhcmFtIGlkIFVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgY29uc3RydWN0IGluIGl0cyBwYXJlbnRcbiAgICogQHBhcmFtIHByb3BzIFByb3BlcnRpZXMgZm9yIGNyZWF0aW5nIHRoZSBNZXRyaWNGaWx0ZXJcbiAgICovXG4gIHB1YmxpYyBhZGRNZXRyaWNGaWx0ZXIoaWQ6IHN0cmluZywgcHJvcHM6IE1ldHJpY0ZpbHRlck9wdGlvbnMpOiBNZXRyaWNGaWx0ZXIge1xuICAgIHJldHVybiBuZXcgTWV0cmljRmlsdGVyKHRoaXMsIGlkLCB7XG4gICAgICBsb2dHcm91cDogdGhpcyxcbiAgICAgIC4uLnByb3BzLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEV4dHJhY3QgYSBtZXRyaWMgZnJvbSBzdHJ1Y3R1cmVkIGxvZyBldmVudHMgaW4gdGhlIExvZ0dyb3VwXG4gICAqXG4gICAqIENyZWF0ZXMgYSBNZXRyaWNGaWx0ZXIgb24gdGhpcyBMb2dHcm91cCB0aGF0IHdpbGwgZXh0cmFjdCB0aGUgdmFsdWVcbiAgICogb2YgdGhlIGluZGljYXRlZCBKU09OIGZpZWxkIGluIGFsbCByZWNvcmRzIHdoZXJlIGl0IG9jY3Vycy5cbiAgICpcbiAgICogVGhlIG1ldHJpYyB3aWxsIGJlIGF2YWlsYWJsZSBpbiBDbG91ZFdhdGNoIE1ldHJpY3MgdW5kZXIgdGhlXG4gICAqIGluZGljYXRlZCBuYW1lc3BhY2UgYW5kIG5hbWUuXG4gICAqXG4gICAqIEBwYXJhbSBqc29uRmllbGQgSlNPTiBmaWVsZCB0byBleHRyYWN0IChleGFtcGxlOiAnJC5teWZpZWxkJylcbiAgICogQHBhcmFtIG1ldHJpY05hbWVzcGFjZSBOYW1lc3BhY2UgdG8gZW1pdCB0aGUgbWV0cmljIHVuZGVyXG4gICAqIEBwYXJhbSBtZXRyaWNOYW1lIE5hbWUgdG8gZW1pdCB0aGUgbWV0cmljIHVuZGVyXG4gICAqIEByZXR1cm5zIEEgTWV0cmljIG9iamVjdCByZXByZXNlbnRpbmcgdGhlIGV4dHJhY3RlZCBtZXRyaWNcbiAgICovXG4gIHB1YmxpYyBleHRyYWN0TWV0cmljKGpzb25GaWVsZDogc3RyaW5nLCBtZXRyaWNOYW1lc3BhY2U6IHN0cmluZywgbWV0cmljTmFtZTogc3RyaW5nKSB7XG4gICAgbmV3IE1ldHJpY0ZpbHRlcih0aGlzLCBgJHttZXRyaWNOYW1lc3BhY2V9XyR7bWV0cmljTmFtZX1gLCB7XG4gICAgICBsb2dHcm91cDogdGhpcyxcbiAgICAgIG1ldHJpY05hbWVzcGFjZSxcbiAgICAgIG1ldHJpY05hbWUsXG4gICAgICBmaWx0ZXJQYXR0ZXJuOiBGaWx0ZXJQYXR0ZXJuLmV4aXN0cyhqc29uRmllbGQpLFxuICAgICAgbWV0cmljVmFsdWU6IGpzb25GaWVsZCxcbiAgICB9KTtcblxuICAgIHJldHVybiBuZXcgY2xvdWR3YXRjaC5NZXRyaWMoeyBtZXRyaWNOYW1lLCBuYW1lc3BhY2U6IG1ldHJpY05hbWVzcGFjZSB9KS5hdHRhY2hUbyh0aGlzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHaXZlIHBlcm1pc3Npb25zIHRvIGNyZWF0ZSBhbmQgd3JpdGUgdG8gc3RyZWFtcyBpbiB0aGlzIGxvZyBncm91cFxuICAgKi9cbiAgcHVibGljIGdyYW50V3JpdGUoZ3JhbnRlZTogaWFtLklHcmFudGFibGUpIHtcbiAgICByZXR1cm4gdGhpcy5ncmFudChncmFudGVlLCAnbG9nczpDcmVhdGVMb2dTdHJlYW0nLCAnbG9nczpQdXRMb2dFdmVudHMnKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHaXZlIHRoZSBpbmRpY2F0ZWQgcGVybWlzc2lvbnMgb24gdGhpcyBsb2cgZ3JvdXAgYW5kIGFsbCBzdHJlYW1zXG4gICAqL1xuICBwdWJsaWMgZ3JhbnQoZ3JhbnRlZTogaWFtLklHcmFudGFibGUsIC4uLmFjdGlvbnM6IHN0cmluZ1tdKSB7XG4gICAgcmV0dXJuIGlhbS5HcmFudC5hZGRUb1ByaW5jaXBhbE9yUmVzb3VyY2Uoe1xuICAgICAgZ3JhbnRlZSxcbiAgICAgIGFjdGlvbnMsXG4gICAgICAvLyBBIExvZ0dyb3VwIEFSTiBvdXQgb2YgQ2xvdWRGb3JtYXRpb24gYWxyZWFkeSBpbmNsdWRlcyBhICc6KicgYXQgdGhlIGVuZCB0byBpbmNsdWRlIHRoZSBsb2cgc3RyZWFtcyB1bmRlciB0aGUgZ3JvdXAuXG4gICAgICAvLyBTZWUgaHR0cHM6Ly9kb2NzLmF3cy5hbWF6b24uY29tL0FXU0Nsb3VkRm9ybWF0aW9uL2xhdGVzdC9Vc2VyR3VpZGUvYXdzLXJlc291cmNlLWxvZ3MtbG9nZ3JvdXAuaHRtbCN3MmFiMWMyMWMxMGM2M2M0M2MxMVxuICAgICAgcmVzb3VyY2VBcm5zOiBbdGhpcy5sb2dHcm91cEFybl0sXG4gICAgICByZXNvdXJjZTogdGhpcyxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBQdWJsaWMgbWV0aG9kIHRvIGdldCB0aGUgcGh5c2ljYWwgbmFtZSBvZiB0aGlzIGxvZyBncm91cFxuICAgKiBAcmV0dXJucyBQaHlzaWNhbCBuYW1lIG9mIGxvZyBncm91cFxuICAgKi9cbiAgcHVibGljIGxvZ0dyb3VwUGh5c2ljYWxOYW1lKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMucGh5c2ljYWxOYW1lO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYSBzdGF0ZW1lbnQgdG8gdGhlIHJlc291cmNlIHBvbGljeSBhc3NvY2lhdGVkIHdpdGggdGhpcyBsb2cgZ3JvdXAuXG4gICAqIEEgcmVzb3VyY2UgcG9saWN5IHdpbGwgYmUgYXV0b21hdGljYWxseSBjcmVhdGVkIHVwb24gdGhlIGZpcnN0IGNhbGwgdG8gYGFkZFRvUmVzb3VyY2VQb2xpY3lgLlxuICAgKlxuICAgKiBBbnkgQVJOIFByaW5jaXBhbHMgaW5zaWRlIG9mIHRoZSBzdGF0ZW1lbnQgd2lsbCBiZSBjb252ZXJ0ZWQgaW50byBBV1MgQWNjb3VudCBJRCBzdHJpbmdzXG4gICAqIGJlY2F1c2UgQ2xvdWRXYXRjaCBMb2dzIFJlc291cmNlIFBvbGljaWVzIGRvIG5vdCBhY2NlcHQgQVJOIHByaW5jaXBhbHMuXG4gICAqXG4gICAqIEBwYXJhbSBzdGF0ZW1lbnQgVGhlIHBvbGljeSBzdGF0ZW1lbnQgdG8gYWRkXG4gICAqL1xuICBwdWJsaWMgYWRkVG9SZXNvdXJjZVBvbGljeShzdGF0ZW1lbnQ6IGlhbS5Qb2xpY3lTdGF0ZW1lbnQpOiBpYW0uQWRkVG9SZXNvdXJjZVBvbGljeVJlc3VsdCB7XG4gICAgaWYgKCF0aGlzLnBvbGljeSkge1xuICAgICAgdGhpcy5wb2xpY3kgPSBuZXcgUmVzb3VyY2VQb2xpY3kodGhpcywgJ1BvbGljeScpO1xuICAgIH1cbiAgICB0aGlzLnBvbGljeS5kb2N1bWVudC5hZGRTdGF0ZW1lbnRzKHN0YXRlbWVudC5jb3B5KHtcbiAgICAgIHByaW5jaXBhbHM6IHN0YXRlbWVudC5wcmluY2lwYWxzLm1hcChwID0+IHRoaXMuY29udmVydEFyblByaW5jcGFsVG9BY2NvdW50SWQocCkpLFxuICAgIH0pKTtcbiAgICByZXR1cm4geyBzdGF0ZW1lbnRBZGRlZDogdHJ1ZSwgcG9saWN5RGVwZW5kYWJsZTogdGhpcy5wb2xpY3kgfTtcbiAgfVxuXG4gIHByaXZhdGUgY29udmVydEFyblByaW5jcGFsVG9BY2NvdW50SWQocHJpbmNpcGFsOiBpYW0uSVByaW5jaXBhbCkge1xuICAgIGlmIChwcmluY2lwYWwucHJpbmNpcGFsQWNjb3VudCkge1xuICAgICAgLy8gd2UgdXNlIEFyblByaW5jaXBhbCBoZXJlIGJlY2F1c2UgdGhlIGNvbnN0cnVjdG9yIGluc2VydHMgdGhlIGFyZ3VtZW50XG4gICAgICAvLyBpbnRvIHRoZSB0ZW1wbGF0ZSB3aXRob3V0IG11dGF0aW5nIGl0LCB3aGljaCBtZWFucyB0aGF0IHRoZXJlIGlzIG5vXG4gICAgICAvLyBBUk4gY3JlYXRlZCBieSB0aGlzIGNhbGwuXG4gICAgICByZXR1cm4gbmV3IGlhbS5Bcm5QcmluY2lwYWwocHJpbmNpcGFsLnByaW5jaXBhbEFjY291bnQpO1xuICAgIH1cblxuICAgIGlmIChwcmluY2lwYWwgaW5zdGFuY2VvZiBpYW0uQXJuUHJpbmNpcGFsKSB7XG4gICAgICBjb25zdCBwYXJzZWRBcm4gPSBBcm4uc3BsaXQocHJpbmNpcGFsLmFybiwgQXJuRm9ybWF0LlNMQVNIX1JFU09VUkNFX05BTUUpO1xuICAgICAgaWYgKHBhcnNlZEFybi5hY2NvdW50KSB7XG4gICAgICAgIHJldHVybiBuZXcgaWFtLkFyblByaW5jaXBhbChwYXJzZWRBcm4uYWNjb3VudCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHByaW5jaXBhbDtcbiAgfVxufVxuXG4vKipcbiAqIEhvdyBsb25nLCBpbiBkYXlzLCB0aGUgbG9nIGNvbnRlbnRzIHdpbGwgYmUgcmV0YWluZWQuXG4gKi9cbmV4cG9ydCBlbnVtIFJldGVudGlvbkRheXMge1xuICAvKipcbiAgICogMSBkYXlcbiAgICovXG4gIE9ORV9EQVkgPSAxLFxuXG4gIC8qKlxuICAgKiAzIGRheXNcbiAgICovXG4gIFRIUkVFX0RBWVMgPSAzLFxuXG4gIC8qKlxuICAgKiA1IGRheXNcbiAgICovXG4gIEZJVkVfREFZUyA9IDUsXG5cbiAgLyoqXG4gICAqIDEgd2Vla1xuICAgKi9cbiAgT05FX1dFRUsgPSA3LFxuXG4gIC8qKlxuICAgKiAyIHdlZWtzXG4gICAqL1xuICBUV09fV0VFS1MgPSAxNCxcblxuICAvKipcbiAgICogMSBtb250aFxuICAgKi9cbiAgT05FX01PTlRIID0gMzAsXG5cbiAgLyoqXG4gICAqIDIgbW9udGhzXG4gICAqL1xuICBUV09fTU9OVEhTID0gNjAsXG5cbiAgLyoqXG4gICAqIDMgbW9udGhzXG4gICAqL1xuICBUSFJFRV9NT05USFMgPSA5MCxcblxuICAvKipcbiAgICogNCBtb250aHNcbiAgICovXG4gIEZPVVJfTU9OVEhTID0gMTIwLFxuXG4gIC8qKlxuICAgKiA1IG1vbnRoc1xuICAgKi9cbiAgRklWRV9NT05USFMgPSAxNTAsXG5cbiAgLyoqXG4gICAqIDYgbW9udGhzXG4gICAqL1xuICBTSVhfTU9OVEhTID0gMTgwLFxuXG4gIC8qKlxuICAgKiAxIHllYXJcbiAgICovXG4gIE9ORV9ZRUFSID0gMzY1LFxuXG4gIC8qKlxuICAgKiAxMyBtb250aHNcbiAgICovXG4gIFRISVJURUVOX01PTlRIUyA9IDQwMCxcblxuICAvKipcbiAgICogMTggbW9udGhzXG4gICAqL1xuICBFSUdIVEVFTl9NT05USFMgPSA1NDUsXG5cbiAgLyoqXG4gICAqIDIgeWVhcnNcbiAgICovXG4gIFRXT19ZRUFSUyA9IDczMSxcblxuICAvKipcbiAgICogNSB5ZWFyc1xuICAgKi9cbiAgRklWRV9ZRUFSUyA9IDE4MjcsXG5cbiAgLyoqXG4gICAqIDYgeWVhcnNcbiAgICovXG4gIFNJWF9ZRUFSUyA9IDIxOTIsXG5cbiAgLyoqXG4gICAqIDcgeWVhcnNcbiAgICovXG4gIFNFVkVOX1lFQVJTID0gMjU1NyxcblxuICAvKipcbiAgICogOCB5ZWFyc1xuICAgKi9cbiAgRUlHSFRfWUVBUlMgPSAyOTIyLFxuXG4gIC8qKlxuICAgKiA5IHllYXJzXG4gICAqL1xuICBOSU5FX1lFQVJTID0gMzI4OCxcblxuICAvKipcbiAgICogMTAgeWVhcnNcbiAgICovXG4gIFRFTl9ZRUFSUyA9IDM2NTMsXG5cbiAgLyoqXG4gICAqIFJldGFpbiBsb2dzIGZvcmV2ZXJcbiAgICovXG4gIElORklOSVRFID0gOTk5OSxcbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBhIExvZ0dyb3VwXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTG9nR3JvdXBQcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgS01TIEtleSB0byBlbmNyeXB0IHRoZSBsb2cgZ3JvdXAgd2l0aC5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBsb2cgZ3JvdXAgaXMgZW5jcnlwdGVkIHdpdGggdGhlIGRlZmF1bHQgbWFzdGVyIGtleVxuICAgKi9cbiAgcmVhZG9ubHkgZW5jcnlwdGlvbktleT86IGttcy5JS2V5O1xuXG4gIC8qKlxuICAgKiBOYW1lIG9mIHRoZSBsb2cgZ3JvdXAuXG4gICAqXG4gICAqIEBkZWZhdWx0IEF1dG9tYXRpY2FsbHkgZ2VuZXJhdGVkXG4gICAqL1xuICByZWFkb25seSBsb2dHcm91cE5hbWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEhvdyBsb25nLCBpbiBkYXlzLCB0aGUgbG9nIGNvbnRlbnRzIHdpbGwgYmUgcmV0YWluZWQuXG4gICAqXG4gICAqIFRvIHJldGFpbiBhbGwgbG9ncywgc2V0IHRoaXMgdmFsdWUgdG8gUmV0ZW50aW9uRGF5cy5JTkZJTklURS5cbiAgICpcbiAgICogQGRlZmF1bHQgUmV0ZW50aW9uRGF5cy5UV09fWUVBUlNcbiAgICovXG4gIHJlYWRvbmx5IHJldGVudGlvbj86IFJldGVudGlvbkRheXM7XG5cbiAgLyoqXG4gICAqIERldGVybWluZSB0aGUgcmVtb3ZhbCBwb2xpY3kgb2YgdGhpcyBsb2cgZ3JvdXAuXG4gICAqXG4gICAqIE5vcm1hbGx5IHlvdSB3YW50IHRvIHJldGFpbiB0aGUgbG9nIGdyb3VwIHNvIHlvdSBjYW4gZGlhZ25vc2UgaXNzdWVzXG4gICAqIGZyb20gbG9ncyBldmVuIGFmdGVyIGEgZGVwbG95bWVudCB0aGF0IG5vIGxvbmdlciBpbmNsdWRlcyB0aGUgbG9nIGdyb3VwLlxuICAgKiBJbiB0aGF0IGNhc2UsIHVzZSB0aGUgbm9ybWFsIGRhdGUtYmFzZWQgcmV0ZW50aW9uIHBvbGljeSB0byBhZ2Ugb3V0IHlvdXJcbiAgICogbG9ncy5cbiAgICpcbiAgICogQGRlZmF1bHQgUmVtb3ZhbFBvbGljeS5SZXRhaW5cbiAgICovXG4gIHJlYWRvbmx5IHJlbW92YWxQb2xpY3k/OiBSZW1vdmFsUG9saWN5O1xufVxuXG4vKipcbiAqIERlZmluZSBhIENsb3VkV2F0Y2ggTG9nIEdyb3VwXG4gKi9cbmV4cG9ydCBjbGFzcyBMb2dHcm91cCBleHRlbmRzIExvZ0dyb3VwQmFzZSB7XG4gIC8qKlxuICAgKiBJbXBvcnQgYW4gZXhpc3RpbmcgTG9nR3JvdXAgZ2l2ZW4gaXRzIEFSTlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tTG9nR3JvdXBBcm4oc2NvcGU6IENvbnN0cnVjdCwgaWQ6IHN0cmluZywgbG9nR3JvdXBBcm46IHN0cmluZyk6IElMb2dHcm91cCB7XG4gICAgY29uc3QgYmFzZUxvZ0dyb3VwQXJuID0gbG9nR3JvdXBBcm4ucmVwbGFjZSgvOlxcKiQvLCAnJyk7XG5cbiAgICBjbGFzcyBJbXBvcnQgZXh0ZW5kcyBMb2dHcm91cEJhc2Uge1xuICAgICAgcHVibGljIHJlYWRvbmx5IGxvZ0dyb3VwQXJuID0gYCR7YmFzZUxvZ0dyb3VwQXJufToqYDtcbiAgICAgIHB1YmxpYyByZWFkb25seSBsb2dHcm91cE5hbWUgPSBTdGFjay5vZihzY29wZSkuc3BsaXRBcm4oYmFzZUxvZ0dyb3VwQXJuLCBBcm5Gb3JtYXQuQ09MT05fUkVTT1VSQ0VfTkFNRSkucmVzb3VyY2VOYW1lITtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IEltcG9ydChzY29wZSwgaWQsIHtcbiAgICAgIGVudmlyb25tZW50RnJvbUFybjogYmFzZUxvZ0dyb3VwQXJuLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEltcG9ydCBhbiBleGlzdGluZyBMb2dHcm91cCBnaXZlbiBpdHMgbmFtZVxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBmcm9tTG9nR3JvdXBOYW1lKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIGxvZ0dyb3VwTmFtZTogc3RyaW5nKTogSUxvZ0dyb3VwIHtcbiAgICBjb25zdCBiYXNlTG9nR3JvdXBOYW1lID0gbG9nR3JvdXBOYW1lLnJlcGxhY2UoLzpcXCokLywgJycpO1xuXG4gICAgY2xhc3MgSW1wb3J0IGV4dGVuZHMgTG9nR3JvdXBCYXNlIHtcbiAgICAgIHB1YmxpYyByZWFkb25seSBsb2dHcm91cE5hbWUgPSBiYXNlTG9nR3JvdXBOYW1lO1xuICAgICAgcHVibGljIHJlYWRvbmx5IGxvZ0dyb3VwQXJuID0gU3RhY2sub2Yoc2NvcGUpLmZvcm1hdEFybih7XG4gICAgICAgIHNlcnZpY2U6ICdsb2dzJyxcbiAgICAgICAgcmVzb3VyY2U6ICdsb2ctZ3JvdXAnLFxuICAgICAgICBhcm5Gb3JtYXQ6IEFybkZvcm1hdC5DT0xPTl9SRVNPVVJDRV9OQU1FLFxuICAgICAgICByZXNvdXJjZU5hbWU6IGJhc2VMb2dHcm91cE5hbWUgKyAnOionLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBJbXBvcnQoc2NvcGUsIGlkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgQVJOIG9mIHRoaXMgbG9nIGdyb3VwXG4gICAqL1xuICBwdWJsaWMgcmVhZG9ubHkgbG9nR3JvdXBBcm46IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhpcyBsb2cgZ3JvdXBcbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBsb2dHcm91cE5hbWU6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogTG9nR3JvdXBQcm9wcyA9IHt9KSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkLCB7XG4gICAgICBwaHlzaWNhbE5hbWU6IHByb3BzLmxvZ0dyb3VwTmFtZSxcbiAgICB9KTtcblxuICAgIGxldCByZXRlbnRpb25JbkRheXMgPSBwcm9wcy5yZXRlbnRpb247XG4gICAgaWYgKHJldGVudGlvbkluRGF5cyA9PT0gdW5kZWZpbmVkKSB7IHJldGVudGlvbkluRGF5cyA9IFJldGVudGlvbkRheXMuVFdPX1lFQVJTOyB9XG4gICAgaWYgKHJldGVudGlvbkluRGF5cyA9PT0gSW5maW5pdHkgfHwgcmV0ZW50aW9uSW5EYXlzID09PSBSZXRlbnRpb25EYXlzLklORklOSVRFKSB7IHJldGVudGlvbkluRGF5cyA9IHVuZGVmaW5lZDsgfVxuXG4gICAgaWYgKHJldGVudGlvbkluRGF5cyAhPT0gdW5kZWZpbmVkICYmICFUb2tlbi5pc1VucmVzb2x2ZWQocmV0ZW50aW9uSW5EYXlzKSAmJiByZXRlbnRpb25JbkRheXMgPD0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGByZXRlbnRpb25JbkRheXMgbXVzdCBiZSBwb3NpdGl2ZSwgZ290ICR7cmV0ZW50aW9uSW5EYXlzfWApO1xuICAgIH1cblxuICAgIGNvbnN0IHJlc291cmNlID0gbmV3IENmbkxvZ0dyb3VwKHRoaXMsICdSZXNvdXJjZScsIHtcbiAgICAgIGttc0tleUlkOiBwcm9wcy5lbmNyeXB0aW9uS2V5Py5rZXlBcm4sXG4gICAgICBsb2dHcm91cE5hbWU6IHRoaXMucGh5c2ljYWxOYW1lLFxuICAgICAgcmV0ZW50aW9uSW5EYXlzLFxuICAgIH0pO1xuXG4gICAgcmVzb3VyY2UuYXBwbHlSZW1vdmFsUG9saWN5KHByb3BzLnJlbW92YWxQb2xpY3kpO1xuXG4gICAgdGhpcy5sb2dHcm91cEFybiA9IHRoaXMuZ2V0UmVzb3VyY2VBcm5BdHRyaWJ1dGUocmVzb3VyY2UuYXR0ckFybiwge1xuICAgICAgc2VydmljZTogJ2xvZ3MnLFxuICAgICAgcmVzb3VyY2U6ICdsb2ctZ3JvdXAnLFxuICAgICAgcmVzb3VyY2VOYW1lOiB0aGlzLnBoeXNpY2FsTmFtZSxcbiAgICAgIGFybkZvcm1hdDogQXJuRm9ybWF0LkNPTE9OX1JFU09VUkNFX05BTUUsXG4gICAgfSk7XG4gICAgdGhpcy5sb2dHcm91cE5hbWUgPSB0aGlzLmdldFJlc291cmNlTmFtZUF0dHJpYnV0ZShyZXNvdXJjZS5yZWYpO1xuICB9XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgYSBuZXcgTG9nU3RyZWFtIGNyZWF0ZWQgZnJvbSBhIExvZ0dyb3VwXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3RyZWFtT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgbG9nIHN0cmVhbSB0byBjcmVhdGUuXG4gICAqXG4gICAqIFRoZSBuYW1lIG11c3QgYmUgdW5pcXVlIHdpdGhpbiB0aGUgbG9nIGdyb3VwLlxuICAgKlxuICAgKiBAZGVmYXVsdCBBdXRvbWF0aWNhbGx5IGdlbmVyYXRlZFxuICAgKi9cbiAgcmVhZG9ubHkgbG9nU3RyZWFtTmFtZT86IHN0cmluZztcbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBhIG5ldyBTdWJzY3JpcHRpb25GaWx0ZXIgY3JlYXRlZCBmcm9tIGEgTG9nR3JvdXBcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdWJzY3JpcHRpb25GaWx0ZXJPcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSBkZXN0aW5hdGlvbiB0byBzZW5kIHRoZSBmaWx0ZXJlZCBldmVudHMgdG8uXG4gICAqXG4gICAqIEZvciBleGFtcGxlLCBhIEtpbmVzaXMgc3RyZWFtIG9yIGEgTGFtYmRhIGZ1bmN0aW9uLlxuICAgKi9cbiAgcmVhZG9ubHkgZGVzdGluYXRpb246IElMb2dTdWJzY3JpcHRpb25EZXN0aW5hdGlvbjtcblxuICAvKipcbiAgICogTG9nIGV2ZW50cyBtYXRjaGluZyB0aGlzIHBhdHRlcm4gd2lsbCBiZSBzZW50IHRvIHRoZSBkZXN0aW5hdGlvbi5cbiAgICovXG4gIHJlYWRvbmx5IGZpbHRlclBhdHRlcm46IElGaWx0ZXJQYXR0ZXJuO1xufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIGEgTWV0cmljRmlsdGVyIGNyZWF0ZWQgZnJvbSBhIExvZ0dyb3VwXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTWV0cmljRmlsdGVyT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBQYXR0ZXJuIHRvIHNlYXJjaCBmb3IgbG9nIGV2ZW50cy5cbiAgICovXG4gIHJlYWRvbmx5IGZpbHRlclBhdHRlcm46IElGaWx0ZXJQYXR0ZXJuO1xuXG4gIC8qKlxuICAgKiBUaGUgbmFtZXNwYWNlIG9mIHRoZSBtZXRyaWMgdG8gZW1pdC5cbiAgICovXG4gIHJlYWRvbmx5IG1ldHJpY05hbWVzcGFjZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgbmFtZSBvZiB0aGUgbWV0cmljIHRvIGVtaXQuXG4gICAqL1xuICByZWFkb25seSBtZXRyaWNOYW1lOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSB2YWx1ZSB0byBlbWl0IGZvciB0aGUgbWV0cmljLlxuICAgKlxuICAgKiBDYW4gZWl0aGVyIGJlIGEgbGl0ZXJhbCBudW1iZXIgKHR5cGljYWxseSBcIjFcIiksIG9yIHRoZSBuYW1lIG9mIGEgZmllbGQgaW4gdGhlIHN0cnVjdHVyZVxuICAgKiB0byB0YWtlIHRoZSB2YWx1ZSBmcm9tIHRoZSBtYXRjaGVkIGV2ZW50LiBJZiB5b3UgYXJlIHVzaW5nIGEgZmllbGQgdmFsdWUsIHRoZSBmaWVsZFxuICAgKiB2YWx1ZSBtdXN0IGhhdmUgYmVlbiBtYXRjaGVkIHVzaW5nIHRoZSBwYXR0ZXJuLlxuICAgKlxuICAgKiBJZiB5b3Ugd2FudCB0byBzcGVjaWZ5IGEgZmllbGQgZnJvbSBhIG1hdGNoZWQgSlNPTiBzdHJ1Y3R1cmUsIHVzZSAnJC5maWVsZE5hbWUnLFxuICAgKiBhbmQgbWFrZSBzdXJlIHRoZSBmaWVsZCBpcyBpbiB0aGUgcGF0dGVybiAoaWYgb25seSBhcyAnJC5maWVsZE5hbWUgPSAqJykuXG4gICAqXG4gICAqIElmIHlvdSB3YW50IHRvIHNwZWNpZnkgYSBmaWVsZCBmcm9tIGEgbWF0Y2hlZCBzcGFjZS1kZWxpbWl0ZWQgc3RydWN0dXJlLFxuICAgKiB1c2UgJyRmaWVsZE5hbWUnLlxuICAgKlxuICAgKiBAZGVmYXVsdCBcIjFcIlxuICAgKi9cbiAgcmVhZG9ubHkgbWV0cmljVmFsdWU/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSB2YWx1ZSB0byBlbWl0IGlmIHRoZSBwYXR0ZXJuIGRvZXMgbm90IG1hdGNoIGEgcGFydGljdWxhciBldmVudC5cbiAgICpcbiAgICogQGRlZmF1bHQgTm8gbWV0cmljIGVtaXR0ZWQuXG4gICAqL1xuICByZWFkb25seSBkZWZhdWx0VmFsdWU/OiBudW1iZXI7XG59XG4iXX0=
\No newline at end of file