This is an automated email from the ASF dual-hosted git repository. bhliva pushed a commit to branch billing_gcp in repository https://gitbox.apache.org/repos/asf/incubator-dlab.git
commit 310b9c55db6a6e9205934c274beb471b0dd2bad4 Author: bhliva <[email protected]> AuthorDate: Mon Mar 4 17:33:43 2019 +0200 DLAB-000 billing mock on gcp implemented --- services/provisioning-service/provisioning.yml | 4 +- .../dlab/backendapi/dao/azure/AzureBillingDAO.java | 2 +- .../dlab/backendapi/dao/gcp/GcpBillingDao.java | 194 +++++++++++++++++---- .../backendapi/modules/GcpSelfServiceModule.java | 75 ++++---- .../resources/dto/gcp/GcpBillingFilter.java | 37 ++++ .../resources/gcp/BillingResourceGcp.java | 56 ++++++ .../dlab/backendapi/service/BillingService.java | 87 +++++---- .../backendapi/service/aws/AwsBillingService.java | 14 -- .../service/azure/AzureBillingService.java | 150 ++++++++-------- .../backendapi/service/gcp/GcpBillingService.java | 55 ++++++ 10 files changed, 468 insertions(+), 206 deletions(-) diff --git a/services/provisioning-service/provisioning.yml b/services/provisioning-service/provisioning.yml index e14ce94..a97dd4a 100644 --- a/services/provisioning-service/provisioning.yml +++ b/services/provisioning-service/provisioning.yml @@ -56,7 +56,7 @@ server: - type: https port: 8084 certAlias: dlab - validateCerts: true + validateCerts: false keyStorePath: ${KEY_STORE_PATH} keyStorePassword: ${KEY_STORE_PASSWORD} trustStorePath: ${TRUST_STORE_PATH} @@ -66,7 +66,7 @@ server: - type: https port: 8085 certAlias: dlab - validateCerts: true + validateCerts: false keyStorePath: ${KEY_STORE_PATH} keyStorePassword: ${KEY_STORE_PASSWORD} trustStorePath: ${TRUST_STORE_PATH} diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/azure/AzureBillingDAO.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/azure/AzureBillingDAO.java index ad818f8..401c83c 100644 --- a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/azure/AzureBillingDAO.java +++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/azure/AzureBillingDAO.java @@ -52,7 +52,7 @@ import static com.mongodb.client.model.Projections.include; public class AzureBillingDAO extends BaseBillingDAO<AzureBillingFilter> { public static final String SIZE = "size"; - public Document getReport(UserInfo userInfo, AzureBillingFilter filter) { + public Document getReport(UserInfo userInfo, AzureBillingFilter filter) { boolean isFullReport = UserRoles.checkAccess(userInfo, RoleType.PAGE, "/api/infrastructure_provision/billing"); setUserFilter(userInfo, filter, isFullReport); diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/gcp/GcpBillingDao.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/gcp/GcpBillingDao.java index 1bb4215..4a51272 100644 --- a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/gcp/GcpBillingDao.java +++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/gcp/GcpBillingDao.java @@ -19,43 +19,163 @@ package com.epam.dlab.backendapi.dao.gcp; import com.epam.dlab.auth.UserInfo; -import com.epam.dlab.backendapi.dao.BillingDAO; -import com.epam.dlab.backendapi.resources.dto.BillingFilter; +import com.epam.dlab.backendapi.dao.BaseBillingDAO; +import com.epam.dlab.backendapi.resources.dto.gcp.GcpBillingFilter; +import com.epam.dlab.backendapi.roles.RoleType; +import com.epam.dlab.backendapi.roles.UserRoles; +import com.epam.dlab.billing.BillingCalculationUtils; +import com.epam.dlab.billing.DlabResourceType; +import com.epam.dlab.dto.UserInstanceStatus; +import com.mongodb.client.AggregateIterable; +import org.apache.commons.lang3.StringUtils; import org.bson.Document; +import org.bson.conversions.Bson; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static com.epam.dlab.MongoKeyWords.*; +import static com.epam.dlab.backendapi.dao.MongoCollections.BILLING; +import static com.epam.dlab.backendapi.dao.aws.AwsBillingDAO.DLAB_RESOURCE_TYPE; +import static com.epam.dlab.backendapi.dao.aws.AwsBillingDAO.TAG_RESOURCE_ID; +import static com.epam.dlab.model.aws.ReportLine.*; +import static com.mongodb.client.model.Accumulators.*; +import static com.mongodb.client.model.Aggregates.*; +import static com.mongodb.client.model.Filters.and; +import static com.mongodb.client.model.Filters.in; + +public class GcpBillingDao extends BaseBillingDAO<GcpBillingFilter> { + @Override + public Double getTotalCost() { + return null; + } + + @Override + public Double getUserCost(String user) { + return null; + } + + @Override + public int getBillingQuoteUsed() { + return 0; + } + + @Override + public int getBillingUserQuoteUsed(String user) { + return 0; + } + + @Override + public boolean isBillingQuoteReached() { + return false; + } + + @Override + public boolean isUserQuoteReached(String user) { + return false; + } + + @Override + protected void appendSsnAndEdgeNodeType(List<String> shapeNames, Map<String, ShapeInfo> shapes) { + + } + + public Document getReport(UserInfo userInfo, GcpBillingFilter filter) { + // Create filter + List<Bson> conditions = new ArrayList<>(); + boolean isFullReport = UserRoles.checkAccess(userInfo, RoleType.PAGE, "/api/infrastructure_provision/billing"); + setUserFilter(userInfo, filter, isFullReport); + addCondition(conditions, USER, filter.getUser()); + addCondition(conditions, FIELD_PRODUCT, filter.getProduct()); + + // Create aggregation conditions + + List<Bson> pipeline = new ArrayList<>(); + if (!conditions.isEmpty()) { + pipeline.add(match(and(conditions))); + } + pipeline.add( + group(getGroupingFields(USER, FIELD_DLAB_ID, DLAB_RESOURCE_TYPE, FIELD_PRODUCT, FIELD_RESOURCE_TYPE, + FIELD_CURRENCY_CODE), + sum(FIELD_COST, "$" + FIELD_COST), + min(USAGE_FROM, "$" + FIELD_USAGE_DATE), + max(USAGE_TO, "$" + FIELD_USAGE_DATE) + )); + pipeline.add( + sort(new Document(ID + "." + USER, 1) + .append(ID + "." + FIELD_DLAB_ID, 1) + .append(ID + "." + RESOURCE_TYPE, 1) + .append(ID + "." + FIELD_PRODUCT, 1)) + ); + + // Get billing report and the list of shape info + AggregateIterable<Document> agg = getCollection(BILLING).aggregate(pipeline); + Map<String, ShapeInfo> shapes = getShapes(filter.getShape()); + + // Build billing report lines + List<Document> reportItems = new ArrayList<>(); + boolean filterByShape = !(filter.getShape() == null || filter.getShape().isEmpty()); + String usageDateStart = null; + String usageDateEnd = null; + double costTotal = 0; + + for (Document d : agg) { + Document id = (Document) d.get(ID); + String resourceId = id.getString(FIELD_DLAB_ID); + ShapeInfo shape = shapes.get(resourceId); + final UserInstanceStatus status = Optional.ofNullable(shape).map(ShapeInfo::getStatus).orElse(null); + if ((filterByShape && shape == null) || (!filter.getStatuses().isEmpty() && filter.getStatuses().stream() + .noneMatch(s -> s.equals(status)))) { + continue; + } + + String resourceTypeId = DlabResourceType.getResourceTypeName(id.getString(DLAB_RESOURCE_TYPE)); + String shapeName = generateShapeName(shape); + String dateStart = d.getString(USAGE_FROM); + if (StringUtils.compare(usageDateStart, dateStart, false) > 0) { + usageDateStart = dateStart; + } + String dateEnd = d.getString(USAGE_TO); + if (StringUtils.compare(usageDateEnd, dateEnd) < 0) { + usageDateEnd = dateEnd; + } + double cost = BillingCalculationUtils.round(d.getDouble(FIELD_COST), 2); + costTotal += cost; + + Document item = new Document() + .append(FIELD_USER_ID, getUserOrDefault(id.getString(USER))) + .append(FIELD_DLAB_ID, resourceId) + .append(DLAB_RESOURCE_TYPE, resourceTypeId) + .append(SHAPE, shapeName) + .append(STATUS, + Optional.ofNullable(status).map(UserInstanceStatus::toString).orElse(StringUtils.EMPTY)) + .append(FIELD_PRODUCT, id.getString(FIELD_PRODUCT)) + .append(FIELD_RESOURCE_TYPE, id.getString(FIELD_RESOURCE_TYPE)) + .append(FIELD_COST, BillingCalculationUtils.formatDouble(cost)) + .append(FIELD_CURRENCY_CODE, id.getString(FIELD_CURRENCY_CODE)) + .append(USAGE_FROM, dateStart) + .append(USAGE_TO, dateEnd); + reportItems.add(item); + } + + return new Document() + .append(SERVICE_BASE_NAME, settings.getServiceBaseName()) + .append(TAG_RESOURCE_ID, settings.getConfTagResourceId()) + .append(USAGE_FROM, usageDateStart) + .append(USAGE_TO, usageDateEnd) + .append(ITEMS, reportItems) + .append(COST_TOTAL, BillingCalculationUtils.formatDouble(BillingCalculationUtils.round(costTotal, 2))) + .append(FIELD_CURRENCY_CODE, (reportItems.isEmpty() ? null : + reportItems.get(0).getString(FIELD_CURRENCY_CODE))) + .append(FULL_REPORT, isFullReport); + } + + private void addCondition(List<Bson> conditions, String fieldName, List<String> values) { + if (values != null && !values.isEmpty()) { + conditions.add(in(fieldName, values)); + } + } -public class GcpBillingDao implements BillingDAO<BillingFilter> { - @Override - public Double getTotalCost() { - return null; - } - - @Override - public Double getUserCost(String user) { - return null; - } - - @Override - public int getBillingQuoteUsed() { - return 0; - } - - @Override - public int getBillingUserQuoteUsed(String user) { - return 0; - } - - @Override - public boolean isBillingQuoteReached() { - return false; - } - - @Override - public boolean isUserQuoteReached(String user) { - return false; - } - - @Override - public Document getReport(UserInfo userInfo, BillingFilter filter) { - return null; - } } diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/GcpSelfServiceModule.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/GcpSelfServiceModule.java index 03aee60..e48c26f 100644 --- a/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/GcpSelfServiceModule.java +++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/GcpSelfServiceModule.java @@ -26,10 +26,13 @@ import com.epam.dlab.backendapi.dao.gcp.GcpBillingDao; import com.epam.dlab.backendapi.dao.gcp.GcpKeyDao; import com.epam.dlab.backendapi.resources.callback.gcp.EdgeCallbackGcp; import com.epam.dlab.backendapi.resources.callback.gcp.KeyUploaderCallbackGcp; +import com.epam.dlab.backendapi.resources.gcp.BillingResourceGcp; import com.epam.dlab.backendapi.resources.gcp.ComputationalResourceGcp; import com.epam.dlab.backendapi.resources.gcp.GcpOauthResource; +import com.epam.dlab.backendapi.service.BillingService; import com.epam.dlab.backendapi.service.InfrastructureInfoService; import com.epam.dlab.backendapi.service.InfrastructureTemplateService; +import com.epam.dlab.backendapi.service.gcp.GcpBillingService; import com.epam.dlab.backendapi.service.gcp.GcpInfrastructureInfoService; import com.epam.dlab.backendapi.service.gcp.GcpInfrastructureTemplateService; import com.epam.dlab.cloud.CloudModule; @@ -46,44 +49,46 @@ import org.quartz.impl.StdSchedulerFactory; public class GcpSelfServiceModule extends CloudModule { - private static final String MONGO_URI_FORMAT = "mongodb://%s:%s@%s:%d/%s"; - private static final String QUARTZ_MONGO_URI_PROPERTY = "org.quartz.jobStore.mongoUri"; - private static final String QUARTZ_DB_NAME = "org.quartz.jobStore.dbName"; + private static final String MONGO_URI_FORMAT = "mongodb://%s:%s@%s:%d/%s"; + private static final String QUARTZ_MONGO_URI_PROPERTY = "org.quartz.jobStore.mongoUri"; + private static final String QUARTZ_DB_NAME = "org.quartz.jobStore.dbName"; - @Override - @SuppressWarnings("unchecked") - public void init(Environment environment, Injector injector) { + @Override + @SuppressWarnings("unchecked") + public void init(Environment environment, Injector injector) { - environment.jersey().register(injector.getInstance(EdgeCallbackGcp.class)); - environment.jersey().register(injector.getInstance(KeyUploaderCallbackGcp.class)); - environment.jersey().register(injector.getInstance(ComputationalResourceGcp.class)); - if (injector.getInstance(SelfServiceApplicationConfiguration.class).isGcpOuauth2AuthenticationEnabled()) { - environment.jersey().register(injector.getInstance(GcpOauthResource.class)); - } - injector.getInstance(SecurityFactory.class).configure(injector, environment, - SelfServiceSecurityAuthenticator.class, injector.getInstance(Authorizer.class)); + environment.jersey().register(injector.getInstance(EdgeCallbackGcp.class)); + environment.jersey().register(injector.getInstance(KeyUploaderCallbackGcp.class)); + environment.jersey().register(injector.getInstance(ComputationalResourceGcp.class)); + environment.jersey().register(injector.getInstance(BillingResourceGcp.class)); + if (injector.getInstance(SelfServiceApplicationConfiguration.class).isGcpOuauth2AuthenticationEnabled()) { + environment.jersey().register(injector.getInstance(GcpOauthResource.class)); + } + injector.getInstance(SecurityFactory.class).configure(injector, environment, + SelfServiceSecurityAuthenticator.class, injector.getInstance(Authorizer.class)); - } + } - @Override - protected void configure() { - bind((KeyDAO.class)).to(GcpKeyDao.class); - bind(InfrastructureInfoService.class).to(GcpInfrastructureInfoService.class); - bind(InfrastructureTemplateService.class).to(GcpInfrastructureTemplateService.class); - bind(SchedulerConfiguration.class).toInstance( - new SchedulerConfiguration(SelfServiceApplication.class.getPackage().getName())); - bind(BillingDAO.class).toInstance(new GcpBillingDao()); - } + @Override + protected void configure() { + bind(BillingService.class).to(GcpBillingService.class); + bind((KeyDAO.class)).to(GcpKeyDao.class); + bind(InfrastructureInfoService.class).to(GcpInfrastructureInfoService.class); + bind(InfrastructureTemplateService.class).to(GcpInfrastructureTemplateService.class); + bind(BillingDAO.class).to(GcpBillingDao.class); + bind(SchedulerConfiguration.class).toInstance( + new SchedulerConfiguration(SelfServiceApplication.class.getPackage().getName())); + } - @Provides - @Singleton - Scheduler provideScheduler(SelfServiceApplicationConfiguration configuration) throws SchedulerException { - final MongoServiceFactory mongoFactory = configuration.getMongoFactory(); - final String database = mongoFactory.getDatabase(); - final String mongoUri = String.format(MONGO_URI_FORMAT, mongoFactory.getUsername(), mongoFactory.getPassword(), - mongoFactory.getHost(), mongoFactory.getPort(), database); - System.setProperty(QUARTZ_MONGO_URI_PROPERTY, mongoUri); - System.setProperty(QUARTZ_DB_NAME, database); - return StdSchedulerFactory.getDefaultScheduler(); - } + @Provides + @Singleton + Scheduler provideScheduler(SelfServiceApplicationConfiguration configuration) throws SchedulerException { + final MongoServiceFactory mongoFactory = configuration.getMongoFactory(); + final String database = mongoFactory.getDatabase(); + final String mongoUri = String.format(MONGO_URI_FORMAT, mongoFactory.getUsername(), mongoFactory.getPassword(), + mongoFactory.getHost(), mongoFactory.getPort(), database); + System.setProperty(QUARTZ_MONGO_URI_PROPERTY, mongoUri); + System.setProperty(QUARTZ_DB_NAME, database); + return StdSchedulerFactory.getDefaultScheduler(); + } } diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/gcp/GcpBillingFilter.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/gcp/GcpBillingFilter.java new file mode 100644 index 0000000..2966146 --- /dev/null +++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/gcp/GcpBillingFilter.java @@ -0,0 +1,37 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.epam.dlab.backendapi.resources.dto.gcp; + +import com.epam.dlab.backendapi.resources.dto.BillingFilter; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.util.List; + +@Data +@JsonIgnoreProperties(ignoreUnknown = true) +public class GcpBillingFilter extends BillingFilter { + + @JsonProperty + private List<String> shape; + @JsonProperty + private List<String> product; +} diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/gcp/BillingResourceGcp.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/gcp/BillingResourceGcp.java new file mode 100644 index 0000000..8218ba6 --- /dev/null +++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/gcp/BillingResourceGcp.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.epam.dlab.backendapi.resources.gcp; + +import com.epam.dlab.auth.UserInfo; +import com.epam.dlab.backendapi.resources.dto.gcp.GcpBillingFilter; +import com.epam.dlab.backendapi.service.BillingService; +import com.google.inject.Inject; +import io.dropwizard.auth.Auth; +import org.bson.Document; + +import javax.validation.Valid; +import javax.validation.constraints.NotNull; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +@Path("/billing") +public class BillingResourceGcp { + + @Inject + private BillingService billingService; + + /** + * Returns the billing report. + * + * @param userInfo user info. + * @param formDTO filter for report data. + */ + @POST + @Path("/report") + @Produces(MediaType.APPLICATION_JSON) + @SuppressWarnings("unchecked") + public Document getBillingReport(@Auth UserInfo userInfo, @Valid @NotNull GcpBillingFilter formDTO) { + return billingService.getBillingReport(userInfo, formDTO); + } + +} diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/BillingService.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/BillingService.java index f9098f8..cd747e6 100644 --- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/BillingService.java +++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/BillingService.java @@ -18,66 +18,81 @@ package com.epam.dlab.backendapi.service; import com.epam.dlab.auth.UserInfo; import com.epam.dlab.backendapi.dao.BaseBillingDAO; +import com.epam.dlab.backendapi.dao.BillingDAO; import com.epam.dlab.backendapi.resources.dto.BillingFilter; import com.epam.dlab.backendapi.util.CSVFormatter; import com.epam.dlab.exceptions.DlabException; +import com.google.inject.Inject; import jersey.repackaged.com.google.common.collect.Lists; +import lombok.extern.slf4j.Slf4j; import org.bson.Document; import java.text.ParseException; import java.util.List; +@Slf4j public abstract class BillingService<T extends BillingFilter> { - protected abstract Document getReport(UserInfo userInfo, T filter); + @Inject + private BillingDAO billingDAO; - protected String getValueOrEmpty(Document document, String key) { - String value = document.getString(key); - return value == null ? "" : value; - } + public Document getReport(UserInfo userInfo, T filter) { + log.trace("Get billing report for user {} with filter {}", userInfo.getName(), filter); + try { + return billingDAO.getReport(userInfo, filter); + } catch (RuntimeException t) { + log.error("Cannot load billing report for user {} with filter {}", userInfo.getName(), filter, t); + throw new DlabException("Cannot load billing report: " + t.getLocalizedMessage(), t); + } + } - String getHeaders(boolean full) { - return CSVFormatter.formatLine(getHeadersList(full), CSVFormatter.SEPARATOR); - } + protected String getValueOrEmpty(Document document, String key) { + String value = document.getString(key); + return value == null ? "" : value; + } - public Document getBillingReport(UserInfo userInfo, T filter) { - filter.getUser().replaceAll(s -> s.equalsIgnoreCase(BaseBillingDAO.SHARED_RESOURCE_NAME) ? null : s); - return getReport(userInfo, filter); - } + String getHeaders(boolean full) { + return CSVFormatter.formatLine(getHeadersList(full), CSVFormatter.SEPARATOR); + } - public byte[] downloadReport(UserInfo userInfo, T filter) { - return prepareReport(getReport(userInfo, filter)).getBytes(); - } + public Document getBillingReport(UserInfo userInfo, T filter) { + filter.getUser().replaceAll(s -> s.equalsIgnoreCase(BaseBillingDAO.SHARED_RESOURCE_NAME) ? null : s); + return getReport(userInfo, filter); + } - String prepareReport(Document document) { - try { - StringBuilder builder = - new StringBuilder(CSVFormatter.formatLine(Lists.newArrayList(getFirstLine(document)), - CSVFormatter.SEPARATOR, '\"')); + public byte[] downloadReport(UserInfo userInfo, T filter) { + return prepareReport(getReport(userInfo, filter)).getBytes(); + } - Boolean full = (Boolean) document.get(BaseBillingDAO.FULL_REPORT); - builder.append(getHeaders(full)); + String prepareReport(Document document) { + try { + StringBuilder builder = + new StringBuilder(CSVFormatter.formatLine(Lists.newArrayList(getFirstLine(document)), + CSVFormatter.SEPARATOR, '\"')); - @SuppressWarnings("unchecked") - List<Document> items = (List<Document>) document.get(BaseBillingDAO.ITEMS); + Boolean full = (Boolean) document.get(BaseBillingDAO.FULL_REPORT); + builder.append(getHeaders(full)); - items.forEach(d -> builder.append(getLine(full, d))); + @SuppressWarnings("unchecked") + List<Document> items = (List<Document>) document.get(BaseBillingDAO.ITEMS); - builder.append(getTotal(full, document)); + items.forEach(d -> builder.append(getLine(full, d))); - return builder.toString(); - } catch (ParseException e) { - throw new DlabException("Cannot prepare CSV file", e); - } - } + builder.append(getTotal(full, document)); - public abstract String getFirstLine(Document document) throws ParseException; + return builder.toString(); + } catch (ParseException e) { + throw new DlabException("Cannot prepare CSV file", e); + } + } - public abstract List<String> getHeadersList(boolean full); + public abstract String getFirstLine(Document document) throws ParseException; - public abstract String getLine(boolean full, Document document); + public abstract List<String> getHeadersList(boolean full); - public abstract String getTotal(boolean full, Document document); + public abstract String getLine(boolean full, Document document); - public abstract String getReportFileName(UserInfo userInfo, T filter); + public abstract String getTotal(boolean full, Document document); + + public abstract String getReportFileName(UserInfo userInfo, T filter); } diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/aws/AwsBillingService.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/aws/AwsBillingService.java index ca19a3f..c89311b 100644 --- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/aws/AwsBillingService.java +++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/aws/AwsBillingService.java @@ -38,20 +38,6 @@ import java.util.List; @Singleton public class AwsBillingService extends BillingService<AwsBillingFilter> { - @Inject - private BillingDAO billingDAO; - - @Override - protected Document getReport(UserInfo userInfo, AwsBillingFilter filter) { - log.trace("Get billing report for user {} with filter {}", userInfo.getName(), filter); - try { - return billingDAO.getReport(userInfo, filter); - } catch (RuntimeException t) { - log.error("Cannot load billing report for user {} with filter {}", userInfo.getName(), filter, t); - throw new DlabException("Cannot load billing report: " + t.getLocalizedMessage(), t); - } - } - @Override public String getReportFileName(UserInfo userInfo, AwsBillingFilter filter) { return "aws-billing-report.csv"; diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/azure/AzureBillingService.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/azure/AzureBillingService.java index 7a684f7..cac4b41 100644 --- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/azure/AzureBillingService.java +++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/azure/AzureBillingService.java @@ -24,7 +24,6 @@ import com.epam.dlab.backendapi.dao.azure.AzureBillingDAO; import com.epam.dlab.backendapi.resources.dto.azure.AzureBillingFilter; import com.epam.dlab.backendapi.service.BillingService; import com.epam.dlab.backendapi.util.CSVFormatter; -import com.epam.dlab.exceptions.DlabException; import com.google.inject.Inject; import com.google.inject.Singleton; import lombok.extern.slf4j.Slf4j; @@ -39,84 +38,73 @@ import java.util.List; @Singleton public class AzureBillingService extends BillingService<AzureBillingFilter> { - @Inject - private BillingDAO billingDAO; - - @Override - public Document getReport(UserInfo userInfo, AzureBillingFilter filter) { - log.trace("Get billing report for user {} with filter {}", userInfo.getName(), filter); - try { - return billingDAO.getReport(userInfo, filter); - } catch (RuntimeException t) { - log.error("Cannot load billing report for user {} with filter {}", userInfo.getName(), filter, t); - throw new DlabException("Cannot load billing report: " + t.getLocalizedMessage(), t); - } - } - - @Override - public String getReportFileName(UserInfo userInfo, AzureBillingFilter filter) { - return "azure-billing-report.csv"; - } - - @Override - public String getFirstLine(Document document) throws ParseException { - SimpleDateFormat from = new SimpleDateFormat("yyyy-MM-dd"); - SimpleDateFormat to = new SimpleDateFormat("MMM dd, yyyy"); - - return String.format("Service base name: %s " + - "Available reporting period from: %s to: %s", - document.get(BaseBillingDAO.SERVICE_BASE_NAME), - to.format(from.parse((String) document.get(MongoKeyWords.USAGE_FROM))), - to.format(from.parse((String) document.get(MongoKeyWords.USAGE_TO)))); - } - - public List<String> getHeadersList(boolean full) { - List<String> headers = new ArrayList<>(); - - if (full) { - headers.add("USER"); - } - - headers.add("ENVIRONMENT NAME"); - headers.add("RESOURCE TYPE"); - headers.add("INSTANCE SIZE"); - headers.add("CATEGORY"); - headers.add("SERVICE CHARGES"); - - return headers; - } - - @Override - public String getLine(boolean full, Document document) { - List<String> items = new ArrayList<>(); - - if (full) { - items.add(getValueOrEmpty(document, MongoKeyWords.DLAB_USER)); - } - - items.add(getValueOrEmpty(document, MongoKeyWords.DLAB_ID)); - items.add(getValueOrEmpty(document, MongoKeyWords.RESOURCE_TYPE)); - items.add(getValueOrEmpty(document, AzureBillingDAO.SIZE).replace(System.lineSeparator(), " ")); - items.add(getValueOrEmpty(document, MongoKeyWords.METER_CATEGORY)); - - items.add(getValueOrEmpty(document, MongoKeyWords.COST_STRING) - + " " + getValueOrEmpty(document, MongoKeyWords.CURRENCY_CODE)); - - return CSVFormatter.formatLine(items, CSVFormatter.SEPARATOR); - } - - @Override - public String getTotal(boolean full, Document document) { - int padding = getHeadersList(full).size() - 1; - - List<String> items = new ArrayList<>(); - while (padding-- > 0) { - items.add(""); - } - - items.add(String.format("Total: %s %s", getValueOrEmpty(document, MongoKeyWords.COST_STRING), - getValueOrEmpty(document, MongoKeyWords.CURRENCY_CODE))); - - return CSVFormatter.formatLine(items, CSVFormatter.SEPARATOR); - } + @Inject + private BillingDAO billingDAO; + + @Override + public String getReportFileName(UserInfo userInfo, AzureBillingFilter filter) { + return "azure-billing-report.csv"; + } + + @Override + public String getFirstLine(Document document) throws ParseException { + SimpleDateFormat from = new SimpleDateFormat("yyyy-MM-dd"); + SimpleDateFormat to = new SimpleDateFormat("MMM dd, yyyy"); + + return String.format("Service base name: %s " + + "Available reporting period from: %s to: %s", + document.get(BaseBillingDAO.SERVICE_BASE_NAME), + to.format(from.parse((String) document.get(MongoKeyWords.USAGE_FROM))), + to.format(from.parse((String) document.get(MongoKeyWords.USAGE_TO)))); + } + + public List<String> getHeadersList(boolean full) { + List<String> headers = new ArrayList<>(); + + if (full) { + headers.add("USER"); + } + + headers.add("ENVIRONMENT NAME"); + headers.add("RESOURCE TYPE"); + headers.add("INSTANCE SIZE"); + headers.add("CATEGORY"); + headers.add("SERVICE CHARGES"); + + return headers; + } + + @Override + public String getLine(boolean full, Document document) { + List<String> items = new ArrayList<>(); + + if (full) { + items.add(getValueOrEmpty(document, MongoKeyWords.DLAB_USER)); + } + + items.add(getValueOrEmpty(document, MongoKeyWords.DLAB_ID)); + items.add(getValueOrEmpty(document, MongoKeyWords.RESOURCE_TYPE)); + items.add(getValueOrEmpty(document, AzureBillingDAO.SIZE).replace(System.lineSeparator(), " ")); + items.add(getValueOrEmpty(document, MongoKeyWords.METER_CATEGORY)); + + items.add(getValueOrEmpty(document, MongoKeyWords.COST_STRING) + + " " + getValueOrEmpty(document, MongoKeyWords.CURRENCY_CODE)); + + return CSVFormatter.formatLine(items, CSVFormatter.SEPARATOR); + } + + @Override + public String getTotal(boolean full, Document document) { + int padding = getHeadersList(full).size() - 1; + + List<String> items = new ArrayList<>(); + while (padding-- > 0) { + items.add(""); + } + + items.add(String.format("Total: %s %s", getValueOrEmpty(document, MongoKeyWords.COST_STRING), + getValueOrEmpty(document, MongoKeyWords.CURRENCY_CODE))); + + return CSVFormatter.formatLine(items, CSVFormatter.SEPARATOR); + } } diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/gcp/GcpBillingService.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/gcp/GcpBillingService.java new file mode 100644 index 0000000..42d2095 --- /dev/null +++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/gcp/GcpBillingService.java @@ -0,0 +1,55 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.epam.dlab.backendapi.service.gcp; + +import com.epam.dlab.auth.UserInfo; +import com.epam.dlab.backendapi.resources.dto.gcp.GcpBillingFilter; +import com.epam.dlab.backendapi.service.BillingService; +import org.bson.Document; + +import java.text.ParseException; +import java.util.List; + +public class GcpBillingService extends BillingService<GcpBillingFilter> { + @Override + public String getFirstLine(Document document) throws ParseException { + return null; + } + + @Override + public List<String> getHeadersList(boolean full) { + return null; + } + + @Override + public String getLine(boolean full, Document document) { + return null; + } + + @Override + public String getTotal(boolean full, Document document) { + return null; + } + + @Override + public String getReportFileName(UserInfo userInfo, GcpBillingFilter filter) { + return null; + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
