UNPKG

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
"use strict"; 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