You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dlab.apache.org by of...@apache.org on 2020/04/06 13:58:45 UTC

[incubator-dlab] branch DLAB-1571 updated: [DLAB-1694] Fixed quotas issues

This is an automated email from the ASF dual-hosted git repository.

ofuks pushed a commit to branch DLAB-1571
in repository https://gitbox.apache.org/repos/asf/incubator-dlab.git


The following commit(s) were added to refs/heads/DLAB-1571 by this push:
     new 0d8ea60  [DLAB-1694] Fixed quotas issues
     new 3ca46a9  Merge remote-tracking branch 'origin/DLAB-1571' into DLAB-1571
0d8ea60 is described below

commit 0d8ea60596cbb30a342d67d35781928dbc184b17
Author: Oleh Fuks <ol...@gmail.com>
AuthorDate: Mon Apr 6 16:58:06 2020 +0300

    [DLAB-1694] Fixed quotas issues
---
 .../epam/dlab/backendapi/dao/BaseBillingDAO.java   | 78 ++++++++++------------
 .../com/epam/dlab/backendapi/dao/BillingDAO.java   | 20 +++---
 .../interceptor/BudgetLimitInterceptor.java        | 29 ++++----
 .../schedulers/CheckApplicationQuoteScheduler.java |  5 +-
 .../schedulers/CheckProjectQuoteScheduler.java     |  5 +-
 .../schedulers/CheckUserQuoteScheduler.java        |  5 +-
 .../dlab/backendapi/service/BillingService.java    |  2 +-
 .../service/impl/BillingServiceImpl.java           | 21 +++---
 .../service/impl/ComputationalServiceImpl.java     |  7 +-
 .../service/impl/ExploratoryServiceImpl.java       |  5 +-
 .../impl/InfrastructureInfoServiceImpl.java        |  6 +-
 .../service/impl/ProjectServiceImpl.java           |  4 +-
 .../CheckApplicationQuoteSchedulerTest.java        | 28 ++++++--
 .../schedulers/CheckUserQuoteSchedulerTest.java    | 27 ++++++--
 14 files changed, 145 insertions(+), 97 deletions(-)

diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/BaseBillingDAO.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/BaseBillingDAO.java
index d22e400..a784641 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/BaseBillingDAO.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/BaseBillingDAO.java
@@ -19,30 +19,21 @@
 
 package com.epam.dlab.backendapi.dao;
 
+import com.epam.dlab.auth.UserInfo;
+import com.epam.dlab.backendapi.domain.BillingReportLine;
+import com.epam.dlab.backendapi.resources.dto.BillingFilter;
+import com.epam.dlab.backendapi.service.BillingService;
 import com.google.inject.Inject;
 import lombok.extern.slf4j.Slf4j;
-import org.bson.conversions.Bson;
 
 import java.math.BigDecimal;
-import java.util.Arrays;
-import java.util.List;
+import java.util.Collections;
 import java.util.Optional;
 import java.util.function.Supplier;
 
-import static com.epam.dlab.backendapi.dao.MongoCollections.BILLING;
-import static com.mongodb.client.model.Accumulators.sum;
-import static com.mongodb.client.model.Aggregates.group;
-import static com.mongodb.client.model.Aggregates.match;
-import static com.mongodb.client.model.Filters.eq;
-import static java.util.Collections.singletonList;
-
 @Slf4j
 public class BaseBillingDAO extends BaseDAO implements BillingDAO {
-
-	private static final String PROJECT = "project";
 	private static final int ONE_HUNDRED = 100;
-	private static final String TOTAL_FIELD_NAME = "total";
-	private static final String COST_FIELD = "$cost";
 
 	@Inject
 	protected SettingsDAO settings;
@@ -50,60 +41,69 @@ public class BaseBillingDAO extends BaseDAO implements BillingDAO {
 	private UserSettingsDAO userSettingsDAO;
 	@Inject
 	private ProjectDAO projectDAO;
+	@Inject
+	private BillingService billingService;
 
 	@Override
-	public Double getTotalCost() {
-		return aggregateBillingData(singletonList(group(null, sum(TOTAL_FIELD_NAME, COST_FIELD))));
+	public Double getTotalCost(UserInfo userInfo) {
+		return getSum(userInfo, new BillingFilter());
 	}
 
 	@Override
-	public Double getUserCost(String user) {
-		final List<Bson> pipeline = Arrays.asList(match(eq(USER, user)),
-				group(null, sum(TOTAL_FIELD_NAME, COST_FIELD)));
-		return aggregateBillingData(pipeline);
+	public Double getUserCost(String user, UserInfo userInfo) {
+		BillingFilter filter = new BillingFilter();
+		filter.setUsers(Collections.singletonList(user));
+		return getSum(userInfo, filter);
 	}
 
 	@Override
-	public Double getProjectCost(String project) {
-		final List<Bson> pipeline = Arrays.asList(match(eq(PROJECT, project)),
-				group(null, sum(TOTAL_FIELD_NAME, COST_FIELD)));
-		return aggregateBillingData(pipeline);
+	public Double getProjectCost(String project, UserInfo userInfo) {
+		BillingFilter filter = new BillingFilter();
+		filter.setProjects(Collections.singletonList(project));
+		return getSum(userInfo, filter);
 	}
 
 	@Override
-	public int getBillingQuoteUsed() {
-		return toPercentage(() -> settings.getMaxBudget(), getTotalCost());
+	public int getBillingQuoteUsed(UserInfo userInfo) {
+		return toPercentage(() -> settings.getMaxBudget(), getTotalCost(userInfo));
 	}
 
 	@Override
-	public int getBillingUserQuoteUsed(String user) {
-		return toPercentage(() -> userSettingsDAO.getAllowedBudget(user), getUserCost(user));
+	public int getBillingUserQuoteUsed(String user, UserInfo userInfo) {
+		return toPercentage(() -> userSettingsDAO.getAllowedBudget(user), getUserCost(user, userInfo));
 	}
 
 	@Override
-	public boolean isBillingQuoteReached() {
-		return getBillingQuoteUsed() >= ONE_HUNDRED;
+	public boolean isBillingQuoteReached(UserInfo userInfo) {
+		return getBillingQuoteUsed(userInfo) >= ONE_HUNDRED;
 	}
 
 	@Override
-	public boolean isUserQuoteReached(String user) {
-		final Double userCost = getUserCost(user);
+	public boolean isUserQuoteReached(String user, UserInfo userInfo) {
+		final Double userCost = getUserCost(user, userInfo);
 		return userSettingsDAO.getAllowedBudget(user)
 				.filter(allowedBudget -> userCost.intValue() != 0 && allowedBudget <= userCost)
 				.isPresent();
 	}
 
 	@Override
-	public boolean isProjectQuoteReached(String project) {
-		final Double projectCost = getProjectCost(project);
+	public boolean isProjectQuoteReached(String project, UserInfo userInfo) {
+		final Double projectCost = getProjectCost(project, userInfo);
 		return projectDAO.getAllowedBudget(project)
 				.filter(allowedBudget -> projectCost.intValue() != 0 && allowedBudget <= projectCost)
 				.isPresent();
 	}
 
 	@Override
-	public int getBillingProjectQuoteUsed(String project) {
-		return toPercentage(() -> projectDAO.getAllowedBudget(project), getProjectCost(project));
+	public int getBillingProjectQuoteUsed(String project, UserInfo userInfo) {
+		return toPercentage(() -> projectDAO.getAllowedBudget(project), getProjectCost(project, userInfo));
+	}
+
+	private double getSum(UserInfo userInfo, BillingFilter filter) {
+		return billingService.getBillingReportLines(userInfo, filter, true)
+				.stream()
+				.mapToDouble(BillingReportLine::getCost)
+				.sum();
 	}
 
 	private Integer toPercentage(Supplier<Optional<Integer>> allowedBudget, Double totalCost) {
@@ -112,10 +112,4 @@ public class BaseBillingDAO extends BaseDAO implements BillingDAO {
 				.map(Double::intValue)
 				.orElse(BigDecimal.ZERO.intValue());
 	}
-
-	private Double aggregateBillingData(List<Bson> pipeline) {
-		return Optional.ofNullable(aggregate(BILLING, pipeline).first())
-				.map(d -> d.getDouble(TOTAL_FIELD_NAME))
-				.orElse(BigDecimal.ZERO.doubleValue());
-	}
 }
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/BillingDAO.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/BillingDAO.java
index d50c62f..d5e0064 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/BillingDAO.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/BillingDAO.java
@@ -18,22 +18,24 @@
  */
 package com.epam.dlab.backendapi.dao;
 
+import com.epam.dlab.auth.UserInfo;
+
 public interface BillingDAO {
-	Double getTotalCost();
+	Double getTotalCost(UserInfo userInfo);
 
-	Double getUserCost(String user);
+	Double getUserCost(String user, UserInfo userInfo);
 
-	Double getProjectCost(String project);
+	Double getProjectCost(String project, UserInfo userInfo);
 
-	int getBillingQuoteUsed();
+	int getBillingQuoteUsed(UserInfo userInfo);
 
-	int getBillingUserQuoteUsed(String user);
+	int getBillingUserQuoteUsed(String user, UserInfo userInfo);
 
-	int getBillingProjectQuoteUsed(String project);
+	int getBillingProjectQuoteUsed(String project, UserInfo userInfo);
 
-	boolean isBillingQuoteReached();
+	boolean isBillingQuoteReached(UserInfo userInfo);
 
-	boolean isUserQuoteReached(String user);
+	boolean isUserQuoteReached(String user, UserInfo userInfo);
 
-	boolean isProjectQuoteReached(String project);
+	boolean isProjectQuoteReached(String project, UserInfo userInfo);
 }
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/interceptor/BudgetLimitInterceptor.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/interceptor/BudgetLimitInterceptor.java
index 43fdaf6..e4fab10 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/interceptor/BudgetLimitInterceptor.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/interceptor/BudgetLimitInterceptor.java
@@ -21,7 +21,10 @@ package com.epam.dlab.backendapi.interceptor;
 
 import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.annotation.Project;
+import com.epam.dlab.backendapi.annotation.User;
 import com.epam.dlab.backendapi.dao.BillingDAO;
+import com.epam.dlab.backendapi.service.SecurityService;
+import com.epam.dlab.exceptions.DlabException;
 import com.epam.dlab.exceptions.ResourceQuoteReachedException;
 import com.google.inject.Inject;
 import lombok.extern.slf4j.Slf4j;
@@ -30,7 +33,6 @@ import org.aopalliance.intercept.MethodInvocation;
 
 import java.lang.reflect.Method;
 import java.lang.reflect.Parameter;
-import java.util.Arrays;
 import java.util.Objects;
 import java.util.stream.IntStream;
 
@@ -38,10 +40,12 @@ import java.util.stream.IntStream;
 public class BudgetLimitInterceptor implements MethodInterceptor {
 	@Inject
 	private BillingDAO billingDAO;
+	@Inject
+	private SecurityService securityService;
 
 	@Override
 	public Object invoke(MethodInvocation mi) throws Throwable {
-		if (projectQuoteReached(mi) || billingDAO.isBillingQuoteReached()) {
+		if (projectQuoteReached(mi) || billingDAO.isBillingQuoteReached(securityService.getServiceAccountInfo("admin"))) {
 			final Method method = mi.getMethod();
 			log.warn("Execution of method {} failed because of reaching resource limit quote", method.getName());
 			throw new ResourceQuoteReachedException("Operation can not be finished. Resource quote is reached");
@@ -50,23 +54,20 @@ public class BudgetLimitInterceptor implements MethodInterceptor {
 		}
 	}
 
-	private Boolean userQuoteReached(MethodInvocation mi) {
-		return Arrays.stream(mi.getArguments())
-				.filter(arg -> arg.getClass().equals(UserInfo.class))
-				.findAny()
-				.map(u -> ((UserInfo) u).getName())
-				.map(billingDAO::isUserQuoteReached)
-				.orElse(Boolean.FALSE);
-	}
-
 	private Boolean projectQuoteReached(MethodInvocation mi) {
 
 		final Parameter[] parameters = mi.getMethod().getParameters();
-		return IntStream.range(0, parameters.length)
+		String project = IntStream.range(0, parameters.length)
 				.filter(i -> Objects.nonNull(parameters[i].getAnnotation(Project.class)))
 				.mapToObj(i -> (String) mi.getArguments()[i])
 				.findAny()
-				.map(billingDAO::isProjectQuoteReached)
-				.orElse(Boolean.FALSE);
+				.orElseThrow(() -> new DlabException("Project parameter wanted!"));
+		UserInfo userInfo = IntStream.range(0, parameters.length)
+				.filter(i -> Objects.nonNull(parameters[i].getAnnotation(User.class)))
+				.mapToObj(i -> (UserInfo) mi.getArguments()[i])
+				.findAny()
+				.orElseThrow(() -> new DlabException("UserInfo parameter wanted!"));
+
+		return billingDAO.isProjectQuoteReached(project, userInfo);
 	}
 }
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/schedulers/CheckApplicationQuoteScheduler.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/schedulers/CheckApplicationQuoteScheduler.java
index bca047c..35b1ad3 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/schedulers/CheckApplicationQuoteScheduler.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/schedulers/CheckApplicationQuoteScheduler.java
@@ -22,6 +22,7 @@ package com.epam.dlab.backendapi.schedulers;
 import com.epam.dlab.backendapi.dao.BillingDAO;
 import com.epam.dlab.backendapi.schedulers.internal.Scheduled;
 import com.epam.dlab.backendapi.service.EnvironmentService;
+import com.epam.dlab.backendapi.service.SecurityService;
 import com.google.inject.Inject;
 import lombok.extern.slf4j.Slf4j;
 import org.quartz.Job;
@@ -34,10 +35,12 @@ public class CheckApplicationQuoteScheduler implements Job {
 	private BillingDAO billingDAO;
 	@Inject
 	private EnvironmentService environmentService;
+	@Inject
+	private SecurityService securityService;
 
 	@Override
 	public void execute(JobExecutionContext context) {
-		if (billingDAO.isBillingQuoteReached()) {
+		if (billingDAO.isBillingQuoteReached(securityService.getServiceAccountInfo("admin"))) {
 			log.warn("Stopping all environments because of reaching budget quote");
 			environmentService.stopAll();
 		}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/schedulers/CheckProjectQuoteScheduler.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/schedulers/CheckProjectQuoteScheduler.java
index 030c10d..57598df 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/schedulers/CheckProjectQuoteScheduler.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/schedulers/CheckProjectQuoteScheduler.java
@@ -24,6 +24,7 @@ import com.epam.dlab.backendapi.domain.ProjectDTO;
 import com.epam.dlab.backendapi.schedulers.internal.Scheduled;
 import com.epam.dlab.backendapi.service.EnvironmentService;
 import com.epam.dlab.backendapi.service.ProjectService;
+import com.epam.dlab.backendapi.service.SecurityService;
 import com.google.inject.Inject;
 import lombok.extern.slf4j.Slf4j;
 import org.quartz.Job;
@@ -39,13 +40,15 @@ public class CheckProjectQuoteScheduler implements Job {
 	private EnvironmentService environmentService;
 	@Inject
 	private ProjectService projectService;
+	@Inject
+	private SecurityService securityService;
 
 	@Override
 	public void execute(JobExecutionContext context) {
 		projectService.getProjects()
 				.stream()
 				.map(ProjectDTO::getName)
-				.filter(billingDAO::isProjectQuoteReached)
+				.filter(p -> billingDAO.isProjectQuoteReached(p, securityService.getServiceAccountInfo("admin")))
 				.peek(p -> log.debug("Stopping {} project env because of reaching user billing quote", p))
 				.forEach(environmentService::stopProjectEnvironment);
 	}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/schedulers/CheckUserQuoteScheduler.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/schedulers/CheckUserQuoteScheduler.java
index 1e2e7f4..11aa586 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/schedulers/CheckUserQuoteScheduler.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/schedulers/CheckUserQuoteScheduler.java
@@ -23,6 +23,7 @@ import com.epam.dlab.backendapi.dao.BillingDAO;
 import com.epam.dlab.backendapi.resources.dto.UserDTO;
 import com.epam.dlab.backendapi.schedulers.internal.Scheduled;
 import com.epam.dlab.backendapi.service.EnvironmentService;
+import com.epam.dlab.backendapi.service.SecurityService;
 import com.google.inject.Inject;
 import lombok.extern.slf4j.Slf4j;
 import org.quartz.Job;
@@ -36,13 +37,15 @@ public class CheckUserQuoteScheduler implements Job {
 	private BillingDAO billingDAO;
 	@Inject
 	private EnvironmentService environmentService;
+	@Inject
+	private SecurityService securityService;
 
 	@Override
 	public void execute(JobExecutionContext context) {
 		environmentService.getUsers()
 				.stream()
 				.map(UserDTO::getName)
-				.filter(billingDAO::isUserQuoteReached)
+				.filter(u -> billingDAO.isUserQuoteReached(u, securityService.getServiceAccountInfo("admin")))
 				.peek(u -> log.warn("Stopping {} user env because of reaching user billing quote", u))
 				.forEach(environmentService::stopEnvironmentWithServiceAccount);
 	}
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 40a5c14..9925b1c 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
@@ -33,7 +33,7 @@ public interface BillingService {
 
     String downloadReport(UserInfo userInfo, BillingFilter filter);
 
-    List<BillingReportLine> getBillingReportLines(UserInfo userInfo, BillingFilter filter);
+    List<BillingReportLine> getBillingReportLines(UserInfo userInfo, BillingFilter filter, boolean isFullReport);
 
     List<BillingData> getExploratoryRemoteBillingData(UserInfo user, String endpoint, List<UserInstanceDTO> userInstanceDTOS);
 }
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/BillingServiceImpl.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/BillingServiceImpl.java
index 7d6ab11..baef8a5 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/BillingServiceImpl.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/BillingServiceImpl.java
@@ -60,6 +60,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
@@ -98,7 +99,7 @@ public class BillingServiceImpl implements BillingService {
 
     @Override
     public BillingReport getBillingReport(UserInfo user, BillingFilter filter) {
-        List<BillingReportLine> billingReportLines = getBillingReportLines(user, filter);
+        List<BillingReportLine> billingReportLines = getBillingReportLines(user, filter, isFullReport(user));
         LocalDate min = billingReportLines.stream().min(Comparator.comparing(BillingReportLine::getUsageDateFrom)).map(BillingReportLine::getUsageDateFrom).orElse(null);
         LocalDate max = billingReportLines.stream().max(Comparator.comparing(BillingReportLine::getUsageDateTo)).map(BillingReportLine::getUsageDateTo).orElse(null);
         double sum = billingReportLines.stream().mapToDouble(BillingReportLine::getCost).sum();
@@ -130,10 +131,10 @@ public class BillingServiceImpl implements BillingService {
     }
 
     @Override
-    public List<BillingReportLine> getBillingReportLines(UserInfo user, BillingFilter filter) {
+    public List<BillingReportLine> getBillingReportLines(UserInfo user, BillingFilter filter, boolean isFullReport) {
         setUserFilter(user, filter);
         Set<ProjectDTO> projects;
-        if (isFullReport(user)) {
+        if (isFullReport) {
             projects = new HashSet<>(projectService.getProjects());
         } else {
             projects = new HashSet<>(projectService.getProjects(user));
@@ -239,7 +240,7 @@ public class BillingServiceImpl implements BillingService {
         try {
             return s.get();
         } catch (InterruptedException | ExecutionException e) {
-            log.error("Cannot retrieve billing information {}", e.getMessage());
+            log.error("Cannot retrieve billing information {}", e.getMessage(), e);
             return Collections.emptyList();
         }
     }
@@ -261,14 +262,18 @@ public class BillingServiceImpl implements BillingService {
     }
 
     private Callable<List<BillingData>> getTask(UserInfo userInfo, String url, BillingFilter filter) {
+        final String dateStart = Optional.ofNullable(filter.getDateStart()).orElse("");
+        final String dateEnd = Optional.ofNullable(filter.getDateEnd()).orElse("");
+        final String dlabId = Optional.ofNullable(filter.getDlabId()).orElse("");
+        final List<String> products = Optional.ofNullable(filter.getProducts()).orElse(Collections.emptyList());
         return () -> provisioningService.get(url, userInfo.getAccessToken(),
                 new GenericType<List<BillingData>>() {
                 },
                 Stream.of(new String[][]{
-                        {"date-start", filter.getDateStart()},
-                        {"date-end", filter.getDateEnd()},
-                        {"dlab-id", filter.getDlabId()},
-                        {"product", String.join(",", filter.getProducts())}
+                        {"date-start", dateStart},
+                        {"date-end", dateEnd},
+                        {"dlab-id", dlabId},
+                        {"product", String.join(",", products)}
                 }).collect(Collectors.toMap(data -> data[0], data -> data[1])));
     }
 
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ComputationalServiceImpl.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ComputationalServiceImpl.java
index 722ee4d..6d7e663 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ComputationalServiceImpl.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ComputationalServiceImpl.java
@@ -23,6 +23,7 @@ package com.epam.dlab.backendapi.service.impl;
 import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.annotation.BudgetLimited;
 import com.epam.dlab.backendapi.annotation.Project;
+import com.epam.dlab.backendapi.annotation.User;
 import com.epam.dlab.backendapi.dao.ComputationalDAO;
 import com.epam.dlab.backendapi.dao.ExploratoryDAO;
 import com.epam.dlab.backendapi.domain.EndpointDTO;
@@ -143,7 +144,7 @@ public class ComputationalServiceImpl implements ComputationalService {
 
 	@BudgetLimited
 	@Override
-	public boolean createSparkCluster(UserInfo userInfo, SparkStandaloneClusterCreateForm form, @Project String project) {
+	public boolean createSparkCluster(@User UserInfo userInfo, SparkStandaloneClusterCreateForm form, @Project String project) {
 
 		final ProjectDTO projectDTO = projectService.get(project);
 		final UserInstanceDTO instance =
@@ -211,7 +212,7 @@ public class ComputationalServiceImpl implements ComputationalService {
 
 	@BudgetLimited
 	@Override
-	public boolean createDataEngineService(UserInfo userInfo, ComputationalCreateFormDTO formDTO,
+	public boolean createDataEngineService(@User UserInfo userInfo, ComputationalCreateFormDTO formDTO,
 										   UserComputationalResource computationalResource, @Project String project) {
 
 		final ProjectDTO projectDTO = projectService.get(project);
@@ -272,7 +273,7 @@ public class ComputationalServiceImpl implements ComputationalService {
 
 	@BudgetLimited
 	@Override
-	public void startSparkCluster(UserInfo userInfo, String expName, String compName, @Project String project) {
+	public void startSparkCluster(@User UserInfo userInfo, String expName, String compName, @Project String project) {
 		final UserInstanceDTO userInstance =
 				exploratoryDAO.fetchExploratoryFields(userInfo.getName(), project, expName, true);
 		final UserInstanceStatus requiredStatus = UserInstanceStatus.STOPPED;
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ExploratoryServiceImpl.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ExploratoryServiceImpl.java
index 6a2a615..1ee7bce 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ExploratoryServiceImpl.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ExploratoryServiceImpl.java
@@ -22,6 +22,7 @@ package com.epam.dlab.backendapi.service.impl;
 import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.annotation.BudgetLimited;
 import com.epam.dlab.backendapi.annotation.Project;
+import com.epam.dlab.backendapi.annotation.User;
 import com.epam.dlab.backendapi.dao.ComputationalDAO;
 import com.epam.dlab.backendapi.dao.ExploratoryDAO;
 import com.epam.dlab.backendapi.dao.GitCredsDAO;
@@ -105,7 +106,7 @@ public class ExploratoryServiceImpl implements ExploratoryService {
 
 	@BudgetLimited
 	@Override
-	public String start(UserInfo userInfo, String exploratoryName, @Project String project) {
+	public String start(@User UserInfo userInfo, String exploratoryName, @Project String project) {
 		return action(userInfo, project, exploratoryName, EXPLORATORY_START, STARTING);
 	}
 
@@ -121,7 +122,7 @@ public class ExploratoryServiceImpl implements ExploratoryService {
 
 	@BudgetLimited
 	@Override
-	public String create(UserInfo userInfo, Exploratory exploratory, @Project String project) {
+	public String create(@User UserInfo userInfo, Exploratory exploratory, @Project String project) {
 		boolean isAdded = false;
 		try {
 			final ProjectDTO projectDTO = projectService.get(project);
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InfrastructureInfoServiceImpl.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InfrastructureInfoServiceImpl.java
index 28b94e9..267ef36 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InfrastructureInfoServiceImpl.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InfrastructureInfoServiceImpl.java
@@ -120,7 +120,7 @@ public class InfrastructureInfoServiceImpl implements InfrastructureInfoService
 										.stream()
 										.collect(Collectors.toMap(ProjectEndpointDTO::getName, this::getSharedInfo));
 						return new ProjectInfrastructureInfo(e.getKey(),
-								billingDAO.getBillingProjectQuoteUsed(e.getKey()), projectEdges, e.getValue(), collect, endpointResult);
+								billingDAO.getBillingProjectQuoteUsed(e.getKey(), user), projectEdges, e.getValue(), collect, endpointResult);
 					})
 					.collect(Collectors.toList());
 		} catch (Exception e) {
@@ -141,8 +141,8 @@ public class InfrastructureInfoServiceImpl implements InfrastructureInfoService
 					.projectAdmin(UserRoles.isProjectAdmin(userInfo))
 					.admin(UserRoles.isAdmin(userInfo))
 					.projectAssigned(projectService.isAnyProjectAssigned(userInfo))
-					.billingQuoteUsed(billingDAO.getBillingQuoteUsed())
-					.billingUserQuoteUsed(billingDAO.getBillingUserQuoteUsed(user))
+					.billingQuoteUsed(billingDAO.getBillingQuoteUsed(userInfo))
+					.billingUserQuoteUsed(billingDAO.getBillingUserQuoteUsed(user, userInfo))
 					.build();
 		} catch (Exception e) {
 			log.warn("Could not return status of resources for user {}: {}", user, e.getLocalizedMessage(), e);
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ProjectServiceImpl.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ProjectServiceImpl.java
index 0d1f5ed..48d1388 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ProjectServiceImpl.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ProjectServiceImpl.java
@@ -100,7 +100,7 @@ public class ProjectServiceImpl implements ProjectService {
 
 	@BudgetLimited
 	@Override
-	public void create(UserInfo user, ProjectDTO projectDTO) {
+	public void create(@User UserInfo user, ProjectDTO projectDTO) {
 		if (!projectDAO.get(projectDTO.getName()).isPresent()) {
 			projectDAO.create(projectDTO);
 			createProjectOnCloud(user, projectDTO);
@@ -131,7 +131,7 @@ public class ProjectServiceImpl implements ProjectService {
 
 	@BudgetLimited
 	@Override
-	public void start(UserInfo userInfo, String endpoint, @Project String name) {
+	public void start(@User UserInfo userInfo, String endpoint, @Project String name) {
 		projectActionOnCloud(userInfo, name, START_PRJ_API, endpoint);
 		projectDAO.updateEdgeStatus(name, endpoint, UserInstanceStatus.STARTING);
 	}
diff --git a/services/self-service/src/test/java/com/epam/dlab/backendapi/schedulers/CheckApplicationQuoteSchedulerTest.java b/services/self-service/src/test/java/com/epam/dlab/backendapi/schedulers/CheckApplicationQuoteSchedulerTest.java
index 99fd932..b95202b 100644
--- a/services/self-service/src/test/java/com/epam/dlab/backendapi/schedulers/CheckApplicationQuoteSchedulerTest.java
+++ b/services/self-service/src/test/java/com/epam/dlab/backendapi/schedulers/CheckApplicationQuoteSchedulerTest.java
@@ -19,8 +19,10 @@
 
 package com.epam.dlab.backendapi.schedulers;
 
+import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.dao.BillingDAO;
 import com.epam.dlab.backendapi.service.EnvironmentService;
+import com.epam.dlab.backendapi.service.SecurityService;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.InjectMocks;
@@ -28,7 +30,12 @@ import org.mockito.Mock;
 import org.mockito.runners.MockitoJUnitRunner;
 import org.quartz.JobExecutionContext;
 
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
 
 @RunWith(MockitoJUnitRunner.class)
 public class CheckApplicationQuoteSchedulerTest {
@@ -39,28 +46,39 @@ public class CheckApplicationQuoteSchedulerTest {
 	private EnvironmentService environmentService;
 	@Mock
 	private JobExecutionContext jobExecutionContext;
+	@Mock
+	private SecurityService securityService;
 	@InjectMocks
 	private CheckApplicationQuoteScheduler checkApplicationQuoteScheduler;
 
 	@Test
 	public void testWhenQuoteNotReached() {
-		when(billingDAO.isBillingQuoteReached()).thenReturn(false);
+		when(billingDAO.isBillingQuoteReached(any(UserInfo.class))).thenReturn(false);
+		when(securityService.getServiceAccountInfo(anyString())).thenReturn(getUserInfo());
 
 		checkApplicationQuoteScheduler.execute(jobExecutionContext);
 
-		verify(billingDAO).isBillingQuoteReached();
+		verify(securityService).getServiceAccountInfo("admin");
+		verify(billingDAO).isBillingQuoteReached(getUserInfo());
 		verifyNoMoreInteractions(billingDAO);
 		verifyZeroInteractions(environmentService);
 	}
 
 	@Test
 	public void testWhenQuoteReached() {
-		when(billingDAO.isBillingQuoteReached()).thenReturn(true);
+		when(billingDAO.isBillingQuoteReached(any(UserInfo.class))).thenReturn(true);
+		when(securityService.getServiceAccountInfo(anyString())).thenReturn(getUserInfo());
 
 		checkApplicationQuoteScheduler.execute(jobExecutionContext);
 
-		verify(billingDAO).isBillingQuoteReached();
+		verify(securityService).getServiceAccountInfo("admin");
+		verify(billingDAO).isBillingQuoteReached(getUserInfo());
 		verify(environmentService).stopAll();
 		verifyNoMoreInteractions(billingDAO, environmentService);
 	}
+
+	private UserInfo getUserInfo() {
+		return new UserInfo("admin", null);
+	}
+
 }
\ No newline at end of file
diff --git a/services/self-service/src/test/java/com/epam/dlab/backendapi/schedulers/CheckUserQuoteSchedulerTest.java b/services/self-service/src/test/java/com/epam/dlab/backendapi/schedulers/CheckUserQuoteSchedulerTest.java
index 1c6937c..1cb7511 100644
--- a/services/self-service/src/test/java/com/epam/dlab/backendapi/schedulers/CheckUserQuoteSchedulerTest.java
+++ b/services/self-service/src/test/java/com/epam/dlab/backendapi/schedulers/CheckUserQuoteSchedulerTest.java
@@ -19,9 +19,11 @@
 
 package com.epam.dlab.backendapi.schedulers;
 
+import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.dao.BillingDAO;
 import com.epam.dlab.backendapi.resources.dto.UserDTO;
 import com.epam.dlab.backendapi.service.EnvironmentService;
+import com.epam.dlab.backendapi.service.SecurityService;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.InjectMocks;
@@ -32,7 +34,12 @@ import org.quartz.JobExecutionContext;
 import java.util.Collections;
 
 import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.when;
 
 @RunWith(MockitoJUnitRunner.class)
 public class CheckUserQuoteSchedulerTest {
@@ -44,18 +51,22 @@ public class CheckUserQuoteSchedulerTest {
 	private EnvironmentService environmentService;
 	@Mock
 	private JobExecutionContext jobExecutionContext;
+	@Mock
+	private SecurityService securityService;
 	@InjectMocks
 	private CheckUserQuoteScheduler checkUserQuoteScheduler;
 
 	@Test
 	public void testWhenUserQuoteReached() {
-		when(billingDAO.isUserQuoteReached(anyString())).thenReturn(true);
+		when(billingDAO.isUserQuoteReached(anyString(), any(UserInfo.class))).thenReturn(true);
 		when(environmentService.getUsers()).thenReturn(Collections.singletonList(new UserDTO(USER, 1, UserDTO.Status.ACTIVE)));
+		when(securityService.getServiceAccountInfo(anyString())).thenReturn(getUserInfo());
 
 		checkUserQuoteScheduler.execute(jobExecutionContext);
 
 		verify(environmentService).getUsers();
-		verify(billingDAO).isUserQuoteReached(USER);
+		verify(securityService).getServiceAccountInfo("admin");
+		verify(billingDAO).isUserQuoteReached(USER, getUserInfo());
 		verify(environmentService).stopEnvironmentWithServiceAccount(USER);
 		verifyNoMoreInteractions(environmentService, billingDAO);
 		verifyZeroInteractions(jobExecutionContext);
@@ -63,15 +74,21 @@ public class CheckUserQuoteSchedulerTest {
 
 	@Test
 	public void testWhenUserQuoteNotReached() {
-		when(billingDAO.isUserQuoteReached(anyString())).thenReturn(false);
+		when(billingDAO.isUserQuoteReached(anyString(), any(UserInfo.class))).thenReturn(false);
 		when(environmentService.getUsers()).thenReturn(Collections.singletonList(new UserDTO(USER, 1, UserDTO.Status.ACTIVE)));
+		when(securityService.getServiceAccountInfo(anyString())).thenReturn(getUserInfo());
 
 		checkUserQuoteScheduler.execute(jobExecutionContext);
 
 		verify(environmentService).getUsers();
-		verify(billingDAO).isUserQuoteReached(USER);
+		verify(securityService).getServiceAccountInfo("admin");
+		verify(billingDAO).isUserQuoteReached(USER, getUserInfo());
 		verify(environmentService, never()).stopEnvironmentWithServiceAccount(anyString());
 		verifyNoMoreInteractions(environmentService, billingDAO);
 		verifyZeroInteractions(jobExecutionContext);
 	}
+
+	private UserInfo getUserInfo() {
+		return new UserInfo("admin", null);
+	}
 }
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@dlab.apache.org
For additional commands, e-mail: commits-help@dlab.apache.org