@gammarers/aws-daily-cost-usage-report-stack 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,13 @@
1
+ import * as lambda from 'aws-cdk-lib/aws-lambda';
2
+ import { Construct } from 'constructs';
3
+ /**
4
+ * Props for CostReporterFunction
5
+ */
6
+ export interface CostReporterFunctionProps extends lambda.FunctionOptions {
7
+ }
8
+ /**
9
+ * An AWS Lambda function which executes src/funcs/cost-reporter.
10
+ */
11
+ export declare class CostReporterFunction extends lambda.Function {
12
+ constructor(scope: Construct, id: string, props?: CostReporterFunctionProps);
13
+ }
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CostReporterFunction = void 0;
4
+ // ~~ Generated by projen. To modify, edit .projenrc.ts and run "npx projen".
5
+ const path = require("path");
6
+ const lambda = require("aws-cdk-lib/aws-lambda");
7
+ /**
8
+ * An AWS Lambda function which executes src/funcs/cost-reporter.
9
+ */
10
+ class CostReporterFunction extends lambda.Function {
11
+ constructor(scope, id, props) {
12
+ super(scope, id, {
13
+ description: 'src/funcs/cost-reporter.lambda.ts',
14
+ ...props,
15
+ runtime: new lambda.Runtime('nodejs20.x', lambda.RuntimeFamily.NODEJS),
16
+ handler: 'index.handler',
17
+ code: lambda.Code.fromAsset(path.join(__dirname, '../../assets/funcs/cost-reporter.lambda')),
18
+ });
19
+ this.addEnvironment('AWS_NODEJS_CONNECTION_REUSE_ENABLED', '1', { removeInEdge: true });
20
+ }
21
+ }
22
+ exports.CostReporterFunction = CostReporterFunction;
23
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29zdC1yZXBvcnRlci1mdW5jdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9mdW5jcy9jb3N0LXJlcG9ydGVyLWZ1bmN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDZFQUE2RTtBQUM3RSw2QkFBNkI7QUFDN0IsaURBQWlEO0FBU2pEOztHQUVHO0FBQ0gsTUFBYSxvQkFBcUIsU0FBUSxNQUFNLENBQUMsUUFBUTtJQUN2RCxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQWlDO1FBQ3pFLEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxFQUFFO1lBQ2YsV0FBVyxFQUFFLG1DQUFtQztZQUNoRCxHQUFHLEtBQUs7WUFDUixPQUFPLEVBQUUsSUFBSSxNQUFNLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRSxNQUFNLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQztZQUN0RSxPQUFPLEVBQUUsZUFBZTtZQUN4QixJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUseUNBQXlDLENBQUMsQ0FBQztTQUM3RixDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsY0FBYyxDQUFDLHFDQUFxQyxFQUFFLEdBQUcsRUFBRSxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQzFGLENBQUM7Q0FDRjtBQVhELG9EQVdDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gfn4gR2VuZXJhdGVkIGJ5IHByb2plbi4gVG8gbW9kaWZ5LCBlZGl0IC5wcm9qZW5yYy50cyBhbmQgcnVuIFwibnB4IHByb2plblwiLlxuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCAqIGFzIGxhbWJkYSBmcm9tICdhd3MtY2RrLWxpYi9hd3MtbGFtYmRhJztcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuXG4vKipcbiAqIFByb3BzIGZvciBDb3N0UmVwb3J0ZXJGdW5jdGlvblxuICovXG5leHBvcnQgaW50ZXJmYWNlIENvc3RSZXBvcnRlckZ1bmN0aW9uUHJvcHMgZXh0ZW5kcyBsYW1iZGEuRnVuY3Rpb25PcHRpb25zIHtcbn1cblxuLyoqXG4gKiBBbiBBV1MgTGFtYmRhIGZ1bmN0aW9uIHdoaWNoIGV4ZWN1dGVzIHNyYy9mdW5jcy9jb3N0LXJlcG9ydGVyLlxuICovXG5leHBvcnQgY2xhc3MgQ29zdFJlcG9ydGVyRnVuY3Rpb24gZXh0ZW5kcyBsYW1iZGEuRnVuY3Rpb24ge1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wcz86IENvc3RSZXBvcnRlckZ1bmN0aW9uUHJvcHMpIHtcbiAgICBzdXBlcihzY29wZSwgaWQsIHtcbiAgICAgIGRlc2NyaXB0aW9uOiAnc3JjL2Z1bmNzL2Nvc3QtcmVwb3J0ZXIubGFtYmRhLnRzJyxcbiAgICAgIC4uLnByb3BzLFxuICAgICAgcnVudGltZTogbmV3IGxhbWJkYS5SdW50aW1lKCdub2RlanMyMC54JywgbGFtYmRhLlJ1bnRpbWVGYW1pbHkuTk9ERUpTKSxcbiAgICAgIGhhbmRsZXI6ICdpbmRleC5oYW5kbGVyJyxcbiAgICAgIGNvZGU6IGxhbWJkYS5Db2RlLmZyb21Bc3NldChwYXRoLmpvaW4oX19kaXJuYW1lLCAnLi4vLi4vYXNzZXRzL2Z1bmNzL2Nvc3QtcmVwb3J0ZXIubGFtYmRhJykpLFxuICAgIH0pO1xuICAgIHRoaXMuYWRkRW52aXJvbm1lbnQoJ0FXU19OT0RFSlNfQ09OTkVDVElPTl9SRVVTRV9FTkFCTEVEJywgJzEnLCB7IHJlbW92ZUluRWRnZTogdHJ1ZSB9KTtcbiAgfVxufSJdfQ==
@@ -0,0 +1,13 @@
1
+ import { Context } from 'aws-lambda';
2
+ export interface EventInput {
3
+ readonly Type: EventInputType;
4
+ }
5
+ export declare enum EventInputType {
6
+ ACCOUNTS = "Accounts",
7
+ SERVICES = "Services"
8
+ }
9
+ export interface MessageAttachmentField {
10
+ readonly title: string;
11
+ readonly value: string;
12
+ }
13
+ export declare const handler: (event: EventInput, context: Context) => Promise<string | Error>;
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handler = exports.EventInputType = void 0;
4
+ const client_cost_explorer_1 = require("@aws-sdk/client-cost-explorer");
5
+ const web_api_1 = require("@slack/web-api");
6
+ const aws_lambda_errors_1 = require("@yicr/aws-lambda-errors");
7
+ const get_billing_command_1 = require("./lib/get-billing-command");
8
+ const get_date_range_1 = require("./lib/get-date-range");
9
+ var EventInputType;
10
+ (function (EventInputType) {
11
+ EventInputType["ACCOUNTS"] = "Accounts";
12
+ EventInputType["SERVICES"] = "Services";
13
+ })(EventInputType || (exports.EventInputType = EventInputType = {}));
14
+ const ceClient = new client_cost_explorer_1.CostExplorerClient({
15
+ region: 'us-east-1',
16
+ });
17
+ const handler = async (event, context) => {
18
+ console.log(`Event: ${JSON.stringify(event, null, 2)}`);
19
+ console.log(`Context: ${JSON.stringify(context, null, 2)}`);
20
+ // do validation
21
+ if (!process.env.SLACK_TOKEN) {
22
+ throw new aws_lambda_errors_1.MissingEnvironmentVariableError('missing environment variable SLACK_TOKEN.');
23
+ }
24
+ if (!process.env.SLACK_CHANNEL) {
25
+ throw new aws_lambda_errors_1.MissingEnvironmentVariableError('missing environment variable SLACK_CHANNEL.');
26
+ }
27
+ if (!event.Type) {
28
+ throw new aws_lambda_errors_1.MissingInputVariableError('missing input variable Type');
29
+ }
30
+ else {
31
+ if (!Object.values(EventInputType).includes(event.Type)) {
32
+ throw new aws_lambda_errors_1.InvalidInputVariableFormatError('invalid input variable format is Accounts or Services.');
33
+ }
34
+ }
35
+ // 👇Calculate Date Range
36
+ const dateRange = new get_date_range_1.GetDateRange();
37
+ console.log(`DateRange::${JSON.stringify(dateRange, null, 2)}`);
38
+ // 👇Get Total Billing
39
+ const totalBilling = await (new get_billing_command_1.GetTotalBilling(ceClient)).execute(dateRange);
40
+ console.log(`TotalBilling: ${JSON.stringify(totalBilling, null, 2)}`);
41
+ const fields = await (async () => {
42
+ switch (event.Type) {
43
+ case EventInputType.ACCOUNTS:
44
+ // 👇Get Accounts Billings
45
+ const accountBillings = await (new get_billing_command_1.GetAccountBillings(ceClient).execute(dateRange));
46
+ console.log(`AccountBillings: ${JSON.stringify(accountBillings, null, 2)}`);
47
+ return accountBillings?.map((value) => {
48
+ return {
49
+ title: value.account,
50
+ value: `${value.amount} ${value.unit}`,
51
+ };
52
+ });
53
+ case EventInputType.SERVICES:
54
+ // 👇Get Service Billings
55
+ const serviceBillings = await (new get_billing_command_1.GetServiceBilling(ceClient)).execute(dateRange);
56
+ console.log(`ServiceBilling: ${JSON.stringify(serviceBillings, null, 2)}`);
57
+ return serviceBillings?.map((value) => {
58
+ return {
59
+ title: value.service,
60
+ value: `${value.amount} ${value.unit}`,
61
+ };
62
+ });
63
+ }
64
+ })();
65
+ const client = new web_api_1.WebClient(process.env.SLACK_TOKEN);
66
+ const channel = process.env.SLACK_CHANNEL;
67
+ // Send the notification
68
+ await (async () => {
69
+ const result = await client.chat.postMessage({
70
+ channel,
71
+ icon_emoji: ':money-with-wings:',
72
+ text: `AWS Cost Reports (${dateRange.start} - ${dateRange.end})`,
73
+ attachments: [
74
+ {
75
+ title: ':moneybag: Total',
76
+ text: `${totalBilling?.amount} ${totalBilling?.unit}`,
77
+ color: '#ff8c00',
78
+ },
79
+ ],
80
+ });
81
+ if (result.ok) {
82
+ await client.chat.postMessage({
83
+ channel,
84
+ thread_ts: result.ts,
85
+ attachments: [
86
+ {
87
+ color: '#ffd700',
88
+ fields: fields?.map((filed) => {
89
+ return {
90
+ title: `:aws: ${filed.title}`,
91
+ value: filed.value,
92
+ short: false,
93
+ };
94
+ }),
95
+ },
96
+ ],
97
+ });
98
+ }
99
+ })();
100
+ return 'OK';
101
+ };
102
+ exports.handler = handler;
103
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29zdC1yZXBvcnRlci5sYW1iZGEuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZnVuY3MvY29zdC1yZXBvcnRlci5sYW1iZGEudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsd0VBQW1FO0FBQ25FLDRDQUEyQztBQUMzQywrREFBc0k7QUFFdEksbUVBQW1HO0FBQ25HLHlEQUFvRDtBQU1wRCxJQUFZLGNBR1g7QUFIRCxXQUFZLGNBQWM7SUFDeEIsdUNBQXFCLENBQUE7SUFDckIsdUNBQXFCLENBQUE7QUFDdkIsQ0FBQyxFQUhXLGNBQWMsOEJBQWQsY0FBYyxRQUd6QjtBQU9ELE1BQU0sUUFBUSxHQUFHLElBQUkseUNBQWtCLENBQUM7SUFDdEMsTUFBTSxFQUFFLFdBQVc7Q0FDcEIsQ0FBQyxDQUFDO0FBRUksTUFBTSxPQUFPLEdBQUcsS0FBSyxFQUFFLEtBQWlCLEVBQUUsT0FBZ0IsRUFBMkIsRUFBRTtJQUM1RixPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUN4RCxPQUFPLENBQUMsR0FBRyxDQUFDLFlBQVksSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUU1RCxnQkFBZ0I7SUFDaEIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDN0IsTUFBTSxJQUFJLG1EQUErQixDQUFDLDJDQUEyQyxDQUFDLENBQUM7SUFDekYsQ0FBQztJQUNELElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQy9CLE1BQU0sSUFBSSxtREFBK0IsQ0FBQyw2Q0FBNkMsQ0FBQyxDQUFDO0lBQzNGLENBQUM7SUFDRCxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFD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SUFBSSxFQUFFLHFCQUFxQixTQUFTLENBQUMsS0FBSyxNQUFNLFNBQVMsQ0FBQyxHQUFHLEdBQUc7WUFDaEUsV0FBVyxFQUFFO2dCQUNYO29CQUNFLEtBQUssRUFBRSxrQkFBa0I7b0JBQ3pCLElBQUksRUFBRSxHQUFHLFlBQVksRUFBRSxNQUFNLElBQUksWUFBWSxFQUFFLElBQUksRUFBRTtvQkFDckQsS0FBSyxFQUFFLFNBQVM7aUJBQ2pCO2FBQ0Y7U0FDRixDQUFDLENBQUM7UUFDSCxJQUFJLE1BQU0sQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUNkLE1BQU0sTUFBTSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUM7Z0JBQzVCLE9BQU87Z0JBQ1AsU0FBUyxFQUFFLE1BQU0sQ0FBQyxFQUFFO2dCQUNwQixXQUFXLEVBQUU7b0JBQ1g7d0JBQ0UsS0FBSyxFQUFFLFNBQVM7d0JBQ2hCLE1BQU0sRUFBRSxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7NEJBQzVCLE9BQU87Z0NBQ0wsS0FBSyxFQUFFLFNBQVMsS0FBSyxDQUFDLEtBQUssRUFBRTtnQ0FDN0IsS0FBSyxFQUFFLEtBQUssQ0FBQyxLQUFLO2dDQUNsQixLQUFLLEVBQUUsS0FBSzs2QkFDYixDQUFDO3dCQUNKLENBQUMsQ0FBQztxQkFDSDtpQkFDRjthQUNGLENBQUMsQ0FBQztRQUNMLENBQUM7SUFDSCxDQUFDLENBQUMsRUFBRSxDQUFDO0lBRUwsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDLENBQUM7QUEzRlcsUUFBQSxPQUFPLFdBMkZsQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvc3RFeHBsb3JlckNsaWVudCB9IGZyb20gJ0Bhd3Mtc2RrL2NsaWVudC1jb3N0LWV4cGxvcmVyJztcbmltcG9ydCB7IFdlYkNsaWVudCB9IGZyb20gJ0BzbGFjay93ZWItYXBpJztcbmltcG9ydCB7IE1pc3NpbmdFbnZpcm9ubWVudFZhcmlhYmxlRXJyb3IsIE1pc3NpbmdJbnB1dFZhcmlhYmxlRXJyb3IsIEludmFsaWRJbnB1dFZhcmlhYmxlRm9ybWF0RXJyb3IgfSBmcm9tICdAeWljci9hd3MtbGFtYmRhLWVycm9ycyc7XG5pbXBvcnQgeyBDb250ZXh0IH0gZnJvbSAnYXdzLWxhbWJkYSc7XG5pbXBvcnQgeyBHZXRBY2NvdW50QmlsbGluZ3MsIEdldFNlcnZpY2VCaWxsaW5nLCBHZXRUb3RhbEJpbGxpbmcgfSBmcm9tICcuL2xpYi9nZXQtYmlsbGluZy1jb21tYW5kJztcbmltcG9ydCB7IEdldERhdGVSYW5nZSB9IGZyb20gJy4vbGliL2dldC1kYXRlLXJhbmdlJztcblxuZXhwb3J0IGludGVyZmFjZSBFdmVudElucHV0IHtcbiAgcmVhZG9ubHkgVHlwZTogRXZlbnRJbnB1dFR5cGU7XG59XG5cbmV4cG9ydCBlbnVtIEV2ZW50SW5wdXRUeXBlIHtcbiAgQUNDT1VOVFMgPSAnQWNjb3VudHMnLFxuICBTRVJWSUNFUyA9ICdTZXJ2aWNlcycsXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTWVzc2FnZUF0dGFjaG1lbnRGaWVsZCB7XG4gIHJlYWRvbmx5IHRpdGxlOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHZhbHVlOiBzdHJpbmc7XG59XG5cbmNvbnN0IGNlQ2xpZW50ID0gbmV3IENvc3RFeHBsb3JlckNsaWVudCh7XG4gIHJlZ2lvbjogJ3VzLWVhc3QtMScsXG59KTtcblxuZXhwb3J0IGNvbnN0IGhhbmRsZXIgPSBhc3luYyAoZXZlbnQ6IEV2ZW50SW5wdXQsIGNvbnRleHQ6IENvbnRleHQpOiBQcm9taXNlPHN0cmluZyB8IEVycm9yPiA9PiB7XG4gIGNvbnNvbGUubG9nKGBFdmVudDogJHtKU09OLnN0cmluZ2lmeShldmVudCwgbnVsbCwgMil9YCk7XG4gIGNvbnNvbGUubG9nKGBDb250ZXh0OiAke0pTT04uc3RyaW5naWZ5KGNvbnRleHQsIG51bGwsIDIpfWApO1xuXG4gIC8vIGRvIHZhbGlkYXRpb25cbiAgaWYgKCFwcm9jZXNzLmVudi5TTEFDS19UT0tFTikge1xuICAgIHRocm93IG5ldyBNaXNzaW5nRW52aXJvbm1lbnRWYXJpYWJsZUVycm9yKCdtaXNzaW5nIGVudmlyb25tZW50IHZhcmlhYmxlIFNMQUNLX1RPS0VOLicpO1xuICB9XG4gIGlmICghcHJvY2Vzcy5lbnYuU0xBQ0tfQ0hBTk5FTCkge1xuICAgIHRocm93IG5ldyBNaXNzaW5nRW52aXJvbm1lbnRWYXJpYWJsZUVycm9yKCdtaXNzaW5nIGVudmlyb25tZW50IHZhcmlhYmxlIFNMQUNLX0NIQU5ORUwuJyk7XG4gIH1cbiAgaWYgKCFldmVudC5UeXBlKSB7XG4gICAgdGhyb3cgbmV3IE1pc3NpbmdJbnB1dFZhcmlhYmxlRXJyb3IoJ21pc3NpbmcgaW5wdXQgdmFyaWFibGUgVHlwZScpO1xuICB9IGVsc2Uge1xuICAgIGlmICghT2JqZWN0LnZhbHVlcyhFdmVudElucHV0VHlwZSkuaW5jbHVkZXMoZXZlbnQuVHlwZSkpIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkSW5wdXRWYXJpYWJsZUZvcm1hdEVycm9yKCdpbnZhbGlkIGlucHV0IHZhcmlhYmxlIGZvcm1hdCBpcyBBY2NvdW50cyBvciBTZXJ2aWNlcy4nKTtcbiAgICB9XG4gIH1cblxuICAvLyDwn5GHQ2FsY3VsYXRlIERhdGUgUmFuZ2VcbiAgY29uc3QgZGF0ZVJhbmdlID0gbmV3IEdldERhdGVSYW5nZSgpO1xuICBjb25zb2xlLmxvZyhgRGF0ZVJhbmdlOjoke0pTT04uc3RyaW5naWZ5KGRhdGVSYW5nZSwgbnVsbCwgMil9YCk7XG5cbiAgLy8g8J+Rh0dldCBUb3RhbCBCaWxsaW5nXG4gIGNvbnN0IHRvdGFsQmlsbGluZyA9IGF3YWl0IChuZXcgR2V0VG90YWxCaWxsaW5nKGNlQ2xpZW50KSkuZXhlY3V0ZShkYXRlUmFuZ2UpO1xuICBjb25zb2xlLmxvZyhgVG90YWxCaWxsaW5nOiAke0pTT04uc3RyaW5naWZ5KHRvdGFsQmlsbGluZywgbnVsbCwgMil9YCk7XG5cbiAgY29uc3QgZmllbGRzOiBNZXNzYWdlQXR0YWNobWVudEZpZWxkW10gfCB1bmRlZmluZWQgPSBhd2FpdCAoYXN5bmMgKCkgPT4ge1xuICAgIHN3aXRjaCAoZXZlbnQuVHlwZSkge1xuICAgICAgY2FzZSBFdmVudElucHV0VHlwZS5BQ0NPVU5UUzpcbiAgICAgICAgLy8g8J+Rh0dldCBBY2NvdW50cyBCaWxsaW5nc1xuICAgICAgICBjb25zdCBhY2NvdW50QmlsbGluZ3MgPSBhd2FpdCAobmV3IEdldEFjY291bnRCaWxsaW5ncyhjZUNsaWVudCkuZXhlY3V0ZShkYXRlUmFuZ2UpKTtcbiAgICAgICAgY29uc29sZS5sb2coYEFjY291bnRCaWxsaW5nczogJHtKU09OLnN0cmluZ2lmeShhY2NvdW50QmlsbGluZ3MsIG51bGwsIDIpfWApO1xuICAgICAgICByZXR1cm4gYWNjb3VudEJpbGxpbmdzPy5tYXAoKHZhbHVlKSA9PiB7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHRpdGxlOiB2YWx1ZS5hY2NvdW50LFxuICAgICAgICAgICAgdmFsdWU6IGAke3ZhbHVlLmFtb3VudH0gJHt2YWx1ZS51bml0fWAsXG4gICAgICAgICAgfTtcbiAgICAgICAgfSk7XG4gICAgICBjYXNlIEV2ZW50SW5wdXRUeXBlLlNFUlZJQ0VTOlxuICAgICAgICAvLyDwn5GHR2V0IFNlcnZpY2UgQmlsbGluZ3NcbiAgICAgICAgY29uc3Qgc2VydmljZUJpbGxpbmdzID0gYXdhaXQgKG5ldyBHZXRTZXJ2aWNlQmlsbGluZyhjZUNsaWVudCkpLmV4ZWN1dGUoZGF0ZVJhbmdlKTtcbiAgICAgICAgY29uc29sZS5sb2coYFNlcnZpY2VCaWxsaW5nOiAke0pTT04uc3RyaW5naWZ5KHNlcnZpY2VCaWxsaW5ncywgbnVsbCwgMil9YCk7XG4gICAgICAgIHJldHVybiBzZXJ2aWNlQmlsbGluZ3M/Lm1hcCgodmFsdWUpID0+IHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdGl0bGU6IHZhbHVlLnNlcnZpY2UsXG4gICAgICAgICAgICB2YWx1ZTogYCR7dmFsdWUuYW1vdW50fSAke3ZhbHVlLnVuaXR9YCxcbiAgICAgICAgICB9O1xuICAgICAgICB9KTtcbiAgICB9XG4gIH0pKCk7XG5cbiAgY29uc3QgY2xpZW50ID0gbmV3IFdlYkNsaWVudChwcm9jZXNzLmVudi5TTEFDS19UT0tFTik7XG5cbiAgY29uc3QgY2hhbm5lbCA9IHByb2Nlc3MuZW52LlNMQUNLX0NIQU5ORUw7XG5cbiAgLy8gU2VuZCB0aGUgbm90aWZpY2F0aW9uXG4gIGF3YWl0IChhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgY2xpZW50LmNoYXQucG9zdE1lc3NhZ2Uoe1xuICAgICAgY2hhbm5lbCxcbiAgICAgIGljb25fZW1vamk6ICc6bW9uZXktd2l0aC13aW5nczonLFxuICAgICAgdGV4dDogYEFXUyBDb3N0IFJlcG9ydHMgKCR7ZGF0ZVJhbmdlLnN0YXJ0fSAtICR7ZGF0ZVJhbmdlLmVuZH0pYCxcbiAgICAgIGF0dGFjaG1lbnRzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICB0aXRsZTogJzptb25leWJhZzogVG90YWwnLFxuICAgICAgICAgIHRleHQ6IGAke3RvdGFsQmlsbGluZz8uYW1vdW50fSAke3RvdGFsQmlsbGluZz8udW5pdH1gLFxuICAgICAgICAgIGNvbG9yOiAnI2ZmOGMwMCcsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pO1xuICAgIGlmIChyZXN1bHQub2spIHtcbiAgICAgIGF3YWl0IGNsaWVudC5jaGF0LnBvc3RNZXNzYWdlKHtcbiAgICAgICAgY2hhbm5lbCxcbiAgICAgICAgdGhyZWFkX3RzOiByZXN1bHQudHMsXG4gICAgICAgIGF0dGFjaG1lbnRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgY29sb3I6ICcjZmZkNzAwJyxcbiAgICAgICAgICAgIGZpZWxkczogZmllbGRzPy5tYXAoKGZpbGVkKSA9PiB7XG4gICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgdGl0bGU6IGA6YXdzOiAke2ZpbGVkLnRpdGxlfWAsXG4gICAgICAgICAgICAgICAgdmFsdWU6IGZpbGVkLnZhbHVlLFxuICAgICAgICAgICAgICAgIHNob3J0OiBmYWxzZSxcbiAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9KTtcbiAgICB9XG4gIH0pKCk7XG5cbiAgcmV0dXJuICdPSyc7XG59O1xuXG4iXX0=
@@ -0,0 +1,31 @@
1
+ import { CostExplorerClient } from '@aws-sdk/client-cost-explorer';
2
+ import { GetDateRange } from './get-date-range';
3
+ export interface TotalBilling {
4
+ readonly unit: string;
5
+ readonly amount: number;
6
+ }
7
+ export declare class GetTotalBilling {
8
+ private client;
9
+ constructor(client: CostExplorerClient);
10
+ execute: (dateRange: GetDateRange) => Promise<TotalBilling | undefined>;
11
+ }
12
+ export interface ServiceBilling {
13
+ readonly service: string;
14
+ readonly unit: string;
15
+ readonly amount: number;
16
+ }
17
+ export declare class GetServiceBilling {
18
+ private client;
19
+ constructor(client: CostExplorerClient);
20
+ execute: (dateRange: GetDateRange, nextPageToken?: string) => Promise<ServiceBilling[] | undefined>;
21
+ }
22
+ export interface AccountBilling {
23
+ readonly account: string;
24
+ readonly amount: number;
25
+ readonly unit: string;
26
+ }
27
+ export declare class GetAccountBillings {
28
+ private client;
29
+ constructor(client: CostExplorerClient);
30
+ execute: (dateRange: GetDateRange, nextPageToken?: string) => Promise<AccountBilling[] | undefined>;
31
+ }
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GetAccountBillings = exports.GetServiceBilling = exports.GetTotalBilling = void 0;
4
+ // eslint-disable-next-line import/no-extraneous-dependencies
5
+ const client_cost_explorer_1 = require("@aws-sdk/client-cost-explorer");
6
+ class GetTotalBilling {
7
+ constructor(client) {
8
+ this.client = client;
9
+ this.execute = async (dateRange) => {
10
+ const input = {
11
+ TimePeriod: {
12
+ Start: dateRange.start,
13
+ End: dateRange.end,
14
+ },
15
+ Granularity: 'MONTHLY',
16
+ Metrics: [
17
+ 'AMORTIZED_COST',
18
+ ],
19
+ };
20
+ console.log(`TotalBilling:Command:Input:${JSON.stringify(input)}`);
21
+ return this.client.send(new client_cost_explorer_1.GetCostAndUsageCommand(input))
22
+ .then((data) => {
23
+ if (data && data.ResultsByTime && data.ResultsByTime.length === 1) {
24
+ const cost = Object(data.ResultsByTime[0]).Total.AmortizedCost;
25
+ const result = {
26
+ unit: cost.Unit,
27
+ amount: cost.Amount,
28
+ };
29
+ console.log(`TotalBilling:Command:Output(Shaped):${JSON.stringify(result)}`);
30
+ return result;
31
+ }
32
+ return undefined;
33
+ })
34
+ .catch((error) => {
35
+ console.log('Error caught...');
36
+ console.log(`Error:${JSON.stringify(error)}`);
37
+ return undefined;
38
+ });
39
+ };
40
+ }
41
+ ;
42
+ }
43
+ exports.GetTotalBilling = GetTotalBilling;
44
+ class GetServiceBilling {
45
+ constructor(client) {
46
+ this.client = client;
47
+ this.execute = async (dateRange, nextPageToken) => {
48
+ const input = {
49
+ NextPageToken: nextPageToken,
50
+ TimePeriod: {
51
+ Start: dateRange.start,
52
+ End: dateRange.end,
53
+ },
54
+ Granularity: 'MONTHLY',
55
+ Metrics: [
56
+ 'AMORTIZED_COST',
57
+ ],
58
+ GroupBy: [
59
+ {
60
+ Type: 'DIMENSION',
61
+ Key: 'SERVICE',
62
+ },
63
+ ],
64
+ };
65
+ console.log(`ServiceBillings:Command:Input:${JSON.stringify(input)}`);
66
+ return this.client.send(new client_cost_explorer_1.GetCostAndUsageCommand(input))
67
+ .then(async (data) => {
68
+ const billings = [];
69
+ if (data.ResultsByTime && data.ResultsByTime.length === 1) {
70
+ for (const item of Object(data.ResultsByTime[0]).Groups) {
71
+ billings.push({
72
+ service: item.Keys[0],
73
+ unit: item.Metrics.AmortizedCost.Unit,
74
+ amount: item.Metrics.AmortizedCost.Amount,
75
+ });
76
+ }
77
+ console.log(`ServiceBillings:Command:Output(Shaped):${JSON.stringify(billings)}`);
78
+ if (data.NextPageToken) {
79
+ const nextBillings = await this.execute(dateRange, data.NextPageToken);
80
+ if (nextBillings) {
81
+ return billings.concat(nextBillings);
82
+ }
83
+ }
84
+ return billings;
85
+ }
86
+ return undefined;
87
+ })
88
+ .catch(async (error) => {
89
+ console.log('Error caught...');
90
+ console.log(`Error:${JSON.stringify(error)}`);
91
+ return undefined;
92
+ });
93
+ };
94
+ }
95
+ ;
96
+ }
97
+ exports.GetServiceBilling = GetServiceBilling;
98
+ class GetAccountBillings {
99
+ constructor(client) {
100
+ this.client = client;
101
+ this.execute = async (dateRange, nextPageToken) => {
102
+ const input = {
103
+ NextPageToken: nextPageToken,
104
+ TimePeriod: {
105
+ Start: dateRange.start,
106
+ End: dateRange.end,
107
+ },
108
+ Granularity: 'MONTHLY',
109
+ Metrics: [
110
+ 'AMORTIZED_COST',
111
+ ],
112
+ GroupBy: [
113
+ {
114
+ Type: 'DIMENSION',
115
+ Key: 'LINKED_ACCOUNT',
116
+ },
117
+ ],
118
+ };
119
+ console.log(`AccountBillings:Command:Input:${JSON.stringify(input)}`);
120
+ return this.client.send(new client_cost_explorer_1.GetCostAndUsageCommand(input))
121
+ .then(async (data) => {
122
+ const billings = [];
123
+ if (data.ResultsByTime && data.ResultsByTime.length === 1) {
124
+ const groups = Object(data.ResultsByTime[0]).Groups;
125
+ const dimensionValueAttributes = data.DimensionValueAttributes;
126
+ for (const item of groups) {
127
+ for (const attr of dimensionValueAttributes) {
128
+ if (item.Keys[0] === attr.Value) {
129
+ billings.push({
130
+ account: `${attr.Value} (${attr.Attributes.description})`,
131
+ unit: item.Metrics.AmortizedCost.Unit,
132
+ amount: item.Metrics.AmortizedCost.Amount,
133
+ });
134
+ }
135
+ }
136
+ }
137
+ console.log(`AccountBillings:Command:Output(Shaped):${JSON.stringify(billings)}`);
138
+ if (data.NextPageToken) {
139
+ const nextBillings = await this.execute(dateRange, data.NextPageToken);
140
+ if (nextBillings) {
141
+ return billings.concat(nextBillings);
142
+ }
143
+ }
144
+ return billings;
145
+ }
146
+ return undefined;
147
+ })
148
+ .catch(async (error) => {
149
+ console.log('Error caught...');
150
+ console.log(`Error:${JSON.stringify(error)}`);
151
+ return undefined;
152
+ });
153
+ };
154
+ }
155
+ ;
156
+ }
157
+ exports.GetAccountBillings = GetAccountBillings;
158
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0LWJpbGxpbmctY29tbWFuZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9mdW5jcy9saWIvZ2V0LWJpbGxpbmctY29tbWFuZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSw2REFBNkQ7QUFDN0Qsd0VBQXNKO0FBUXRKLE1BQWEsZUFBZTtJQUUxQixZQUNVLE1BQTBCO1FBQTFCLFdBQU0sR0FBTixNQUFNLENBQW9CO1FBRzdCLFlBQU8sR0FBRyxLQUFLLEVBQUUsU0FBdUIsRUFBcUMsRUFBRTtZQUNwRixNQUFNLEtBQUssR0FBZ0M7Z0JBQ3pDLFVBQVUsRUFBRTtvQkFDVixLQUFLLEVBQUUsU0FBUyxDQUFDLEtBQUs7b0JBQ3RCLEdBQUcsRUFBRSxTQUFTLENBQUMsR0FBRztpQkFDbkI7Z0JBQ0QsV0FBVyxFQUFFLFNBQVM7Z0JBQ3RCLE9BQU8sRUFBRTtvQkFDUCxnQkFBZ0I7aUJBQ2pCO2FBQ0YsQ0FBQztZQUNGLE9BQU8sQ0FBQyxHQUFHLENBQUMsOEJBQThCLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ25FLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSw2Q0FBc0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztpQkFDdkQsSUFBSSxDQUFDLENBQUMsSUFBa0MsRUFBRSxFQUFFO2dCQUMzQyxJQUFJLElBQUksSUFBSSxJQUFJLENBQUMsYUFBYSxJQUFJLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRSxDQUFDO29CQUNsRSxNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxhQUFhLENBQUM7b0JBQy9ELE1BQU0sTUFBTSxHQUFpQjt3QkFDM0IsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJO3dCQUNmLE1BQU0sRUFBRSxJQUFJLENBQUMs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LE9BQU8sU0FBUyxDQUFDO1lBQ25CLENBQUMsQ0FBQztpQkFDRCxLQUFLLENBQUMsS0FBSyxFQUFFLEtBQUssRUFBRSxFQUFFO2dCQUNyQixPQUFPLENBQUMsR0FBRyxDQUFDLGlCQUFpQixDQUFDLENBQUM7Z0JBQy9CLE9BQU8sQ0FBQyxHQUFHLENBQUMsU0FBUyxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDOUMsT0FBTyxTQUFTLENBQUM7WUFDbkIsQ0FBQyxDQUFDLENBQUM7UUFDUCxDQUFDLENBQUM7SUF0REMsQ0FBQztJQUFBLENBQUM7Q0F1RE47QUExREQsZ0RBMERDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGltcG9ydC9uby1leHRyYW5lb3VzLWRlcGVuZGVuY2llc1xuaW1wb3J0IHsgQ29zdEV4cGxvcmVyQ2xpZW50LCBHZXRDb3N0QW5kVXNhZ2VDb21tYW5kLCBHZXRDb3N0QW5kVXNhZ2VDb21tYW5kSW5wdXQsIEdldENvc3RBbmRVc2FnZUNvbW1hbmRPdXRwdXQgfSBmcm9tICdAYXdzLXNkay9jbGllbnQtY29zdC1leHBsb3Jlcic7XG5pbXBvcnQgeyBHZXREYXRlUmFuZ2UgfSBmcm9tICcuL2dldC1kYXRlLXJhbmdlJztcblxuZXhwb3J0IGludGVyZmFjZSBUb3RhbEJpbGxpbmcge1xuICByZWFkb25seSB1bml0OiBzdHJpbmc7XG4gIHJlYWRvbmx5IGFtb3VudDogbnVtYmVyO1xufVxuXG5leHBvcnQgY2xhc3MgR2V0VG90YWxCaWxsaW5nIHtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIGNsaWVudDogQ29zdEV4cGxvcmVyQ2xpZW50LFxuICApIHt9O1xuXG4gIHB1YmxpYyBleGVjdXRlID0gYXN5bmMgKGRhdGVSYW5nZTogR2V0RGF0ZVJhbmdlKTogUHJvbWlzZTxUb3RhbEJpbGxpbmcgfCB1bmRlZmluZWQ+ID0+IHtcbiAgICBjb25zdCBpbnB1dDogR2V0Q29zdEFuZFVzYWdlQ29tbWFuZElucHV0ID0ge1xuICAgICAgVGltZVBlcmlvZDoge1xuICAgICAgICBTdGFydDogZGF0ZVJhbmdlLnN0YXJ0LFxuICAgICAgICBFbmQ6IGRhdGVSYW5nZS5lbmQsXG4gICAgICB9LFxuICAgICAgR3JhbnVsYXJpdHk6ICdNT05USExZJyxcbiAgICAgIE1ldHJpY3M6IFtcbiAgICAgICAgJ0FNT1JUSVpFRF9DT1NUJyxcbiAgICAgIF0sXG4gICAgfTtcbiAgICBjb25zb2xlLmxvZyhgVG90YWxCaWxsaW5nOkNvbW1hbmQ6SW5wdXQ6JHtKU09OLnN0cmluZ2lmeShpbnB1dCl9YCk7XG4gICAgcmV0dXJuIHRoaXMuY2xpZW50LnNlbmQobmV3IEdldENvc3RBbmRVc2FnZUNvbW1hbmQoaW5wdXQpKVxuICAgICAgLnRoZW4oKGRhdGE6IEdldENvc3RBbmRVc2FnZUNvbW1hbmRPdXRwdXQpID0+IHtcbiAgICAgICAgaWYgKGRhdGEgJiYgZGF0YS5SZXN1bHRzQnlUaW1lICYmIGRhdGEuUmVzdWx0c0J5VGltZS5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICBjb25zdCBjb3N0ID0gT2JqZWN0KGRhdGEuUmVzdWx0c0J5VGltZVswXSkuVG90YWwuQW1vcnRpemVkQ29zdDtcbiAgICAgICAgICBjb25zdCByZXN1bHQ6IFRvdGFsQmlsbGluZyA9IHtcbiAgICAgICAgICAgIHVuaXQ6IGNvc3QuVW5pdCxcbiAgICAgICAgICAgIGFtb3VudDogY29zdC5BbW91bnQsXG4gICAgICAgICAgfTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhgVG90YWxCaWxsaW5nOkNvbW1hbmQ6T3V0cHV0KFNoYXBlZCk6JHtKU09OLnN0cmluZ2lmeShyZXN1bHQpfWApO1xuICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdFcnJvciBjYXVnaHQuLi4nKTtcbiAgICAgICAgY29uc29sZS5sb2coYEVycm9yOiR7SlNPTi5zdHJpbmdpZnkoZXJyb3IpfWApO1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfSk7XG4gIH07XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VydmljZUJpbGxpbmcge1xuICByZWFkb25seSBzZXJ2aWNlOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHVuaXQ6IHN0cmluZztcbiAgcmVhZG9ubHkgYW1vdW50OiBudW1iZXI7XG59XG5cbmV4cG9ydCBjbGFzcyBHZXRTZXJ2aWNlQmlsbGluZyB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgY2xpZW50OiBDb3N0RXhwbG9yZXJDbGllbnQsXG4gICkge307XG5cbiAgcHVibGljIGV4ZWN1dGUgPSBhc3luYyAoZGF0ZVJhbmdlOiBHZXREYXRlUmFuZ2UsIG5leHRQYWdlVG9rZW4/OiBzdHJpbmcpOiBQcm9taXNlPFNlcnZpY2VCaWxsaW5nW10gfCB1bmRlZmluZWQ+ID0+IHtcbiAgICBjb25zdCBpbnB1dDogR2V0Q29zdEFuZFVzYWdlQ29tbWFuZElucHV0ID0ge1xuICAgICAgTmV4dFBhZ2VUb2tlbjogbmV4dFBhZ2VUb2tlbixcbiAgICAgIFRpbWVQZXJpb2Q6IHtcbiAgICAgICAgU3RhcnQ6IGRhdGVSYW5nZS5zdGFydCxcbiAgICAgICAgRW5kOiBkYXRlUmFuZ2UuZW5kLFxuICAgICAgfSxcbiAgICAgIEdyYW51bGFyaXR5OiAnTU9OVEhMWScsXG4gICAgICBNZXRyaWNzOiBbXG4gICAgICAgICdBTU9SVElaRURfQ09TVCcsXG4gICAgICBdLFxuICAgICAgR3JvdXBCeTogW1xuICAgICAgICB7XG4gICAgICAgICAgVHlwZTogJ0RJTUVOU0lPTicsXG4gICAgICAgICAgS2V5OiAnU0VSVklDRScsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH07XG4gICAgY29uc29sZS5sb2coYFNlcnZpY2VCaWxsaW5nczpDb21tYW5kOklucHV0OiR7SlNPTi5zdHJpbmdpZnkoaW5wdXQpfWApO1xuICAgIHJldHVybiB0aGlzLmNsaWVudC5zZW5kKG5ldyBHZXRDb3N0QW5kVXNhZ2VDb21tYW5kKGlucHV0KSlcbiAgICAgIC50aGVuKGFzeW5jIChkYXRhKSA9PiB7XG4gICAgICAgIGNvbnN0IGJpbGxpbmdzOiBTZXJ2aWNlQmlsbGluZ1tdID0gW107XG4gICAgICAgIGlmIChkYXRhLlJlc3VsdHNCeVRpbWUgJiYgZGF0YS5SZXN1bHRzQnlUaW1lLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBPYmplY3QoZGF0YS5SZXN1bHRzQnlUaW1lWzBdKS5Hcm91cHMpIHtcbiAgICAgICAgICAgIGJpbGxpbmdzLnB1c2goe1xuICAgICAgICAgICAgICBzZXJ2aWNlOiBpdGVtLktleXNbMF0sXG4gICAgICAgICAgICAgIHVuaXQ6IGl0ZW0uTWV0cmljcy5BbW9ydGl6ZWRDb3N0LlVuaXQsXG4gICAgICAgICAgICAgIGFtb3VudDogaXRlbS5NZXRyaWNzLkFtb3J0aXplZENvc3QuQW1vdW50LFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnNvbGUubG9nKGBTZXJ2aWNlQmlsbGluZ3M6Q29tbWFuZDpPdXRwdXQoU2hhcGVkKToke0pTT04uc3RyaW5naWZ5KGJpbGxpbmdzKX1gKTtcbiAgICAgICAgICBpZiAoZGF0YS5OZXh0UGFnZVRva2VuKSB7XG4gICAgICAgICAgICBjb25zdCBuZXh0QmlsbGluZ3MgPSBhd2FpdCB0aGlzLmV4ZWN1dGUoZGF0ZVJhbmdlLCBkYXRhLk5leHRQYWdlVG9rZW4pO1xuICAgICAgICAgICAgaWYgKG5leHRCaWxsaW5ncykge1xuICAgICAgICAgICAgICByZXR1cm4gYmlsbGluZ3MuY29uY2F0KG5leHRCaWxsaW5ncyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBiaWxsaW5ncztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaChhc3luYyAoZXJyb3IpID0+IHtcbiAgICAgICAgY29uc29sZS5sb2coJ0Vycm9yIGNhdWdodC4uLicpO1xuICAgICAgICBjb25zb2xlLmxvZyhgRXJyb3I6JHtKU09OLnN0cmluZ2lmeShlcnJvcil9YCk7XG4gICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICB9KTtcbiAgfTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBY2NvdW50QmlsbGluZyB7XG4gIHJlYWRvbmx5IGFjY291bnQ6IHN0cmluZztcbiAgcmVhZG9ubHkgYW1vdW50OiBudW1iZXI7XG4gIHJlYWRvbmx5IHVuaXQ6IHN0cmluZztcbn1cblxuZXhwb3J0IGNsYXNzIEdldEFjY291bnRCaWxsaW5ncyB7XG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgY2xpZW50OiBDb3N0RXhwbG9yZXJDbGllbnQsXG4gICkge307XG5cbiAgcHVibGljIGV4ZWN1dGUgPSBhc3luYyAoZGF0ZVJhbmdlOiBHZXREYXRlUmFuZ2UsIG5leHRQYWdlVG9rZW4/OiBzdHJpbmcpOiBQcm9taXNlPEFjY291bnRCaWxsaW5nW10gfCB1bmRlZmluZWQ+ID0+IHtcbiAgICBjb25zdCBpbnB1dDogR2V0Q29zdEFuZFVzYWdlQ29tbWFuZElucHV0ID0ge1xuICAgICAgTmV4dFBhZ2VUb2tlbjogbmV4dFBhZ2VUb2tlbixcbiAgICAgIFRpbWVQZXJpb2Q6IHtcbiAgICAgICAgU3RhcnQ6IGRhdGVSYW5nZS5zdGFydCxcbiAgICAgICAgRW5kOiBkYXRlUmFuZ2UuZW5kLFxuICAgICAgfSxcbiAgICAgIEdyYW51bGFyaXR5OiAnTU9OVEhMWScsXG4gICAgICBNZXRyaWNzOiBbXG4gICAgICAgICdBTU9SVElaRURfQ09TVCcsXG4gICAgICBdLFxuICAgICAgR3JvdXBCeTogW1xuICAgICAgICB7XG4gICAgICAgICAgVHlwZTogJ0RJTUVOU0lPTicsXG4gICAgICAgICAgS2V5OiAnTElOS0VEX0FDQ09VTlQnLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9O1xuICAgIGNvbnNvbGUubG9nKGBBY2NvdW50QmlsbGluZ3M6Q29tbWFuZDpJbnB1dDoke0pTT04uc3RyaW5naWZ5KGlucHV0KX1gKTtcbiAgICByZXR1cm4gdGhpcy5jbGllbnQuc2VuZChuZXcgR2V0Q29zdEFuZFVzYWdlQ29tbWFuZChpbnB1dCkpXG4gICAgICAudGhlbihhc3luYyAoZGF0YSkgPT4ge1xuICAgICAgICBjb25zdCBiaWxsaW5nczogQWNjb3VudEJpbGxpbmdbXSA9IFtdO1xuICAgICAgICBpZiAoZGF0YS5SZXN1bHRzQnlUaW1lICYmIGRhdGEuUmVzdWx0c0J5VGltZS5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICBjb25zdCBncm91cHMgPSBPYmplY3QoZGF0YS5SZXN1bHRzQnlUaW1lWzBdKS5Hcm91cHM7XG4gICAgICAgICAgY29uc3QgZGltZW5zaW9uVmFsdWVBdHRyaWJ1dGVzID0gZGF0YS5EaW1lbnNpb25WYWx1ZUF0dHJpYnV0ZXMhO1xuICAgICAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBncm91cHMpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgYXR0ciBvZiBkaW1lbnNpb25WYWx1ZUF0dHJpYnV0ZXMpIHtcbiAgICAgICAgICAgICAgaWYgKGl0ZW0uS2V5c1swXSA9PT0gYXR0ci5WYWx1ZSkge1xuICAgICAgICAgICAgICAgIGJpbGxpbmdzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgYWNjb3VudDogYCR7YXR0ci5WYWx1ZX0gKCR7YXR0ci5BdHRyaWJ1dGVzIS5kZXNjcmlwdGlvbn0pYCxcbiAgICAgICAgICAgICAgICAgIHVuaXQ6IGl0ZW0uTWV0cmljcy5BbW9ydGl6ZWRDb3N0LlVuaXQsXG4gICAgICAgICAgICAgICAgICBhbW91bnQ6IGl0ZW0uTWV0cmljcy5BbW9ydGl6ZWRDb3N0LkFtb3VudCxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zb2xlLmxvZyhgQWNjb3VudEJpbGxpbmdzOkNvbW1hbmQ6T3V0cHV0KFNoYXBlZCk6JHtKU09OLnN0cmluZ2lmeShiaWxsaW5ncyl9YCk7XG4gICAgICAgICAgaWYgKGRhdGEuTmV4dFBhZ2VUb2tlbikge1xuICAgICAgICAgICAgY29uc3QgbmV4dEJpbGxpbmdzID0gYXdhaXQgdGhpcy5leGVjdXRlKGRhdGVSYW5nZSwgZGF0YS5OZXh0UGFnZVRva2VuKTtcbiAgICAgICAgICAgIGlmIChuZXh0QmlsbGluZ3MpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGJpbGxpbmdzLmNvbmNhdChuZXh0QmlsbGluZ3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gYmlsbGluZ3M7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgIH0pXG4gICAgICAuY2F0Y2goYXN5bmMgKGVycm9yKSA9PiB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdFcnJvciBjYXVnaHQuLi4nKTtcbiAgICAgICAgY29uc29sZS5sb2coYEVycm9yOiR7SlNPTi5zdHJpbmdpZnkoZXJyb3IpfWApO1xuICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgfSk7XG4gIH07XG59Il19
@@ -0,0 +1,6 @@
1
+ export declare class GetDateRange {
2
+ start: string;
3
+ end: string;
4
+ constructor();
5
+ private dateFormatString;
6
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GetDateRange = void 0;
4
+ class GetDateRange {
5
+ constructor() {
6
+ this.dateFormatString = (date) => {
7
+ return (date.getFullYear()) + '-' + ('00' + (date.getMonth() + 1)).slice(-2) + '-' + ('00' + (date.getDate())).slice(-2);
8
+ };
9
+ const now = new Date(Date.now());
10
+ if (now.getDate() === 1) {
11
+ // Last month
12
+ this.start = this.dateFormatString(new Date(now.getFullYear(), now.getMonth() - 1, 1));
13
+ this.end = this.dateFormatString(new Date(now.getFullYear(), now.getMonth(), 0));
14
+ }
15
+ else {
16
+ this.start = this.dateFormatString(new Date(now.getFullYear(), now.getMonth(), 1));
17
+ this.end = this.dateFormatString(new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1));
18
+ }
19
+ }
20
+ }
21
+ exports.GetDateRange = GetDateRange;
22
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2V0LWRhdGUtcmFuZ2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZnVuY3MvbGliL2dldC1kYXRlLXJhbmdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUVBLE1BQWEsWUFBWTtJQUt2QjtRQVlRLHFCQUFnQixHQUFHLENBQUMsSUFBVSxFQUFVLEVBQUU7WUFDaEQsT0FBTyxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsR0FBRyxDQUFDLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0gsQ0FBQyxDQUFDO1FBYkEsTUFBTSxHQUFHLEdBQUcsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFDakMsSUFBSSxHQUFHLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDeEIsYUFBYTtZQUNiLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsRUFBRSxHQUFHLENBQUMsUUFBUSxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDdkYsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxFQUFFLEdBQUcsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ25GLENBQUM7YUFBTSxDQUFDO1lBQ04sSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLFdBQVcsRUFBRSxFQUFFLEdBQUcsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ25GLElBQUksQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxXQUFXLEVBQUUsRUFBRSxHQUFHLENBQUMsUUFBUSxFQUFFLEVBQUUsR0FBRyxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbkcsQ0FBQztJQUNILENBQUM7Q0FLRjtBQXBCRCxvQ0FvQkMiLCJzb3VyY2VzQ29udGVudCI6WyJcblxuZXhwb3J0IGNsYXNzIEdldERhdGVSYW5nZSB7XG5cbiAgcHVibGljIHN0YXJ0OiBzdHJpbmc7XG4gIHB1YmxpYyBlbmQ6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBjb25zdCBub3cgPSBuZXcgRGF0ZShEYXRlLm5vdygpKTtcbiAgICBpZiAobm93LmdldERhdGUoKSA9PT0gMSkge1xuICAgICAgLy8gTGFzdCBtb250aFxuICAgICAgdGhpcy5zdGFydCA9IHRoaXMuZGF0ZUZvcm1hdFN0cmluZyhuZXcgRGF0ZShub3cuZ2V0RnVsbFllYXIoKSwgbm93LmdldE1vbnRoKCkgLSAxLCAxKSk7XG4gICAgICB0aGlzLmVuZCA9IHRoaXMuZGF0ZUZvcm1hdFN0cmluZyhuZXcgRGF0ZShub3cuZ2V0RnVsbFllYXIoKSwgbm93LmdldE1vbnRoKCksIDApKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zdGFydCA9IHRoaXMuZGF0ZUZvcm1hdFN0cmluZyhuZXcgRGF0ZShub3cuZ2V0RnVsbFllYXIoKSwgbm93LmdldE1vbnRoKCksIDEpKTtcbiAgICAgIHRoaXMuZW5kID0gdGhpcy5kYXRlRm9ybWF0U3RyaW5nKG5ldyBEYXRlKG5vdy5nZXRGdWxsWWVhcigpLCBub3cuZ2V0TW9udGgoKSwgbm93LmdldERhdGUoKSAtIDEpKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGRhdGVGb3JtYXRTdHJpbmcgPSAoZGF0ZTogRGF0ZSk6IHN0cmluZyA9PiB7XG4gICAgcmV0dXJuIChkYXRlLmdldEZ1bGxZZWFyKCkpICsgJy0nICsgKCcwMCcgKyAoZGF0ZS5nZXRNb250aCgpICsgMSkpLnNsaWNlKC0yKSArICctJyArICgnMDAnICsgKGRhdGUuZ2V0RGF0ZSgpKSkuc2xpY2UoLTIpO1xuICB9O1xufSJdfQ==
package/lib/index.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { Stack } from 'aws-cdk-lib';
2
+ import { Construct } from 'constructs';
3
+ export interface DailyCostUsageReportStackProps {
4
+ readonly slackToken: string;
5
+ readonly slackChannel: string;
6
+ readonly scheduleTimezone?: string;
7
+ readonly costGroupType: CostGroupType;
8
+ }
9
+ export declare enum CostGroupType {
10
+ ACCOUNTS = "Accounts",
11
+ SERVICES = "Services"
12
+ }
13
+ export declare class DailyCostUsageReportStack extends Stack {
14
+ constructor(scope: Construct, id: string, props: DailyCostUsageReportStackProps);
15
+ }
package/lib/index.js ADDED
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ var _a;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.DailyCostUsageReportStack = exports.CostGroupType = void 0;
5
+ const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
6
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
7
+ const iam = require("aws-cdk-lib/aws-iam");
8
+ const scheduler = require("aws-cdk-lib/aws-scheduler");
9
+ const cost_reporter_function_1 = require("./funcs/cost-reporter-function");
10
+ var CostGroupType;
11
+ (function (CostGroupType) {
12
+ CostGroupType["ACCOUNTS"] = "Accounts";
13
+ CostGroupType["SERVICES"] = "Services";
14
+ })(CostGroupType || (exports.CostGroupType = CostGroupType = {}));
15
+ class DailyCostUsageReportStack extends aws_cdk_lib_1.Stack {
16
+ constructor(scope, id, props) {
17
+ super(scope, id);
18
+ // 👇Get current account & region
19
+ // const account = Stack.of(this).account;
20
+ // const region = cdk.Stack.of(this).region;
21
+ // 👇Lambda Exec Role
22
+ const lambdaExecutionRole = new iam.Role(this, 'LambdaExecutionRole', {
23
+ roleName: undefined,
24
+ description: '',
25
+ assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
26
+ managedPolicies: [
27
+ iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole'),
28
+ ],
29
+ inlinePolicies: {
30
+ ['get-cost-usage']: new iam.PolicyDocument({
31
+ statements: [
32
+ new iam.PolicyStatement({
33
+ effect: iam.Effect.ALLOW,
34
+ actions: [
35
+ 'ce:GetCostAndUsage',
36
+ ],
37
+ resources: ['*'],
38
+ }),
39
+ ],
40
+ }),
41
+ },
42
+ });
43
+ // 👇Lambda Function
44
+ const lambdaFunction = new cost_reporter_function_1.CostReporterFunction(this, 'CostReporterFunction', {
45
+ functionName: undefined,
46
+ description: 'A function to archive logs s3 bucket from CloudWatch Logs.',
47
+ environment: {
48
+ //BUCKET_NAME: logArchiveBucket.bucketName,
49
+ SLACK_TOKEN: props.slackToken,
50
+ SLACK_CHANNEL: props.slackChannel,
51
+ },
52
+ role: lambdaExecutionRole,
53
+ timeout: aws_cdk_lib_1.Duration.seconds(45),
54
+ });
55
+ // 👇EventBridge Scheduler IAM Role
56
+ const schedulerExecutionRole = new iam.Role(this, 'SchedulerExecutionRole', {
57
+ roleName: undefined,
58
+ assumedBy: new iam.ServicePrincipal('scheduler.amazonaws.com'),
59
+ inlinePolicies: {
60
+ ['lambda-invoke-policy']: new iam.PolicyDocument({
61
+ statements: [
62
+ new iam.PolicyStatement({
63
+ effect: iam.Effect.ALLOW,
64
+ actions: [
65
+ 'lambda:InvokeFunction',
66
+ ],
67
+ resources: [
68
+ lambdaFunction.functionArn,
69
+ `${lambdaFunction.functionArn}:*`,
70
+ ],
71
+ }),
72
+ ],
73
+ }),
74
+ },
75
+ });
76
+ // 👇Schedule
77
+ new scheduler.CfnSchedule(this, 'Schedule', {
78
+ name: undefined,
79
+ description: 'aws account const reports.',
80
+ state: 'ENABLED',
81
+ //groupName: scheduleGroup.name, // default
82
+ flexibleTimeWindow: {
83
+ mode: 'OFF',
84
+ },
85
+ scheduleExpressionTimezone: props.scheduleTimezone ?? 'UTC',
86
+ scheduleExpression: 'cron(1 9 * * ? *)',
87
+ target: {
88
+ arn: lambdaFunction.functionArn,
89
+ roleArn: schedulerExecutionRole.roleArn,
90
+ input: JSON.stringify({ Type: props.costGroupType }),
91
+ retryPolicy: {
92
+ maximumEventAgeInSeconds: 60,
93
+ maximumRetryAttempts: 0,
94
+ },
95
+ },
96
+ });
97
+ }
98
+ }
99
+ exports.DailyCostUsageReportStack = DailyCostUsageReportStack;
100
+ _a = JSII_RTTI_SYMBOL_1;
101
+ DailyCostUsageReportStack[_a] = { fqn: "@gammarers/aws-daily-cost-usage-report-stack.DailyCostUsageReportStack", version: "2.0.0" };
102
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFBQSw2Q0FBOEM7QUFDOUMsMkNBQTJDO0FBQzNDLHVEQUF1RDtBQUV2RCwyRUFBc0U7QUFTdEUsSUFBWSxhQUdYO0FBSEQsV0FBWSxhQUFhO0lBQ3ZCLHNDQUFxQixDQUFBO0lBQ3JCLHNDQUFxQixDQUFBO0FBQ3ZCLENBQUMsRUFIVyxhQUFhLDZCQUFiLGFBQWEsUUFHeEI7QUFFRCxNQUFhLHlCQUEwQixTQUFRLG1CQUFLO0lBQ2xELFlBQVksS0FBZ0IsRUFBRSxFQUFVLEVBQUUsS0FBcUM7UUFDN0UsS0FBSyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUVqQixpQ0FBaUM7UUFDakMsMENBQTBDO1FBQzFDLDRDQUE0QztRQUU1QyxxQkFBcUI7UUFDckIsTUFBTSxtQkFBbUIsR0FBRyxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLHFCQUFxQixFQUFFO1lBQ3BFLFFBQVEsRUFBRSxTQUFTO1lBQ25CLFdBQVcsRUFBRSxFQUFFO1lBQ2YsU0FBUyxFQUFFLElBQUksR0FBRyxDQUFDLGdCQUFnQixDQUFDLHNCQUFzQixDQUFDO1lBQzNELGVBQWUsRUFBRTtnQkFDZixHQUFHLENBQUMsYUFBYSxDQUFDLHdCQUF3QixDQUFDLDBDQUEwQyxDQUFDO2FBQ3ZGO1lBQ0QsY0FBYyxFQUFFO2dCQUNkLENBQUMsZ0JBQWdCLENBQUMsRUFBRSxJQUFJLEdBQUcsQ0FBQyxjQUFjLENBQUM7b0JBQ3pDLFVBQVUsRUFBRTt3QkFDVixJQUFJLEdBQUcsQ0FBQyxlQUFlLENBQUM7NEJBQ3RCLE1BQU0sRUFBRSxHQUFHLENBQUMsTUFBTSxDQUFDLEtBQUs7NEJBQ3hCLE9BQU8sRUFBRTtnQ0FDUCxvQkFBb0I7NkJBQ3JCOzRCQUNELFNBQVMsRUFBRSxDQUFDLEdBQUcsQ0FBQzt5QkFDakIsQ0FBQztxQkFDSDtpQkFDRixDQUFDO2FBQ0g7U0FDRixDQUFDLENBQUM7UUFFSCxvQkFBb0I7UUFDcEIsTUFBTSxjQUFjLEdBQUcsSUFBSSw2Q0FBb0IsQ0FBQyxJQUFJLEVBQUUsc0JBQXNCLEVBQUU7WUFDNUUsWUFBWSxFQUFFLFNBQVM7WUFDdkIsV0FBVyxFQUFFLDREQUE0RDtZQUN6RSxXQUFXLEVBQUU7Z0JBQ1gsMkNBQTJDO2dCQUMzQyxXQUFXLEVBQUUsS0FBSyxDQUFDLFVBQVU7Z0JBQzdCLGFBQWEsRUFBRSxLQUFLLENBQUMsWUFBWTthQUNsQztZQUNELElBQUksRUFBRSxtQkFBbUI7WUFDekIsT0FBTyxFQUFFLHNCQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztTQUM5QixDQUFDLENBQUM7UUFFSCxtQ0FBbUM7UUFDbkMsTUFBTSxzQkFBc0IsR0FBRyxJQUFJLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLHdCQUF3QixFQUFFO1lBQzFFLFFBQVEsRUFBRSxTQUFTO1lBQ25CLFNBQVMsRUFBRSxJQUFJLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyx5QkFBeUIsQ0FBQztZQUM5RCxjQUFjLEVBQUU7Z0JBQ2QsQ0FBQyxzQkFBc0IsQ0FBQyxFQUFFLElBQUksR0FBRyxDQUFDLGNBQWMsQ0FBQztvQkFDL0MsVUFBVSxFQUFFO3dCQUNWLElBQUksR0FBRyxDQUFDLGVBQWUsQ0FBQzs0QkFDdEIsTUFBTSxFQUFFLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSzs0QkFDeEIsT0FBTyxFQUFFO2dDQUNQLHVCQUF1Qjs2QkFDeEI7NEJBQ0QsU0FBUyxFQUFFO2dDQUNULGNBQWMsQ0FBQyxXQUFXO2dDQUMxQixHQUFHLGNBQWMsQ0FBQyxXQUFXLElBQUk7NkJBQ2xDO3lCQUNGLENBQUM7cUJBQ0g7aUJBQ0YsQ0FBQzthQUNIO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsYUFBYTtRQUNiLElBQUksU0FBUyxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFO1lBQzFDLElBQUksRUFBRSxTQUFTO1lBQ2YsV0FBVyxFQUFFLDRCQUE0QjtZQUN6QyxLQUFLLEVBQUUsU0FBUztZQUNoQiwyQ0FBMkM7WUFDM0Msa0JBQWtCLEVBQUU7Z0JBQ2xCLElBQUksRUFBRSxLQUFLO2FBQ1o7WUFDRCwwQkFBMEIsRUFBRSxLQUFLLENBQUMsZ0JBQWdCLElBQUksS0FBSztZQUMzRCxrQkFBa0IsRUFBRSxtQkFBbUI7WUFDdkMsTUFBTSxFQUFFO2dCQUNOLEdBQUcsRUFBRSxjQUFjLENBQUMsV0FBVztnQkFDL0IsT0FBTyxFQUFFLHNCQUFzQixDQUFDLE9BQU87Z0JBQ3ZDLEtBQUssRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQyxhQUFhLEVBQUUsQ0FBQztnQkFDcEQsV0FBVyxFQUFFO29CQUNYLHdCQUF3QixFQUFFLEVBQUU7b0JBQzVCLG9CQUFvQixFQUFFLENBQUM7aUJBQ3hCO2FBQ0Y7U0FDRixDQUFDLENBQUM7SUFDTCxDQUFDOztBQXZGSCw4REF5RkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEdXJhdGlvbiwgU3RhY2sgfSBmcm9tICdhd3MtY2RrLWxpYic7XG5pbXBvcnQgKiBhcyBpYW0gZnJvbSAnYXdzLWNkay1saWIvYXdzLWlhbSc7XG5pbXBvcnQgKiBhcyBzY2hlZHVsZXIgZnJvbSAnYXdzLWNkay1saWIvYXdzLXNjaGVkdWxlcic7XG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IENvc3RSZXBvcnRlckZ1bmN0aW9uIH0gZnJvbSAnLi9mdW5jcy9jb3N0LXJlcG9ydGVyLWZ1bmN0aW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBEYWlseUNvc3RVc2FnZVJlcG9ydFN0YWNrUHJvcHMge1xuICByZWFkb25seSBzbGFja1Rva2VuOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHNsYWNrQ2hhbm5lbDogc3RyaW5nO1xuICByZWFkb25seSBzY2hlZHVsZVRpbWV6b25lPzogc3RyaW5nO1xuICByZWFkb25seSBjb3N0R3JvdXBUeXBlOiBDb3N0R3JvdXBUeXBlO1xufVxuXG5leHBvcnQgZW51bSBDb3N0R3JvdXBUeXBlIHtcbiAgQUNDT1VOVFMgPSAnQWNjb3VudHMnLFxuICBTRVJWSUNFUyA9ICdTZXJ2aWNlcycsXG59XG5cbmV4cG9ydCBjbGFzcyBEYWlseUNvc3RVc2FnZVJlcG9ydFN0YWNrIGV4dGVuZHMgU3RhY2sge1xuICBjb25zdHJ1Y3RvcihzY29wZTogQ29uc3RydWN0LCBpZDogc3RyaW5nLCBwcm9wczogRGFpbHlDb3N0VXNhZ2VSZXBvcnRTdGFja1Byb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIC8vIPCfkYdHZXQgY3VycmVudCBhY2NvdW50ICYgcmVnaW9uXG4gICAgLy8gY29uc3QgYWNjb3VudCA9IFN0YWNrLm9mKHRoaXMpLmFjY291bnQ7XG4gICAgLy8gY29uc3QgcmVnaW9uID0gY2RrLlN0YWNrLm9mKHRoaXMpLnJlZ2lvbjtcblxuICAgIC8vIPCfkYdMYW1iZGEgRXhlYyBSb2xlXG4gICAgY29uc3QgbGFtYmRhRXhlY3V0aW9uUm9sZSA9IG5ldyBpYW0uUm9sZSh0aGlzLCAnTGFtYmRhRXhlY3V0aW9uUm9sZScsIHtcbiAgICAgIHJvbGVOYW1lOiB1bmRlZmluZWQsXG4gICAgICBkZXNjcmlwdGlvbjogJycsXG4gICAgICBhc3N1bWVkQnk6IG5ldyBpYW0uU2VydmljZVByaW5jaXBhbCgnbGFtYmRhLmFtYXpvbmF3cy5jb20nKSxcbiAgICAgIG1hbmFnZWRQb2xpY2llczogW1xuICAgICAgICBpYW0uTWFuYWdlZFBvbGljeS5mcm9tQXdzTWFuYWdlZFBvbGljeU5hbWUoJ3NlcnZpY2Utcm9sZS9BV1NMYW1iZGFCYXNpY0V4ZWN1dGlvblJvbGUnKSxcbiAgICAgIF0sXG4gICAgICBpbmxpbmVQb2xpY2llczoge1xuICAgICAgICBbJ2dldC1jb3N0LXVzYWdlJ106IG5ldyBpYW0uUG9saWN5RG9jdW1lbnQoe1xuICAgICAgICAgIHN0YXRlbWVudHM6IFtcbiAgICAgICAgICAgIG5ldyBpYW0uUG9saWN5U3RhdGVtZW50KHtcbiAgICAgICAgICAgICAgZWZmZWN0OiBpYW0uRWZmZWN0LkFMTE9XLFxuICAgICAgICAgICAgICBhY3Rpb25zOiBbXG4gICAgICAgICAgICAgICAgJ2NlOkdldENvc3RBbmRVc2FnZScsXG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgIHJlc291cmNlczogWycqJ10sXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICBdLFxuICAgICAgICB9KSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyDwn5GHTGFtYmRhIEZ1bmN0aW9uXG4gICAgY29uc3QgbGFtYmRhRnVuY3Rpb24gPSBuZXcgQ29zdFJlcG9ydGVyRnVuY3Rpb24odGhpcywgJ0Nvc3RSZXBvcnRlckZ1bmN0aW9uJywge1xuICAgICAgZnVuY3Rpb25OYW1lOiB1bmRlZmluZWQsXG4gICAgICBkZXNjcmlwdGlvbjogJ0EgZnVuY3Rpb24gdG8gYXJjaGl2ZSBsb2dzIHMzIGJ1Y2tldCBmcm9tIENsb3VkV2F0Y2ggTG9ncy4nLFxuICAgICAgZW52aXJvbm1lbnQ6IHtcbiAgICAgICAgLy9CVUNLRVRfTkFNRTogbG9nQXJjaGl2ZUJ1Y2tldC5idWNrZXROYW1lLFxuICAgICAgICBTTEFDS19UT0tFTjogcHJvcHMuc2xhY2tUb2tlbixcbiAgICAgICAgU0xBQ0tfQ0hBTk5FTDogcHJvcHMuc2xhY2tDaGFubmVsLFxuICAgICAgfSxcbiAgICAgIHJvbGU6IGxhbWJkYUV4ZWN1dGlvblJvbGUsXG4gICAgICB0aW1lb3V0OiBEdXJhdGlvbi5zZWNvbmRzKDQ1KSxcbiAgICB9KTtcblxuICAgIC8vIPCfkYdFdmVudEJyaWRnZSBTY2hlZHVsZXIgSUFNIFJvbGVcbiAgICBjb25zdCBzY2hlZHVsZXJFeGVjdXRpb25Sb2xlID0gbmV3IGlhbS5Sb2xlKHRoaXMsICdTY2hlZHVsZXJFeGVjdXRpb25Sb2xlJywge1xuICAgICAgcm9sZU5hbWU6IHVuZGVmaW5lZCxcbiAgICAgIGFzc3VtZWRCeTogbmV3IGlhbS5TZXJ2aWNlUHJpbmNpcGFsKCdzY2hlZHVsZXIuYW1hem9uYXdzLmNvbScpLFxuICAgICAgaW5saW5lUG9saWNpZXM6IHtcbiAgICAgICAgWydsYW1iZGEtaW52b2tlLXBvbGljeSddOiBuZXcgaWFtLlBvbGljeURvY3VtZW50KHtcbiAgICAgICAgICBzdGF0ZW1lbnRzOiBbXG4gICAgICAgICAgICBuZXcgaWFtLlBvbGljeVN0YXRlbWVudCh7XG4gICAgICAgICAgICAgIGVmZmVjdDogaWFtLkVmZmVjdC5BTExPVyxcbiAgICAgICAgICAgICAgYWN0aW9uczogW1xuICAgICAgICAgICAgICAgICdsYW1iZGE6SW52b2tlRnVuY3Rpb24nLFxuICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAgICAgICAgICBsYW1iZGFGdW5jdGlvbi5mdW5jdGlvbkFybixcbiAgICAgICAgICAgICAgICBgJHtsYW1iZGFGdW5jdGlvbi5mdW5jdGlvbkFybn06KmAsXG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB9KSxcbiAgICAgICAgICBdLFxuICAgICAgICB9KSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyDwn5GHU2NoZWR1bGVcbiAgICBuZXcgc2NoZWR1bGVyLkNmblNjaGVkdWxlKHRoaXMsICdTY2hlZHVsZScsIHtcbiAgICAgIG5hbWU6IHVuZGVmaW5lZCxcbiAgICAgIGRlc2NyaXB0aW9uOiAnYXdzIGFjY291bnQgY29uc3QgcmVwb3J0cy4nLFxuICAgICAgc3RhdGU6ICdFTkFCTEVEJyxcbiAgICAgIC8vZ3JvdXBOYW1lOiBzY2hlZHVsZUdyb3VwLm5hbWUsIC8vIGRlZmF1bHRcbiAgICAgIGZsZXhpYmxlVGltZVdpbmRvdzoge1xuICAgICAgICBtb2RlOiAnT0ZGJyxcbiAgICAgIH0sXG4gICAgICBzY2hlZHVsZUV4cHJlc3Npb25UaW1lem9uZTogcHJvcHMuc2NoZWR1bGVUaW1lem9uZSA/PyAnVVRDJyxcbiAgICAgIHNjaGVkdWxlRXhwcmVzc2lvbjogJ2Nyb24oMSA5ICogKiA/ICopJyxcbiAgICAgIHRhcmdldDoge1xuICAgICAgICBhcm46IGxhbWJkYUZ1bmN0aW9uLmZ1bmN0aW9uQXJuLFxuICAgICAgICByb2xlQXJuOiBzY2hlZHVsZXJFeGVjdXRpb25Sb2xlLnJvbGVBcm4sXG4gICAgICAgIGlucHV0OiBKU09OLnN0cmluZ2lmeSh7IFR5cGU6IHByb3BzLmNvc3RHcm91cFR5cGUgfSksXG4gICAgICAgIHJldHJ5UG9saWN5OiB7XG4gICAgICAgICAgbWF4aW11bUV2ZW50QWdlSW5TZWNvbmRzOiA2MCxcbiAgICAgICAgICBtYXhpbXVtUmV0cnlBdHRlbXB0czogMCxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cblxufSJdfQ==