cost-monitoring-construct
Version:
A CDK construct that helps track applications' costs separately and receive alerts in case of unpredicted resource usage
118 lines • 17.7 kB
JavaScript
;
var _a, _b;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ApplicationCostMonitoring = exports.ApplicationCostMonitoringProps = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const budget_1 = require("./budget");
const budget_strategy_1 = require("./budget-strategy");
const utils_1 = require("./utils");
class ApplicationCostMonitoringProps {
/**
* @param applicationName - the name of application to label resources with it.
* @param monthlyLimitInDollars - montly limit in US Dollors.
* @param otherStacksIncludedInBudget - optional other stack to track their resources alog with the default stack.
* @param defaultTopic - default SNS topic name. Only if provided, the BudgetStratgy creates an SNS topic and send notifications to it.
* @param subscribers - list of email address that the CostMonitoring will use to send alerts to.
* @param costAllocationTag - Tag key used to track resources' expenditure. Only if provided, it will be used to tag the application resources. Defaults to `cm:application`
*/
constructor(applicationName, monthlyLimitInDollars, subscribers, otherStacksIncludedInBudget, defaultTopic, costAllocationTag) {
this.applicationName = applicationName;
this.monthlyLimitInDollars = monthlyLimitInDollars;
this.subscribers = subscribers;
this.otherStacksIncludedInBudget = otherStacksIncludedInBudget;
this.defaultTopic = defaultTopic;
this.costAllocationTag = costAllocationTag;
}
}
exports.ApplicationCostMonitoringProps = ApplicationCostMonitoringProps;
_a = JSII_RTTI_SYMBOL_1;
ApplicationCostMonitoringProps[_a] = { fqn: "cost-monitoring-construct.ApplicationCostMonitoringProps", version: "1.2.3" };
class ApplicationCostMonitoring extends budget_strategy_1.IBudgetStrategy {
/**
* Default Application CostMonitoring class that implements daily and monthly budgets.
*
* @param stack - default stack to track its resources and it will be used to define Budget resources in it.
* @param props.applicationName - the name of application to label resources with it.
* @param props.otherStacksIncludedInBudget - optional other stack to track their resources alog with the default stack.
* @param props.monthlyLimitInDollars - montly limit in US Dollors.
* @param props.defaultTopic - default SNS topic name. Only if provided, the BudgetStratgy creates an SNS topic and send notifications to it.
* @param props.subscribers - list of email address that the CostMonitoring will use to send alerts to.
* @param props.costAllocationTag - Tag key used to track resources' expenditure. Only if provided, it will be used to tag the application resources. Defaults to `cm:application`
*
* @example
* Tracking budget for an application called `my-application`
*
* const app = new cdk.App();
* const firstStack = new FirstStack(app, 'FirstStack', {});
* const secondStack = new SecondStack(app, 'SecondStack', {});
* const costMonitoring = new ApplicationCostMonitoring(firstStack, {
* applicationName: 'my-application',
* monthlyLimitInDollars : 200,
* otherStacksToMonitor: [secondStack], // Optional (you can add as many stacks as you want)
* subscribers: ['alert@mymail.com']
* });
*
* budgetStratgy.monitor();
*/
constructor(stack, props) {
super(stack, props);
if (props.monthlyLimitInDollars < 30) {
throw RangeError("monthlyLimitInDollars must be greater than equal to 30.");
}
this.applicationName = props.applicationName;
this.otherStacks = props.otherStacksIncludedInBudget ?? [];
this.costAllocationTag = props.costAllocationTag;
}
createDailyBudgets(dailyLimit, subscribers) {
new budget_1.Budget(this.stack, `application_${this.applicationName}_daily_${dailyLimit}_%80`, {
tags: [{ key: this.applicationTagKey, value: this.applicationName }],
limit: dailyLimit,
subscribers: subscribers,
alertContdition: {
period: utils_1.TimeUnit.DAILY,
threshold: 80,
},
}).clone(`application_${this.applicationName}_daily_${dailyLimit}_%100`, {
alertContdition: { threshold: 100 },
});
}
createMonthlyBudgets(monthlyLimit, subscribers) {
new budget_1.Budget(this.stack, `application_${this.applicationName}_monthly_${monthlyLimit}_%90`, {
tags: [{ key: this.applicationTagKey, value: this.applicationName }],
limit: monthlyLimit,
subscribers: subscribers,
alertContdition: {
period: utils_1.TimeUnit.MONTHLY,
threshold: 90,
},
})
.clone(`application_${this.applicationName}_monthly_${monthlyLimit}_%95`, { alertContdition: { threshold: 95 } })
.clone(`application_${this.applicationName}_monthly_${monthlyLimit}_%98`, { alertContdition: { threshold: 98 } })
.clone(`application_${this.applicationName}_monthly_${monthlyLimit}_%99`, { alertContdition: { threshold: 99 } });
}
createQuarterlyBudgets(_quarterlyLimit, _subscribers) { }
createYearlyBudgets(_yearlyLimit, _subscribers) { }
tagAllStacks() {
[...this.otherStacks, this.stack].forEach((stack) => {
aws_cdk_lib_1.Tags.of(stack).add(this.applicationTagKey, this.applicationName);
});
}
/**
* Creates all the alarms, budgets and tags all resources with the application's name.
*/
monitor() {
this.tagAllStacks();
this.createBudgets();
}
/**
* Default key name for application tag.
*/
get applicationTagKey() {
return this.costAllocationTag || "cm:application";
}
}
exports.ApplicationCostMonitoring = ApplicationCostMonitoring;
_b = JSII_RTTI_SYMBOL_1;
ApplicationCostMonitoring[_b] = { fqn: "cost-monitoring-construct.ApplicationCostMonitoring", version: "1.2.3" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXBwbGljYXRpb24tY29zdC1tb25pdG9yaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2FwcGxpY2F0aW9uLWNvc3QtbW9uaXRvcmluZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLDZDQUFrRTtBQUNsRSxxQ0FBa0M7QUFDbEMsdURBQTBFO0FBQzFFLG1DQUFtQztBQVFuQyxNQUFhLDhCQUE4QjtJQUN6Qzs7Ozs7OztPQU9HO0lBQ0gsWUFDUyxlQUF1QixFQUN2QixxQkFBNkIsRUFDN0IsV0FBcUIsRUFDckIsMkJBQXFDLEVBQ3JDLFlBQXFCLEVBQ3JCLGlCQUEwQjtRQUwxQixvQkFBZSxHQUFmLGVBQWUsQ0FBUTtRQUN2QiwwQkFBcUIsR0FBckIscUJBQXFCLENBQVE7UUFDN0IsZ0JBQVcsR0FBWCxXQUFXLENBQVU7UUFDckIsZ0NBQTJCLEdBQTNCLDJCQUEyQixDQUFVO1FBQ3JDLGlCQUFZLEdBQVosWUFBWSxDQUFTO1FBQ3JCLHNCQUFpQixHQUFqQixpQkFBaUIsQ0FBUztJQUNoQyxDQUFDOztBQWhCTix3RUFpQkM7OztBQUVELE1BQWEseUJBQTBCLFNBQVEsaUNBQWU7SUFLNUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7T0F5Qkc7SUFDSCxZQUFZLEtBQVksRUFBRSxLQUFxQztRQUM3RCxLQUFLLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBRXBCLElBQUksS0FBSyxDQUFDLHFCQUFxQixHQUFHLEVBQUUsRUFBRTtZQUNwQyxNQUFNLFVBQVUsQ0FDZCx5REFBeUQsQ0FDMUQsQ0FBQztTQUNIO1FBRUQsSUFBSSxDQUFDLGVBQWUsR0FBRyxLQUFLLENBQUMsZUFBZSxDQUFDO1FBQzdDLElBQUksQ0FBQyxXQUFXLEdBQUcsS0FBSyxDQUFDLDJCQUEyQixJQUFJLEVBQUUsQ0FBQztRQUMzRCxJQUFJLENBQUMsaUJBQWlCLEdBQUcsS0FBSyxDQUFDLGlCQUFpQixDQUFDO0lBQ25ELENBQUM7SUFFUyxrQkFBa0IsQ0FDMUIsVUFBa0IsRUFDbEIsV0FBd0Q7UUFFeEQsSUFBSSxlQUFNLENBQ1IsSUFBSSxDQUFDLEtBQUssRUFDVixlQUFlLElBQUksQ0FBQyxlQUFlLFVBQVUsVUFBVSxNQUFNLEVBQzdEO1lBQ0UsSUFBSSxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDcEUsS0FBSyxFQUFFLFVBQVU7WUFDakIsV0FBVyxFQUFFLFdBQVc7WUFDeEIsZUFBZSxFQUFFO2dCQUNmLE1BQU0sRUFBRSxnQkFBUSxDQUFDLEtBQUs7Z0JBQ3RCLFNBQVMsRUFBRSxFQUFFO2FBQ2Q7U0FDRixDQUNGLENBQUMsS0FBSyxDQUFDLGVBQWUsSUFBSSxDQUFDLGVBQWUsVUFBVSxVQUFVLE9BQU8sRUFBRTtZQUN0RSxlQUFlLEVBQUUsRUFBRSxTQUFTLEVBQUUsR0FBRyxFQUFFO1NBQ3BDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFUyxvQkFBb0IsQ0FDNUIsWUFBb0IsRUFDcEIsV0FBd0Q7UUFFeEQsSUFBSSxlQUFNLENBQ1IsSUFBSSxDQUFDLEtBQUssRUFDVixlQUFlLElBQUksQ0FBQyxlQUFlLFlBQVksWUFBWSxNQUFNLEVBQ2pFO1lBQ0UsSUFBSSxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsSUFBSSxDQUFDLGlCQUFpQixFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDcEUsS0FBSyxFQUFFLFlBQVk7WUFDbkIsV0FBVyxFQUFFLFdBQVc7WUFDeEIsZUFBZSxFQUFFO2dCQUNmLE1BQU0sRUFBRSxnQkFBUSxDQUFDLE9BQU87Z0JBQ3hCLFNBQVMsRUFBRSxFQUFFO2FBQ2Q7U0FDRixDQUNGO2FBQ0UsS0FBSyxDQUNKLGVBQWUsSUFBSSxDQUFDLGVBQWUsWUFBWSxZQUFZLE1BQU0sRUFDakUsRUFBRSxlQUFlLEVBQUUsRUFBRSxTQUFTLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FDdkM7YUFDQSxLQUFLLENBQ0osZUFBZSxJQUFJLENBQUMsZUFBZSxZQUFZLFlBQVksTUFBTSxFQUNqRSxFQUFFLGVBQWUsRUFBRSxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUN2QzthQUNBLEtBQUssQ0FDSixlQUFlLElBQUksQ0FBQyxlQUFlLFlBQVksWUFBWSxNQUFNLEVBQ2pFLEVBQUUsZUFBZSxFQUFFLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQ3ZDLENBQUM7SUFDTixDQUFDO0lBRVMsc0JBQXNCLENBQzlCLGVBQXVCLEVBQ3ZCLFlBQW9ELElBQzdDLENBQUM7SUFDQSxtQkFBbUIsQ0FDM0IsWUFBb0IsRUFDcEIsWUFBb0QsSUFDN0MsQ0FBQztJQUVGLFlBQVk7UUFDbEIsQ0FBQyxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ2xELGtCQUFJLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQ25FLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVEOztPQUVHO0lBQ0ksT0FBTztRQUNaLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUNwQixJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDdkIsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFBYyxpQkFBaUI7UUFDN0IsT0FBTyxJQUFJLENBQUMsaUJBQWlCLElBQUksZ0JBQWdCLENBQUM7SUFDcEQsQ0FBQzs7QUE3SEgsOERBOEhDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgU3RhY2ssIFRhZ3MsIGF3c19idWRnZXRzIGFzIGJ1ZGdldHMgfSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCB7IEJ1ZGdldCB9IGZyb20gXCIuL2J1ZGdldFwiO1xuaW1wb3J0IHsgSUJ1ZGdldFN0cmF0ZWd5UHJvcHMsIElCdWRnZXRTdHJhdGVneSB9IGZyb20gXCIuL2J1ZGdldC1zdHJhdGVneVwiO1xuaW1wb3J0IHsgVGltZVVuaXQgfSBmcm9tIFwiLi91dGlsc1wiO1xuXG5leHBvcnQgaW50ZXJmYWNlIElBcHBsaWNhdGlvbkNvc3RNb25pdG9yaW5nUHJvcHMgZXh0ZW5kcyBJQnVkZ2V0U3RyYXRlZ3lQcm9wcyB7XG4gIGFwcGxpY2F0aW9uTmFtZTogc3RyaW5nO1xuICBvdGhlclN0YWNrc0luY2x1ZGVkSW5CdWRnZXQ/OiBTdGFja1tdO1xuICBjb3N0QWxsb2NhdGlvblRhZz86IHN0cmluZztcbn1cblxuZXhwb3J0IGNsYXNzIEFwcGxpY2F0aW9uQ29zdE1vbml0b3JpbmdQcm9wcyBpbXBsZW1lbnRzIElBcHBsaWNhdGlvbkNvc3RNb25pdG9yaW5nUHJvcHMge1xuICAvKipcbiAgICogQHBhcmFtIGFwcGxpY2F0aW9uTmFtZSAtIHRoZSBuYW1lIG9mIGFwcGxpY2F0aW9uIHRvIGxhYmVsIHJlc291cmNlcyB3aXRoIGl0LlxuICAgKiBAcGFyYW0gbW9udGhseUxpbWl0SW5Eb2xsYXJzIC0gbW9udGx5IGxpbWl0IGluIFVTIERvbGxvcnMuXG4gICAqIEBwYXJhbSBvdGhlclN0YWNrc0luY2x1ZGVkSW5CdWRnZXQgLSBvcHRpb25hbCBvdGhlciBzdGFjayB0byB0cmFjayB0aGVpciByZXNvdXJjZXMgYWxvZyB3aXRoIHRoZSBkZWZhdWx0IHN0YWNrLlxuICAgKiBAcGFyYW0gZGVmYXVsdFRvcGljIC0gZGVmYXVsdCBTTlMgdG9waWMgbmFtZS4gT25seSBpZiBwcm92aWRlZCwgdGhlIEJ1ZGdldFN0cmF0Z3kgY3JlYXRlcyBhbiBTTlMgdG9waWMgYW5kIHNlbmQgbm90aWZpY2F0aW9ucyB0byBpdC5cbiAgICogQHBhcmFtIHN1YnNjcmliZXJzIC0gbGlzdCBvZiBlbWFpbCBhZGRyZXNzIHRoYXQgdGhlIENvc3RNb25pdG9yaW5nIHdpbGwgdXNlIHRvIHNlbmQgYWxlcnRzIHRvLlxuICAgKiBAcGFyYW0gY29zdEFsbG9jYXRpb25UYWcgLSBUYWcga2V5IHVzZWQgdG8gdHJhY2sgcmVzb3VyY2VzJyBleHBlbmRpdHVyZS4gT25seSBpZiBwcm92aWRlZCwgaXQgd2lsbCBiZSB1c2VkIHRvIHRhZyB0aGUgYXBwbGljYXRpb24gcmVzb3VyY2VzLiBEZWZhdWx0cyB0byBgY206YXBwbGljYXRpb25gXG4gICAqL1xuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgYXBwbGljYXRpb25OYW1lOiBzdHJpbmcsXG4gICAgcHVibGljIG1vbnRobHlMaW1pdEluRG9sbGFyczogbnVtYmVyLFxuICAgIHB1YmxpYyBzdWJzY3JpYmVyczogc3RyaW5nW10sXG4gICAgcHVibGljIG90aGVyU3RhY2tzSW5jbHVkZWRJbkJ1ZGdldD86IFN0YWNrW10sXG4gICAgcHVibGljIGRlZmF1bHRUb3BpYz86IHN0cmluZyxcbiAgICBwdWJsaWMgY29zdEFsbG9jYXRpb25UYWc/OiBzdHJpbmdcbiAgKSB7fVxufVxuXG5leHBvcnQgY2xhc3MgQXBwbGljYXRpb25Db3N0TW9uaXRvcmluZyBleHRlbmRzIElCdWRnZXRTdHJhdGVneSB7XG4gIHJlYWRvbmx5IGFwcGxpY2F0aW9uTmFtZTogc3RyaW5nO1xuICBwcml2YXRlIG90aGVyU3RhY2tzOiBTdGFja1tdO1xuICBwcml2YXRlIGNvc3RBbGxvY2F0aW9uVGFnPzogc3RyaW5nXG5cbiAgLyoqXG4gICAqIERlZmF1bHQgQXBwbGljYXRpb24gQ29zdE1vbml0b3JpbmcgY2xhc3MgdGhhdCBpbXBsZW1lbnRzIGRhaWx5IGFuZCBtb250aGx5IGJ1ZGdldHMuXG4gICAqXG4gICAqIEBwYXJhbSBzdGFjayAtIGRlZmF1bHQgc3RhY2sgdG8gdHJhY2sgaXRzIHJlc291cmNlcyBhbmQgaXQgd2lsbCBiZSB1c2VkIHRvIGRlZmluZSBCdWRnZXQgcmVzb3VyY2VzIGluIGl0LlxuICAgKiBAcGFyYW0gcHJvcHMuYXBwbGljYXRpb25OYW1lIC0gdGhlIG5hbWUgb2YgYXBwbGljYXRpb24gdG8gbGFiZWwgcmVzb3VyY2VzIHdpdGggaXQuXG4gICAqIEBwYXJhbSBwcm9wcy5vdGhlclN0YWNrc0luY2x1ZGVkSW5CdWRnZXQgLSBvcHRpb25hbCBvdGhlciBzdGFjayB0byB0cmFjayB0aGVpciByZXNvdXJjZXMgYWxvZyB3aXRoIHRoZSBkZWZhdWx0IHN0YWNrLlxuICAgKiBAcGFyYW0gcHJvcHMubW9udGhseUxpbWl0SW5Eb2xsYXJzIC0gbW9udGx5IGxpbWl0IGluIFVTIERvbGxvcnMuXG4gICAqIEBwYXJhbSBwcm9wcy5kZWZhdWx0VG9waWMgLSBkZWZhdWx0IFNOUyB0b3BpYyBuYW1lLiBPbmx5IGlmIHByb3ZpZGVkLCB0aGUgQnVkZ2V0U3RyYXRneSBjcmVhdGVzIGFuIFNOUyB0b3BpYyBhbmQgc2VuZCBub3RpZmljYXRpb25zIHRvIGl0LlxuICAgKiBAcGFyYW0gcHJvcHMuc3Vic2NyaWJlcnMgLSBsaXN0IG9mIGVtYWlsIGFkZHJlc3MgdGhhdCB0aGUgQ29zdE1vbml0b3Jpbmcgd2lsbCB1c2UgdG8gc2VuZCBhbGVydHMgdG8uXG4gICAqIEBwYXJhbSBwcm9wcy5jb3N0QWxsb2NhdGlvblRhZyAtIFRhZyBrZXkgdXNlZCB0byB0cmFjayByZXNvdXJjZXMnIGV4cGVuZGl0dXJlLiBPbmx5IGlmIHByb3ZpZGVkLCBpdCB3aWxsIGJlIHVzZWQgdG8gdGFnIHRoZSBhcHBsaWNhdGlvbiByZXNvdXJjZXMuIERlZmF1bHRzIHRvIGBjbTphcHBsaWNhdGlvbmBcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogVHJhY2tpbmcgYnVkZ2V0IGZvciBhbiBhcHBsaWNhdGlvbiBjYWxsZWQgYG15LWFwcGxpY2F0aW9uYFxuICAgKlxuICAgKiBjb25zdCBhcHAgPSBuZXcgY2RrLkFwcCgpO1xuICAgKiBjb25zdCBmaXJzdFN0YWNrID0gbmV3IEZpcnN0U3RhY2soYXBwLCAnRmlyc3RTdGFjaycsIHt9KTtcbiAgICogY29uc3Qgc2Vjb25kU3RhY2sgPSBuZXcgU2Vjb25kU3RhY2soYXBwLCAnU2Vjb25kU3RhY2snLCB7fSk7XG4gICAqIGNvbnN0IGNvc3RNb25pdG9yaW5nID0gbmV3IEFwcGxpY2F0aW9uQ29zdE1vbml0b3JpbmcoZmlyc3RTdGFjaywge1xuICAgKiAgIGFwcGxpY2F0aW9uTmFtZTogJ215LWFwcGxpY2F0aW9uJyxcbiAgICogICBtb250aGx5TGltaXRJbkRvbGxhcnMgOiAyMDAsXG4gICAqICAgb3RoZXJTdGFja3NUb01vbml0b3I6IFtzZWNvbmRTdGFja10sIC8vIE9wdGlvbmFsICh5b3UgY2FuIGFkZCBhcyBtYW55IHN0YWNrcyBhcyB5b3Ugd2FudClcbiAgICogICBzdWJzY3JpYmVyczogWydhbGVydEBteW1haWwuY29tJ11cbiAgICogfSk7XG4gICAqXG4gICAqIGJ1ZGdldFN0cmF0Z3kubW9uaXRvcigpO1xuICAgKi9cbiAgY29uc3RydWN0b3Ioc3RhY2s6IFN0YWNrLCBwcm9wczogQXBwbGljYXRpb25Db3N0TW9uaXRvcmluZ1Byb3BzKSB7XG4gICAgc3VwZXIoc3RhY2ssIHByb3BzKTtcblxuICAgIGlmIChwcm9wcy5tb250aGx5TGltaXRJbkRvbGxhcnMgPCAzMCkge1xuICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcbiAgICAgICAgXCJtb250aGx5TGltaXRJbkRvbGxhcnMgbXVzdCBiZSBncmVhdGVyIHRoYW4gZXF1YWwgdG8gMzAuXCJcbiAgICAgICk7XG4gICAgfVxuXG4gICAgdGhpcy5hcHBsaWNhdGlvbk5hbWUgPSBwcm9wcy5hcHBsaWNhdGlvbk5hbWU7XG4gICAgdGhpcy5vdGhlclN0YWNrcyA9IHByb3BzLm90aGVyU3RhY2tzSW5jbHVkZWRJbkJ1ZGdldCA/PyBbXTtcbiAgICB0aGlzLmNvc3RBbGxvY2F0aW9uVGFnID0gcHJvcHMuY29zdEFsbG9jYXRpb25UYWc7XG4gIH1cblxuICBwcm90ZWN0ZWQgY3JlYXRlRGFpbHlCdWRnZXRzKFxuICAgIGRhaWx5TGltaXQ6IG51bWJlcixcbiAgICBzdWJzY3JpYmVyczogQXJyYXk8YnVkZ2V0cy5DZm5CdWRnZXQuU3Vic2NyaWJlclByb3BlcnR5PlxuICApOiB2b2lkIHtcbiAgICBuZXcgQnVkZ2V0KFxuICAgICAgdGhpcy5zdGFjayxcbiAgICAgIGBhcHBsaWNhdGlvbl8ke3RoaXMuYXBwbGljYXRpb25OYW1lfV9kYWlseV8ke2RhaWx5TGltaXR9XyU4MGAsXG4gICAgICB7XG4gICAgICAgIHRhZ3M6IFt7IGtleTogdGhpcy5hcHBsaWNhdGlvblRhZ0tleSwgdmFsdWU6IHRoaXMuYXBwbGljYXRpb25OYW1lIH1dLFxuICAgICAgICBsaW1pdDogZGFpbHlMaW1pdCxcbiAgICAgICAgc3Vic2NyaWJlcnM6IHN1YnNjcmliZXJzLFxuICAgICAgICBhbGVydENvbnRkaXRpb246IHtcbiAgICAgICAgICBwZXJpb2Q6IFRpbWVVbml0LkRBSUxZLFxuICAgICAgICAgIHRocmVzaG9sZDogODAsXG4gICAgICAgIH0sXG4gICAgICB9XG4gICAgKS5jbG9uZShgYXBwbGljYXRpb25fJHt0aGlzLmFwcGxpY2F0aW9uTmFtZX1fZGFpbHlfJHtkYWlseUxpbWl0fV8lMTAwYCwge1xuICAgICAgYWxlcnRDb250ZGl0aW9uOiB7IHRocmVzaG9sZDogMTAwIH0sXG4gICAgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgY3JlYXRlTW9udGhseUJ1ZGdldHMoXG4gICAgbW9udGhseUxpbWl0OiBudW1iZXIsXG4gICAgc3Vic2NyaWJlcnM6IEFycmF5PGJ1ZGdldHMuQ2ZuQnVkZ2V0LlN1YnNjcmliZXJQcm9wZXJ0eT5cbiAgKTogdm9pZCB7XG4gICAgbmV3IEJ1ZGdldChcbiAgICAgIHRoaXMuc3RhY2ssXG4gICAgICBgYXBwbGljYXRpb25fJHt0aGlzLmFwcGxpY2F0aW9uTmFtZX1fbW9udGhseV8ke21vbnRobHlMaW1pdH1fJTkwYCxcbiAgICAgIHtcbiAgICAgICAgdGFnczogW3sga2V5OiB0aGlzLmFwcGxpY2F0aW9uVGFnS2V5LCB2YWx1ZTogdGhpcy5hcHBsaWNhdGlvbk5hbWUgfV0sXG4gICAgICAgIGxpbWl0OiBtb250aGx5TGltaXQsXG4gICAgICAgIHN1YnNjcmliZXJzOiBzdWJzY3JpYmVycyxcbiAgICAgICAgYWxlcnRDb250ZGl0aW9uOiB7XG4gICAgICAgICAgcGVyaW9kOiBUaW1lVW5pdC5NT05USExZLFxuICAgICAgICAgIHRocmVzaG9sZDogOTAsXG4gICAgICAgIH0sXG4gICAgICB9XG4gICAgKVxuICAgICAgLmNsb25lKFxuICAgICAgICBgYXBwbGljYXRpb25fJHt0aGlzLmFwcGxpY2F0aW9uTmFtZX1fbW9udGhseV8ke21vbnRobHlMaW1pdH1fJTk1YCxcbiAgICAgICAgeyBhbGVydENvbnRkaXRpb246IHsgdGhyZXNob2xkOiA5NSB9IH1cbiAgICAgIClcbiAgICAgIC5jbG9uZShcbiAgICAgICAgYGFwcGxpY2F0aW9uXyR7dGhpcy5hcHBsaWNhdGlvbk5hbWV9X21vbnRobHlfJHttb250aGx5TGltaXR9XyU5OGAsXG4gICAgICAgIHsgYWxlcnRDb250ZGl0aW9uOiB7IHRocmVzaG9sZDogOTggfSB9XG4gICAgICApXG4gICAgICAuY2xvbmUoXG4gICAgICAgIGBhcHBsaWNhdGlvbl8ke3RoaXMuYXBwbGljYXRpb25OYW1lfV9tb250aGx5XyR7bW9udGhseUxpbWl0fV8lOTlgLFxuICAgICAgICB7IGFsZXJ0Q29udGRpdGlvbjogeyB0aHJlc2hvbGQ6IDk5IH0gfVxuICAgICAgKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBjcmVhdGVRdWFydGVybHlCdWRnZXRzKFxuICAgIF9xdWFydGVybHlMaW1pdDogbnVtYmVyLFxuICAgIF9zdWJzY3JpYmVyczogYnVkZ2V0cy5DZm5CdWRnZXQuU3Vic2NyaWJlclByb3BlcnR5W11cbiAgKTogdm9pZCB7fVxuICBwcm90ZWN0ZWQgY3JlYXRlWWVhcmx5QnVkZ2V0cyhcbiAgICBfeWVhcmx5TGltaXQ6IG51bWJlcixcbiAgICBfc3Vic2NyaWJlcnM6IGJ1ZGdldHMuQ2ZuQnVkZ2V0LlN1YnNjcmliZXJQcm9wZXJ0eVtdXG4gICk6IHZvaWQge31cblxuICBwcml2YXRlIHRhZ0FsbFN0YWNrcygpOiB2b2lkIHtcbiAgICBbLi4udGhpcy5vdGhlclN0YWNrcywgdGhpcy5zdGFja10uZm9yRWFjaCgoc3RhY2spID0+IHtcbiAgICAgIFRhZ3Mub2Yoc3RhY2spLmFkZCh0aGlzLmFwcGxpY2F0aW9uVGFnS2V5LCB0aGlzLmFwcGxpY2F0aW9uTmFtZSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlcyBhbGwgdGhlIGFsYXJtcywgYnVkZ2V0cyBhbmQgdGFncyBhbGwgcmVzb3VyY2VzIHdpdGggdGhlIGFwcGxpY2F0aW9uJ3MgbmFtZS5cbiAgICovXG4gIHB1YmxpYyBtb25pdG9yKCk6IHZvaWQge1xuICAgIHRoaXMudGFnQWxsU3RhY2tzKCk7XG4gICAgdGhpcy5jcmVhdGVCdWRnZXRzKCk7XG4gIH1cblxuICAvKipcbiAgICogRGVmYXVsdCBrZXkgbmFtZSBmb3IgYXBwbGljYXRpb24gdGFnLlxuICAgKi9cbiAgcHJvdGVjdGVkIGdldCBhcHBsaWNhdGlvblRhZ0tleSgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmNvc3RBbGxvY2F0aW9uVGFnIHx8IFwiY206YXBwbGljYXRpb25cIjtcbiAgfVxufVxuIl19