@cloud-carbon-footprint/aws
Version:
The core logic to get cloud usage data and estimate energy and carbon emissions from Amazon Web Services.
164 lines • 7.43 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ServiceWrapper = void 0;
const client_s3_1 = require("@aws-sdk/client-s3");
const client_cloudwatch_1 = require("@aws-sdk/client-cloudwatch");
const client_cloudwatch_logs_1 = require("@aws-sdk/client-cloudwatch-logs");
const client_cost_explorer_1 = require("@aws-sdk/client-cost-explorer");
const client_athena_1 = require("@aws-sdk/client-athena");
const client_glue_1 = require("@aws-sdk/client-glue");
const csvtojson_1 = __importDefault(require("csvtojson"));
const ramda_1 = require("ramda");
const stream_1 = require("stream");
const common_1 = require("@cloud-carbon-footprint/common");
class ServiceWrapper {
cloudWatch;
cloudWatchLogs;
costExplorer;
s3;
athena;
glue;
constructor(cloudWatch, cloudWatchLogs, costExplorer, s3, athena, glue) {
this.cloudWatch = cloudWatch;
this.cloudWatchLogs = cloudWatchLogs;
this.costExplorer = costExplorer;
this.s3 = s3;
this.athena = athena;
this.glue = glue;
}
async getCostAndUsageResponse(params) {
return [await this.costExplorer.send(new client_cost_explorer_1.GetCostAndUsageCommand(params))];
}
async getMetricDataResponse(params) {
return [await this.cloudWatch.send(new client_cloudwatch_1.GetMetricDataCommand(params))];
}
async getRightsizingRecommendationResponse(params) {
return [
await this.costExplorer.send(new client_cost_explorer_1.GetRightsizingRecommendationCommand(params)),
];
}
async getAthenaQueryResults(queryExecutionInput) {
if (!this.athena)
throw new Error('Athena client not configured');
return [
await this.athena.send(new client_athena_1.GetQueryResultsCommand(queryExecutionInput)),
];
}
checkForPartialData = (array) => {
const isPartialData = array.some((obj) => obj.StatusCode === 'PartialData');
if (isPartialData) {
throw new common_1.PartialDataError('Partial Data Returned from AWS');
}
};
async getQueryByInterval(intervalInDays, func, start, end, ...args) {
let startCopy = new Date(start);
let endCopy = new Date(new Date(start).setDate(start.getDate() + intervalInDays));
const promiseArray = [];
while (endCopy < end) {
promiseArray.push(func(startCopy, endCopy, ...args));
startCopy = new Date(new Date(startCopy).setDate(start.getDate() + intervalInDays));
endCopy = new Date(new Date(startCopy).setDate(start.getDate() + intervalInDays));
}
promiseArray.push(func(startCopy, end, ...args));
return Promise.all(promiseArray);
}
async getCloudWatchLogQueryResults(params) {
return await this.cloudWatchLogs.send(new client_cloudwatch_logs_1.GetQueryResultsCommand(params));
}
async describeLogGroups(params) {
return await this.cloudWatchLogs.send(new client_cloudwatch_logs_1.DescribeLogGroupsCommand(params));
}
async describeCloudWatchLogsQueries(params) {
return await this.cloudWatchLogs.send(new client_cloudwatch_logs_1.DescribeQueriesCommand(params));
}
async startCloudWatchLogsQuery(params) {
return await this.cloudWatchLogs.send(new client_cloudwatch_logs_1.StartQueryCommand(params));
}
async startAthenaQueryExecution(queryParams) {
if (!this.athena)
throw new Error('Athena client not configured');
return await this.athena.send(new client_athena_1.StartQueryExecutionCommand(queryParams));
}
async getAthenaQueryExecution(queryExecutionInput) {
if (!this.athena)
throw new Error('Athena client not configured');
return await this.athena.send(new client_athena_1.GetQueryExecutionCommand(queryExecutionInput));
}
async getAthenaQueryResultSets(queryExecutionInput) {
return await this.getAthenaQueryResults(queryExecutionInput);
}
async getCostAndUsageResponses(params) {
return await this.getCostAndUsageResponse(params);
}
async getMetricDataResponses(params) {
const response = await this.getMetricDataResponse(params);
this.checkForPartialData(response[0].MetricDataResults);
return response;
}
async getRightsizingRecommendationsResponses(params) {
return await this.getRightsizingRecommendationResponse(params);
}
async listBucketObjects(params) {
return await this.s3.send(new client_s3_1.ListObjectsV2Command(params));
}
async getComputeOptimizerRecommendationsResponse(params) {
const response = await this.s3.send(new client_s3_1.GetObjectCommand(params));
if (!response.Body) {
throw new Error('GetObject response has no Body');
}
const nodeStream = response.Body instanceof stream_1.Readable
? response.Body
: stream_1.Readable.from(response.Body);
const parsedCsv = await (0, csvtojson_1.default)().fromStream(nodeStream);
return JSON.parse(JSON.stringify(parsedCsv));
}
async getAthenaTableDescription(params) {
if (!this.glue)
throw new Error('Glue client not configured');
return await this.glue.send(new client_glue_1.GetTableCommand(params));
}
}
exports.ServiceWrapper = ServiceWrapper;
__decorate([
enablePagination('NextToken')
], ServiceWrapper.prototype, "getAthenaQueryResultSets", null);
__decorate([
enablePagination('NextPageToken')
], ServiceWrapper.prototype, "getCostAndUsageResponses", null);
__decorate([
enablePagination('NextToken')
], ServiceWrapper.prototype, "getMetricDataResponses", null);
__decorate([
enablePagination('NextPageToken')
], ServiceWrapper.prototype, "getRightsizingRecommendationsResponses", null);
function enablePagination(nextPageProperty) {
return (target, propertyKey, descriptor) => {
const originalMethod = descriptor.value;
descriptor.value = async function (props) {
const responses = [];
let latestResponse;
do {
const args = [
{
...props,
[nextPageProperty]: (0, ramda_1.path)([responses.length - 1, nextPageProperty], responses),
},
];
latestResponse = (await originalMethod.apply(this, args))[0];
responses.push(latestResponse);
} while ((0, ramda_1.path)([nextPageProperty], latestResponse));
return responses;
};
return descriptor;
};
}
//# sourceMappingURL=ServiceWrapper.js.map