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

bhliva pushed a commit to branch feature/projects
in repository https://gitbox.apache.org/repos/asf/incubator-dlab.git


The following commit(s) were added to refs/heads/feature/projects by this push:
     new 4a0c343  DLAB-640 added possibility to set limits for project
4a0c343 is described below

commit 4a0c343279cb49a440c458d8d911c648fede6db2
Author: bhliva <[email protected]>
AuthorDate: Fri May 24 16:47:15 2019 +0300

    DLAB-640 added possibility to set limits for project
---
 .../dlab/backendapi/SelfServiceApplication.java    |  2 +-
 .../epam/dlab/backendapi/annotation/Project.java   | 12 +++++
 .../epam/dlab/backendapi/dao/BaseBillingDAO.java   | 18 ++++++++
 .../java/com/epam/dlab/backendapi/dao/BaseDAO.java |  4 +-
 .../com/epam/dlab/backendapi/dao/BillingDAO.java   |  4 ++
 .../epam/dlab/backendapi/dao/ExploratoryDAO.java   | 30 +++++++++++++
 .../com/epam/dlab/backendapi/dao/ProjectDAO.java   |  7 +++
 .../epam/dlab/backendapi/dao/ProjectDAOImpl.java   | 16 +++++++
 .../dlab/backendapi/dao/gcp/GcpBillingDao.java     | 10 +++++
 .../epam/dlab/backendapi/domain/EndpointDTO.java   |  2 +
 .../epam/dlab/backendapi/domain/ProjectDTO.java    |  7 ++-
 .../backendapi/domain/UpdateProjectBudgetDTO.java  | 13 ++++++
 .../interceptor/BudgetLimitInterceptor.java        | 17 ++++++-
 .../backendapi/resources/EndpointResource.java     |  4 +-
 .../backendapi/resources/ExploratoryResource.java  |  4 +-
 .../dlab/backendapi/resources/ProjectResource.java | 35 +++++++++++++++
 .../schedulers/CheckProjectQuoteScheduler.java     | 52 ++++++++++++++++++++++
 .../backendapi/service/ComputationalService.java   |  6 +--
 .../backendapi/service/EnvironmentService.java     |  2 +
 .../backendapi/service/ExploratoryService.java     |  4 +-
 .../dlab/backendapi/service/ProjectService.java    |  6 +++
 .../service/impl/ComputationalServiceImpl.java     |  8 ++--
 .../service/impl/EnvironmentServiceImpl.java       | 29 ++++++++++++
 .../service/impl/ExploratoryServiceImpl.java       |  5 ++-
 .../service/impl/ProjectServiceImpl.java           | 17 ++++++-
 .../service/impl/SchedulerJobServiceImpl.java      |  4 +-
 .../resources/ExploratoryResourceTest.java         | 14 +++---
 .../service/impl/ComputationalServiceImplTest.java | 20 ++++-----
 .../service/impl/ExploratoryServiceImplTest.java   | 12 ++---
 .../service/impl/SchedulerJobServiceImplTest.java  | 12 ++---
 30 files changed, 325 insertions(+), 51 deletions(-)

diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/SelfServiceApplication.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/SelfServiceApplication.java
index 508b34f..8271fb2 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/SelfServiceApplication.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/SelfServiceApplication.java
@@ -192,7 +192,7 @@ public class SelfServiceApplication extends 
Application<SelfServiceApplicationCo
                oas.info(info);
                SwaggerConfiguration oasConfig = new SwaggerConfiguration()
                                .openAPI(oas)
-                               .readAllResources(false)
+                               //.readAllResources(false)
                                .prettyPrint(true)
                                
.resourceClasses(Stream.of(ProjectResource.class.getName(),
                                                
EndpointResource.class.getName())
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/annotation/Project.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/annotation/Project.java
new file mode 100644
index 0000000..5a1e5d4
--- /dev/null
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/annotation/Project.java
@@ -0,0 +1,12 @@
+package com.epam.dlab.backendapi.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+
+@Target(ElementType.PARAMETER)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Project {
+}
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 29319c7..23785b4 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
@@ -58,6 +58,7 @@ public abstract class BaseBillingDAO<T extends BillingFilter> 
extends BaseDAO im
        public static final String COST_TOTAL = "cost_total";
        public static final String FULL_REPORT = "full_report";
 
+       private static final String PROJECT = "project";
        private static final String MASTER_NODE_SHAPE = "master_node_shape";
        private static final String SLAVE_NODE_SHAPE = "slave_node_shape";
        private static final String TOTAL_INSTANCE_NUMBER = 
"total_instance_number";
@@ -75,6 +76,8 @@ public abstract class BaseBillingDAO<T extends BillingFilter> 
extends BaseDAO im
        protected SettingsDAO settings;
        @Inject
        private UserSettingsDAO userSettingsDAO;
+       @Inject
+       private ProjectDAO projectDAO;
 
        protected Map<String, ShapeInfo> getShapes(List<String> shapeNames) {
                FindIterable<Document> userInstances = getUserInstances();
@@ -109,6 +112,13 @@ public abstract class BaseBillingDAO<T extends 
BillingFilter> extends BaseDAO im
        }
 
        @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);
+       }
+
+       @Override
        public int getBillingQuoteUsed() {
                return toPercentage(() -> settings.getMaxBudget(), 
getTotalCost());
        }
@@ -131,6 +141,14 @@ public abstract class BaseBillingDAO<T extends 
BillingFilter> extends BaseDAO im
                                .isPresent();
        }
 
+       @Override
+       public boolean isProjectQuoteReached(String project) {
+               final Double projectCost = getProjectCost(project);
+               return projectDAO.getAllowedBudget(project)
+                               .filter(allowedBudget -> projectCost.intValue() 
!= 0 && allowedBudget <= projectCost)
+                               .isPresent();
+       }
+
        protected String getUserOrDefault(String user) {
                return StringUtils.isNotBlank(user) ? user : 
SHARED_RESOURCE_NAME;
        }
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/BaseDAO.java 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/BaseDAO.java
index 77f3284..034011a 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/BaseDAO.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/BaseDAO.java
@@ -371,7 +371,7 @@ public class BaseDAO {
         */
        protected <T> Optional<T> findOne(String collection, Bson condition, 
Class<T> clazz) {
                Optional<Document> doc = findOne(collection, condition);
-               return doc.isPresent() ? 
Optional.ofNullable(convertFromDocument(doc.get(), clazz)) : Optional.empty();
+               return doc.map(document -> convertFromDocument(document, 
clazz));
        }
 
        /**
@@ -384,7 +384,7 @@ public class BaseDAO {
         */
        protected <T> Optional<T> findOne(String collection, Bson condition, 
Bson projection, Class<T> clazz) {
                Optional<Document> doc = findOne(collection, condition, 
projection);
-               return doc.isPresent() ? 
Optional.ofNullable(convertFromDocument(doc.get(), clazz)) : Optional.empty();
+               return doc.map(document -> convertFromDocument(document, 
clazz));
        }
 
        /**
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 079c7ea..1498012 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
@@ -27,6 +27,8 @@ public interface BillingDAO<T extends BillingFilter> {
 
        Double getUserCost(String user);
 
+       Double getProjectCost(String project);
+
        int getBillingQuoteUsed();
 
        int getBillingUserQuoteUsed(String user);
@@ -35,5 +37,7 @@ public interface BillingDAO<T extends BillingFilter> {
 
        boolean isUserQuoteReached(String user);
 
+       boolean isProjectQuoteReached(String project);
+
        Document getReport(UserInfo userInfo, T filter);
 }
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ExploratoryDAO.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ExploratoryDAO.java
index ea3cef0..499ca20 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ExploratoryDAO.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ExploratoryDAO.java
@@ -67,6 +67,7 @@ public class ExploratoryDAO extends BaseDAO {
        private static final String EXPLORATORY_PRIVATE_IP = "private_ip";
        public static final String EXPLORATORY_NOT_FOUND_MSG = "Exploratory for 
user %s with name %s not found";
        private static final String EXPLORATORY_LAST_ACTIVITY = "last_activity";
+       private static final String PROJECT = "project";
 
        public ExploratoryDAO() {
                log.info("{} is initialized", getClass().getSimpleName());
@@ -129,6 +130,10 @@ public class ExploratoryDAO extends BaseDAO {
                return getUserInstances(and(eq(USER, user), eq(STATUS, 
UserInstanceStatus.RUNNING.toString())), false);
        }
 
+       public List<UserInstanceDTO> 
fetchRunningExploratoryFieldsForProject(String project) {
+               return getUserInstances(and(eq(PROJECT, project), eq(STATUS, 
UserInstanceStatus.RUNNING.toString())), false);
+       }
+
        /**
         * Finds and returns the info of all user's notebooks whose status is 
present among predefined ones.
         *
@@ -169,6 +174,20 @@ public class ExploratoryDAO extends BaseDAO {
                                false);
        }
 
+       public List<UserInstanceDTO> 
fetchProjectExploratoriesWhereStatusIn(String project,
+                                                                               
                                                                
List<UserInstanceStatus> exploratoryStatuses,
+                                                                               
                                                                
UserInstanceStatus... computationalStatuses) {
+               final List<String> exploratoryStatusList = 
statusList(exploratoryStatuses);
+               final List<String> computationalStatusList = 
statusList(computationalStatuses);
+               return getUserInstances(
+                               and(
+                                               eq(PROJECT, project),
+                                               or(in(STATUS, 
exploratoryStatusList),
+                                                               
in(COMPUTATIONAL_RESOURCES + "." + STATUS, computationalStatusList))
+                               ),
+                               false);
+       }
+
        /**
         * Finds and returns the info of all user's notebooks whose status is 
absent among predefined ones.
         *
@@ -185,6 +204,17 @@ public class ExploratoryDAO extends BaseDAO {
                                false);
        }
 
+       public List<UserInstanceDTO> 
fetchProjectExploratoriesWhereStatusNotIn(String project,
+                                                                               
                                                                   
UserInstanceStatus... statuses) {
+               final List<String> statusList = statusList(statuses);
+               return getUserInstances(
+                               and(
+                                               eq(USER, project),
+                                               not(in(STATUS, statusList))
+                               ),
+                               false);
+       }
+
        private List<UserInstanceDTO> getUserInstances(Bson condition, boolean 
computationalFieldsRequired) {
                return stream(getCollection(USER_INSTANCES)
                                .find(condition)
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ProjectDAO.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ProjectDAO.java
index a8e18ea..26f4920 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ProjectDAO.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ProjectDAO.java
@@ -2,9 +2,12 @@ package com.epam.dlab.backendapi.dao;
 
 import com.epam.dlab.backendapi.domain.ProjectDTO;
 
+import java.util.List;
 import java.util.Optional;
 
 public interface ProjectDAO {
+       List<ProjectDTO> getProjects();
+
        void create(ProjectDTO projectDTO);
 
        Optional<ProjectDTO> get(String name);
@@ -12,4 +15,8 @@ public interface ProjectDAO {
        boolean update(ProjectDTO projectDTO);
 
        void remove(String name);
+
+       Optional<Integer> getAllowedBudget(String project);
+
+       void updateBudget(String project, Integer budget);
 }
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ProjectDAOImpl.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ProjectDAOImpl.java
index 0f6c6e7..5c0b9e9 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ProjectDAOImpl.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/ProjectDAOImpl.java
@@ -4,6 +4,7 @@ import com.epam.dlab.backendapi.domain.ProjectDTO;
 import org.bson.Document;
 import org.bson.conversions.Bson;
 
+import java.util.List;
 import java.util.Optional;
 
 import static com.mongodb.client.model.Filters.eq;
@@ -13,6 +14,11 @@ public class ProjectDAOImpl extends BaseDAO implements 
ProjectDAO {
        private static final String PROJECTS_COLLECTION = "Projects";
 
        @Override
+       public List<ProjectDTO> getProjects() {
+               return find(PROJECTS_COLLECTION, ProjectDTO.class);
+       }
+
+       @Override
        public void create(ProjectDTO projectDTO) {
                insertOne(PROJECTS_COLLECTION, projectDTO);
        }
@@ -33,6 +39,16 @@ public class ProjectDAOImpl extends BaseDAO implements 
ProjectDAO {
 
        }
 
+       @Override
+       public Optional<Integer> getAllowedBudget(String project) {
+               return get(project).map(ProjectDTO::getBudget);
+       }
+
+       @Override
+       public void updateBudget(String project, Integer budget) {
+               updateOne(PROJECTS_COLLECTION, projectCondition(project), new 
Document(SET, new Document("budget", budget)));
+       }
+
        private Bson projectCondition(String name) {
                return eq("name", name);
        }
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 492d8b5..05112a2 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
@@ -36,6 +36,11 @@ public class GcpBillingDao implements 
BillingDAO<BillingFilter> {
        }
 
        @Override
+       public Double getProjectCost(String project) {
+               return null;
+       }
+
+       @Override
        public int getBillingQuoteUsed() {
                return 0;
        }
@@ -56,6 +61,11 @@ public class GcpBillingDao implements 
BillingDAO<BillingFilter> {
        }
 
        @Override
+       public boolean isProjectQuoteReached(String project) {
+               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/domain/EndpointDTO.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/EndpointDTO.java
index 4e14f08..e3c467c 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/EndpointDTO.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/EndpointDTO.java
@@ -1,8 +1,10 @@
 package com.epam.dlab.backendapi.domain;
 
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import lombok.Data;
 
 @Data
+@JsonIgnoreProperties(ignoreUnknown = true)
 public class EndpointDTO {
 
        private final String name;
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/ProjectDTO.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/ProjectDTO.java
index 2799a2e..2eb6a05 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/ProjectDTO.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/ProjectDTO.java
@@ -3,12 +3,17 @@ package com.epam.dlab.backendapi.domain;
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import lombok.Data;
 
+import javax.validation.constraints.NotNull;
 import java.util.Set;
 
 @Data
 @JsonIgnoreProperties(ignoreUnknown = true)
 public class ProjectDTO {
+       @NotNull
        private final String name;
-       private final Set<String> endpoints;
+       @NotNull
+       private final Set<String>endpoints;
+       @NotNull
        private final Set<String> groups;
+       private final Integer budget;
 }
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/UpdateProjectBudgetDTO.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/UpdateProjectBudgetDTO.java
new file mode 100644
index 0000000..72cbf05
--- /dev/null
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/UpdateProjectBudgetDTO.java
@@ -0,0 +1,13 @@
+package com.epam.dlab.backendapi.domain;
+
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+@Data
+public class UpdateProjectBudgetDTO {
+       @NotNull
+       private final String project;
+       @NotNull
+       private final Integer budget;
+}
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 ebe3a54..43fdaf6 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
@@ -20,6 +20,7 @@
 package com.epam.dlab.backendapi.interceptor;
 
 import com.epam.dlab.auth.UserInfo;
+import com.epam.dlab.backendapi.annotation.Project;
 import com.epam.dlab.backendapi.dao.BillingDAO;
 import com.epam.dlab.exceptions.ResourceQuoteReachedException;
 import com.google.inject.Inject;
@@ -28,7 +29,10 @@ import org.aopalliance.intercept.MethodInterceptor;
 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;
 
 @Slf4j
 public class BudgetLimitInterceptor implements MethodInterceptor {
@@ -37,7 +41,7 @@ public class BudgetLimitInterceptor implements 
MethodInterceptor {
 
        @Override
        public Object invoke(MethodInvocation mi) throws Throwable {
-               if (userQuoteReached(mi) || billingDAO.isBillingQuoteReached()) 
{
+               if (projectQuoteReached(mi) || 
billingDAO.isBillingQuoteReached()) {
                        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");
@@ -54,4 +58,15 @@ public class BudgetLimitInterceptor implements 
MethodInterceptor {
                                .map(billingDAO::isUserQuoteReached)
                                .orElse(Boolean.FALSE);
        }
+
+       private Boolean projectQuoteReached(MethodInvocation mi) {
+
+               final Parameter[] parameters = mi.getMethod().getParameters();
+               return 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);
+       }
 }
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/EndpointResource.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/EndpointResource.java
index af3426e..0a12c4e 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/EndpointResource.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/EndpointResource.java
@@ -70,11 +70,11 @@ public class EndpointResource {
        })
        @GET
        @Path("{name}")
+       @Produces(MediaType.APPLICATION_JSON)
        public Response getEndpoint(@Parameter(hidden = true) @Auth UserInfo 
userInfo,
                                                                
@Parameter(description = "Endpoint name")
                                                                
@PathParam("name") String name) {
-               endpointService.get(name);
-               return Response.ok().build();
+               return Response.ok(endpointService.get(name)).build();
        }
 
 
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/ExploratoryResource.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/ExploratoryResource.java
index 897255d..6e951c6 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/ExploratoryResource.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/ExploratoryResource.java
@@ -83,7 +83,7 @@ public class ExploratoryResource implements ExploratoryAPI {
                        log.warn("Unauthorized attempt to create a {} by user 
{}", formDTO.getImage(), userInfo.getName());
                        throw new DlabException("You do not have the privileges 
to create a " + formDTO.getTemplateName());
                }
-               String uuid = exploratoryService.create(userInfo, 
getExploratory(formDTO));
+               String uuid = exploratoryService.create(userInfo, 
getExploratory(formDTO), "");
                return Response.ok(uuid).build();
 
        }
@@ -104,7 +104,7 @@ public class ExploratoryResource implements ExploratoryAPI {
                                                @Valid @NotNull 
ExploratoryActionFormDTO formDTO) {
                log.debug("Starting exploratory environment {} for user {}", 
formDTO.getNotebookInstanceName(),
                                userInfo.getName());
-               return exploratoryService.start(userInfo, 
formDTO.getNotebookInstanceName());
+               return exploratoryService.start(userInfo, 
formDTO.getNotebookInstanceName(), "");
        }
 
        /**
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/ProjectResource.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/ProjectResource.java
index 4346601..85029dd 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/ProjectResource.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/ProjectResource.java
@@ -2,6 +2,7 @@ package com.epam.dlab.backendapi.resources;
 
 import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.domain.ProjectDTO;
+import com.epam.dlab.backendapi.domain.UpdateProjectBudgetDTO;
 import com.epam.dlab.backendapi.service.ProjectService;
 import com.epam.dlab.rest.dto.ErrorDTO;
 import com.google.inject.Inject;
@@ -80,6 +81,22 @@ public class ProjectResource {
                                .build();
        }
 
+       @Operation(summary = "Get available projects", tags = "project")
+       @ApiResponses({
+                       @ApiResponse(responseCode = "200", description = 
"Return information about projects",
+                                       content = @Content(mediaType = 
MediaType.APPLICATION_JSON, schema =
+                                       @Schema(implementation = 
ProjectDTO.class))),
+       })
+       @GET
+       @Produces(MediaType.APPLICATION_JSON)
+       public Response getProjects(@Parameter(hidden = true) @Auth UserInfo 
userInfo,
+                                                               
@Parameter(description = "Project name")
+                                                               
@PathParam("name") String name) {
+               return Response
+                               .ok(projectService.getProjects())
+                               .build();
+       }
+
        @Operation(summary = "Update project", tags = "project")
        @ApiResponses({
                        @ApiResponse(responseCode = "200", description = 
"Project is successfully updated"),
@@ -112,4 +129,22 @@ public class ProjectResource {
                projectService.remove(name);
                return Response.ok().build();
        }
+
+       @Operation(summary = "Updates project budget", tags = "project")
+       @ApiResponses({
+                       @ApiResponse(responseCode = "200", description = 
"Project budget is successfully updated"),
+                       @ApiResponse(responseCode = "404", description = 
"Project with specified name not found"),
+                       @ApiResponse(responseCode = "400", description = 
"Validation error",
+                                       content = @Content(mediaType = 
MediaType.APPLICATION_JSON,
+                                                       schema = 
@Schema(implementation = ErrorDTO.class)))
+       })
+       @PUT
+       @Path("/budget")
+       public Response updateBudget(
+                       @Parameter(hidden = true) @Auth UserInfo userInfo,
+                       @Parameter(description = "Project name")
+                                       UpdateProjectBudgetDTO dto) {
+               projectService.updateBudget(dto.getProject(), dto.getBudget());
+               return Response.ok().build();
+       }
 }
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
new file mode 100644
index 0000000..f253145
--- /dev/null
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/schedulers/CheckProjectQuoteScheduler.java
@@ -0,0 +1,52 @@
+/*
+ * 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.schedulers;
+
+import com.epam.dlab.backendapi.dao.BillingDAO;
+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.google.inject.Inject;
+import lombok.extern.slf4j.Slf4j;
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+
+@Scheduled("checkProjectQuoteScheduler")
+@Slf4j
+public class CheckProjectQuoteScheduler implements Job {
+
+       @Inject
+       private BillingDAO billingDAO;
+       @Inject
+       private EnvironmentService environmentService;
+       @Inject
+       private ProjectService projectService;
+
+       @Override
+       public void execute(JobExecutionContext context) {
+               projectService.getProjects()
+                               .stream()
+                               .map(ProjectDTO::getName)
+                               .filter(billingDAO::isProjectQuoteReached)
+                               .peek(p -> log.warn("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/service/ComputationalService.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/ComputationalService.java
index 1be1be5..217e18e 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/ComputationalService.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/ComputationalService.java
@@ -40,7 +40,7 @@ public interface ComputationalService {
         * name already exists
         * @throws IllegalArgumentException if input parameters exceed limits 
or docker image name is malformed
         */
-       boolean createSparkCluster(UserInfo userInfo, 
SparkStandaloneClusterCreateForm form);
+       boolean createSparkCluster(UserInfo userInfo, 
SparkStandaloneClusterCreateForm form, String project);
 
        /**
         * Asynchronously triggers termination of computational resources
@@ -53,11 +53,11 @@ public interface ComputationalService {
        void terminateComputational(UserInfo userInfo, String exploratoryName, 
String computationalName);
 
        boolean createDataEngineService(UserInfo userInfo, 
ComputationalCreateFormDTO formDTO, UserComputationalResource
-                       computationalResource);
+                       computationalResource, String project);
 
        void stopSparkCluster(UserInfo userInfo, String exploratoryName, String 
computationalName);
 
-       void startSparkCluster(UserInfo userInfo, String exploratoryName, 
String computationalName);
+       void startSparkCluster(UserInfo userInfo, String exploratoryName, 
String computationalName, String project);
 
        void updateSparkClusterConfig(UserInfo userInfo, String 
exploratoryName, String computationalName,
                                                                  
List<ClusterConfig> config);
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/EnvironmentService.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/EnvironmentService.java
index cb9371d..230e50e 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/EnvironmentService.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/EnvironmentService.java
@@ -36,6 +36,7 @@ public interface EnvironmentService {
        void stopAll();
 
        void stopEnvironment(String user);
+       void stopProjectEnvironment(String project);
 
        void stopEdge(String user);
 
@@ -46,6 +47,7 @@ public interface EnvironmentService {
        void terminateAll();
 
        void terminateEnvironment(String user);
+       void terminateProjectEnvironment(String project);
 
        void terminateExploratory(String user, String exploratoryName);
 
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/ExploratoryService.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/ExploratoryService.java
index be83ca7..e3729aa 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/ExploratoryService.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/ExploratoryService.java
@@ -31,13 +31,13 @@ import java.util.Optional;
 
 public interface ExploratoryService {
 
-       String start(UserInfo userInfo, String exploratoryName);
+       String start(UserInfo userInfo, String exploratoryName, String project);
 
        String stop(UserInfo userInfo, String exploratoryName);
 
        String terminate(UserInfo userInfo, String exploratoryName);
 
-       String create(UserInfo userInfo, Exploratory exploratory);
+       String create(UserInfo userInfo, Exploratory exploratory, String 
project);
 
        void updateExploratoryStatuses(String user, UserInstanceStatus status);
 
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/ProjectService.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/ProjectService.java
index 9619f87..2e221e1 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/ProjectService.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/ProjectService.java
@@ -2,7 +2,11 @@ package com.epam.dlab.backendapi.service;
 
 import com.epam.dlab.backendapi.domain.ProjectDTO;
 
+import java.util.List;
+
 public interface ProjectService {
+       List<ProjectDTO> getProjects();
+
        void create(ProjectDTO projectDTO);
 
        ProjectDTO get(String name);
@@ -10,4 +14,6 @@ public interface ProjectService {
        void remove(String name);
 
        void update(ProjectDTO projectDTO);
+
+       void updateBudget(String project, Integer budget);
 }
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 70f68f4..cc4ae0a 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
@@ -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.dao.ComputationalDAO;
 import com.epam.dlab.backendapi.dao.ExploratoryDAO;
 import com.epam.dlab.backendapi.domain.RequestId;
@@ -90,7 +91,8 @@ public class ComputationalServiceImpl implements 
ComputationalService {
 
        @BudgetLimited
        @Override
-       public boolean createSparkCluster(UserInfo userInfo, 
SparkStandaloneClusterCreateForm form) {
+       public boolean createSparkCluster(UserInfo userInfo, 
SparkStandaloneClusterCreateForm form,
+                                                                         
@Project String project) {
 
                if (computationalDAO.addComputational(userInfo.getName(), 
form.getNotebookName(),
                                createInitialComputationalResource(form))) {
@@ -153,7 +155,7 @@ public class ComputationalServiceImpl implements 
ComputationalService {
        @BudgetLimited
        @Override
        public boolean createDataEngineService(UserInfo userInfo, 
ComputationalCreateFormDTO formDTO,
-                                                                               
   UserComputationalResource computationalResource) {
+                                                                               
   UserComputationalResource computationalResource, @Project String project) {
 
                boolean isAdded = 
computationalDAO.addComputational(userInfo.getName(), formDTO.getNotebookName(),
                                computationalResource);
@@ -202,7 +204,7 @@ public class ComputationalServiceImpl implements 
ComputationalService {
 
        @BudgetLimited
        @Override
-       public void startSparkCluster(UserInfo userInfo, String expName, String 
compName) {
+       public void startSparkCluster(UserInfo userInfo, String expName, String 
compName, @Project String project) {
                final UserInstanceDTO userInstance =
                                
exploratoryDAO.fetchExploratoryFields(userInfo.getName(), expName, true);
                final UserInstanceStatus requiredStatus = 
UserInstanceStatus.STOPPED;
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/EnvironmentServiceImpl.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/EnvironmentServiceImpl.java
index ade44fb..217d139 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/EnvironmentServiceImpl.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/EnvironmentServiceImpl.java
@@ -119,6 +119,14 @@ public class EnvironmentServiceImpl implements 
EnvironmentService {
        }
 
        @Override
+       public void stopProjectEnvironment(String project) {
+               log.debug("Stopping environment for project {}", project);
+               checkProjectResourceConditions(project, "stop");
+               exploratoryDAO.fetchRunningExploratoryFieldsForProject(project)
+                               .forEach(this::stopNotebook);
+       }
+
+       @Override
        public void stopEdge(String user) {
                if 
(UserInstanceStatus.RUNNING.toString().equals(keyDAO.getEdgeStatus(user))) {
                        edgeService.stop(systemUserInfoService.create(user));
@@ -153,6 +161,15 @@ public class EnvironmentServiceImpl implements 
EnvironmentService {
        }
 
        @Override
+       public void terminateProjectEnvironment(String project) {
+               log.debug("Terminating environment for project {}", project);
+               checkProjectResourceConditions(project, "terminate");
+               
exploratoryDAO.fetchProjectExploratoriesWhereStatusNotIn(project, 
UserInstanceStatus.TERMINATED,
+                               UserInstanceStatus.FAILED, 
UserInstanceStatus.TERMINATING)
+                               .forEach(this::terminateNotebook);
+       }
+
+       @Override
        public void terminateExploratory(String user, String exploratoryName) {
                terminateNotebook(new 
UserInstanceDTO().withUser(user).withExploratoryName(exploratoryName));
        }
@@ -227,4 +244,16 @@ public class EnvironmentServiceImpl implements 
EnvironmentService {
                                .withCompResources(userInstance.getResources())
                                .withUser(userInstance.getUser());
        }
+
+       private void checkProjectResourceConditions(String project, String 
action) {
+               final List<UserInstanceDTO> userInstances = exploratoryDAO
+                               .fetchProjectExploratoriesWhereStatusIn(project,
+                                               
Arrays.asList(UserInstanceStatus.CREATING, UserInstanceStatus.STARTING,
+                                                               
UserInstanceStatus.CREATING_IMAGE),
+                                               UserInstanceStatus.CREATING, 
UserInstanceStatus.STARTING, UserInstanceStatus.CREATING_IMAGE);
+               if (!userInstances.isEmpty()) {
+                       log.error(String.format(ERROR_MSG_FORMAT, action));
+                       throw new 
ResourceConflictException(String.format(ERROR_MSG_FORMAT, action));
+               }
+       }
 }
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 58f4aa5..bdfa155 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
@@ -21,6 +21,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.dao.ComputationalDAO;
 import com.epam.dlab.backendapi.dao.ExploratoryDAO;
 import com.epam.dlab.backendapi.dao.GitCredsDAO;
@@ -75,7 +76,7 @@ public class ExploratoryServiceImpl implements 
ExploratoryService {
 
        @BudgetLimited
        @Override
-       public String start(UserInfo userInfo, String exploratoryName) {
+       public String start(UserInfo userInfo, String exploratoryName, @Project 
String project) {
                return action(userInfo, exploratoryName, EXPLORATORY_START, 
STARTING);
        }
 
@@ -91,7 +92,7 @@ public class ExploratoryServiceImpl implements 
ExploratoryService {
 
        @BudgetLimited
        @Override
-       public String create(UserInfo userInfo, Exploratory exploratory) {
+       public String create(UserInfo userInfo, Exploratory exploratory, 
@Project String project) {
                boolean isAdded = false;
                try {
                        
exploratoryDAO.insertExploratory(getUserInstanceDTO(userInfo, exploratory));
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 5230674..bceb5b9 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
@@ -2,20 +2,29 @@ package com.epam.dlab.backendapi.service.impl;
 
 import com.epam.dlab.backendapi.dao.ProjectDAO;
 import com.epam.dlab.backendapi.domain.ProjectDTO;
+import com.epam.dlab.backendapi.service.EnvironmentService;
 import com.epam.dlab.backendapi.service.ProjectService;
 import com.epam.dlab.exceptions.ResourceConflictException;
 import com.epam.dlab.exceptions.ResourceNotFoundException;
 import com.google.inject.Inject;
 
+import java.util.List;
 import java.util.function.Supplier;
 
 public class ProjectServiceImpl implements ProjectService {
 
        private final ProjectDAO projectDAO;
+       private final EnvironmentService environmentService;
 
        @Inject
-       public ProjectServiceImpl(ProjectDAO projectDAO) {
+       public ProjectServiceImpl(ProjectDAO projectDAO, EnvironmentService 
environmentService) {
                this.projectDAO = projectDAO;
+               this.environmentService = environmentService;
+       }
+
+       @Override
+       public List<ProjectDTO> getProjects() {
+               return projectDAO.getProjects();
        }
 
        @Override
@@ -35,6 +44,7 @@ public class ProjectServiceImpl implements ProjectService {
 
        @Override
        public void remove(String name) {
+               environmentService.terminateProjectEnvironment(name);
                projectDAO.remove(name);
        }
 
@@ -45,6 +55,11 @@ public class ProjectServiceImpl implements ProjectService {
                }
        }
 
+       @Override
+       public void updateBudget(String project, Integer budget) {
+               projectDAO.updateBudget(project, budget);
+       }
+
        private Supplier<ResourceNotFoundException> projectNotFound() {
                return () -> new ResourceNotFoundException("Project with passed 
name not found");
        }
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/SchedulerJobServiceImpl.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/SchedulerJobServiceImpl.java
index c906712..ebe9bcd 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/SchedulerJobServiceImpl.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/SchedulerJobServiceImpl.java
@@ -243,7 +243,7 @@ public class SchedulerJobServiceImpl implements 
SchedulerJobService {
                final String user = schedulerJobData.getUser();
                final String exploratoryName = 
schedulerJobData.getExploratoryName();
                log.debug("Starting exploratory {} for user {} by scheduler", 
exploratoryName, user);
-               exploratoryService.start(systemUserService.create(user), 
exploratoryName);
+               exploratoryService.start(systemUserService.create(user), 
exploratoryName, "");
                if (schedulerJobData.getJobDTO().isSyncStartRequired()) {
                        log.trace("Starting computational for exploratory {} 
for user {} by scheduler", exploratoryName, user);
                        final DataEngineType sparkCluster = 
DataEngineType.SPARK_STANDALONE;
@@ -266,7 +266,7 @@ public class SchedulerJobServiceImpl implements 
SchedulerJobService {
 
        private void startSpark(String user, String expName, String compName) {
                log.debug("Starting exploratory {} computational {} for user {} 
by scheduler", expName, compName, user);
-               
computationalService.startSparkCluster(systemUserService.create(user), expName, 
compName);
+               
computationalService.startSparkCluster(systemUserService.create(user), expName, 
compName,"");
        }
 
        private boolean shouldClusterBeStarted(DataEngineType sparkCluster, 
UserComputationalResource compResource) {
diff --git 
a/services/self-service/src/test/java/com/epam/dlab/backendapi/resources/ExploratoryResourceTest.java
 
b/services/self-service/src/test/java/com/epam/dlab/backendapi/resources/ExploratoryResourceTest.java
index 2fa4c45..0266a8b 100644
--- 
a/services/self-service/src/test/java/com/epam/dlab/backendapi/resources/ExploratoryResourceTest.java
+++ 
b/services/self-service/src/test/java/com/epam/dlab/backendapi/resources/ExploratoryResourceTest.java
@@ -63,7 +63,7 @@ public class ExploratoryResourceTest extends TestBase {
 
        @Test
        public void create() {
-               when(exploratoryService.create(any(UserInfo.class), 
any(Exploratory.class))).thenReturn("someUuid");
+               when(exploratoryService.create(any(UserInfo.class), 
any(Exploratory.class), anyString())).thenReturn("someUuid");
                final Response response = resources.getJerseyTest()
                                
.target("/infrastructure_provision/exploratory_environment")
                                .request()
@@ -74,14 +74,14 @@ public class ExploratoryResourceTest extends TestBase {
                assertEquals("someUuid", response.readEntity(String.class));
                assertEquals(MediaType.APPLICATION_JSON, 
response.getHeaderString(HttpHeaders.CONTENT_TYPE));
 
-               verify(exploratoryService).create(getUserInfo(), 
getExploratory(getExploratoryCreateFormDTO()));
+               verify(exploratoryService).create(getUserInfo(), 
getExploratory(getExploratoryCreateFormDTO()), "");
                verifyNoMoreInteractions(exploratoryService);
        }
 
        @Test
        public void createWithFailedAuth() throws AuthenticationException {
                authFailSetup();
-               when(exploratoryService.create(any(UserInfo.class), 
any(Exploratory.class))).thenReturn("someUuid");
+               when(exploratoryService.create(any(UserInfo.class), 
any(Exploratory.class), anyString())).thenReturn("someUuid");
                final Response response = resources.getJerseyTest()
                                
.target("/infrastructure_provision/exploratory_environment")
                                .request()
@@ -97,7 +97,7 @@ public class ExploratoryResourceTest extends TestBase {
        @Test
        public void createWithException() {
                doThrow(new DlabException("Could not create exploratory 
environment"))
-                               
.when(exploratoryService).create(any(UserInfo.class), any(Exploratory.class));
+                               
.when(exploratoryService).create(any(UserInfo.class), any(Exploratory.class), 
anyString());
                final Response response = resources.getJerseyTest()
                                
.target("/infrastructure_provision/exploratory_environment")
                                .request()
@@ -111,13 +111,13 @@ public class ExploratoryResourceTest extends TestBase {
                assertTrue(actualJson.contains(expectedJson));
                assertEquals(MediaType.APPLICATION_JSON, 
response.getHeaderString(HttpHeaders.CONTENT_TYPE));
 
-               verify(exploratoryService).create(getUserInfo(), 
getExploratory(getExploratoryCreateFormDTO()));
+               verify(exploratoryService).create(getUserInfo(), 
getExploratory(getExploratoryCreateFormDTO()), anyString());
                verifyNoMoreInteractions(exploratoryService);
        }
 
        @Test
        public void start() {
-               when(exploratoryService.start(any(UserInfo.class), 
anyString())).thenReturn("someUuid");
+               when(exploratoryService.start(any(UserInfo.class), anyString(), 
anyString())).thenReturn("someUuid");
                final Response response = resources.getJerseyTest()
                                
.target("/infrastructure_provision/exploratory_environment")
                                .request()
@@ -134,7 +134,7 @@ public class ExploratoryResourceTest extends TestBase {
        @Test
        public void startWithFailedAuth() throws AuthenticationException {
                authFailSetup();
-               when(exploratoryService.start(any(UserInfo.class), 
anyString())).thenReturn("someUuid");
+               when(exploratoryService.start(any(UserInfo.class), anyString(), 
anyString())).thenReturn("someUuid");
                final Response response = resources.getJerseyTest()
                                
.target("/infrastructure_provision/exploratory_environment")
                                .request()
diff --git 
a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/ComputationalServiceImplTest.java
 
b/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/ComputationalServiceImplTest.java
index 6111852..03e0c0b 100644
--- 
a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/ComputationalServiceImplTest.java
+++ 
b/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/ComputationalServiceImplTest.java
@@ -130,7 +130,7 @@ public class ComputationalServiceImplTest {
 
                SparkStandaloneClusterCreateForm sparkClusterCreateForm = 
(SparkStandaloneClusterCreateForm) formList.get(0);
                boolean creationResult =
-                               
computationalService.createSparkCluster(userInfo, sparkClusterCreateForm);
+                               
computationalService.createSparkCluster(userInfo, sparkClusterCreateForm, "");
                assertTrue(creationResult);
 
                verify(computationalDAO)
@@ -153,7 +153,7 @@ public class ComputationalServiceImplTest {
                                
any(SparkStandaloneClusterResource.class))).thenReturn(false);
 
                boolean creationResult =
-                               
computationalService.createSparkCluster(userInfo, 
(SparkStandaloneClusterCreateForm) formList.get(0));
+                               
computationalService.createSparkCluster(userInfo, 
(SparkStandaloneClusterCreateForm) formList.get(0), "");
                assertFalse(creationResult);
 
                verify(computationalDAO).addComputational(eq(USER), 
eq(EXPLORATORY_NAME), refEq(sparkClusterResource));
@@ -172,7 +172,7 @@ public class ComputationalServiceImplTest {
 
                SparkStandaloneClusterCreateForm sparkClusterCreateForm = 
(SparkStandaloneClusterCreateForm) formList.get(0);
                try {
-                       computationalService.createSparkCluster(userInfo, 
sparkClusterCreateForm);
+                       computationalService.createSparkCluster(userInfo, 
sparkClusterCreateForm,"");
                } catch (ResourceNotFoundException e) {
                        assertEquals("Exploratory for user with name not 
found", e.getMessage());
                }
@@ -198,7 +198,7 @@ public class ComputationalServiceImplTest {
 
                SparkStandaloneClusterCreateForm sparkClusterCreateForm = 
(SparkStandaloneClusterCreateForm) formList.get(0);
                try {
-                       computationalService.createSparkCluster(userInfo, 
sparkClusterCreateForm);
+                       computationalService.createSparkCluster(userInfo, 
sparkClusterCreateForm, "");
                } catch (DlabException e) {
                        assertEquals("Cannot create instance of resource class 
", e.getMessage());
                }
@@ -347,7 +347,7 @@ public class ComputationalServiceImplTest {
                when(requestId.put(anyString(), anyString())).thenReturn(UUID);
 
                boolean creationResult =
-                               
computationalService.createDataEngineService(userInfo, formList.get(1), 
ucResource);
+                               
computationalService.createDataEngineService(userInfo, formList.get(1), 
ucResource, "");
                assertTrue(creationResult);
 
                verify(computationalDAO).addComputational(eq(USER), 
eq(EXPLORATORY_NAME), refEq(ucResource));
@@ -369,7 +369,7 @@ public class ComputationalServiceImplTest {
                when(computationalDAO.addComputational(anyString(), 
anyString(), any(UserComputationalResource.class)))
                                .thenReturn(false);
 
-               boolean creationResult = 
computationalService.createDataEngineService(userInfo, formList.get(1), 
ucResource);
+               boolean creationResult = 
computationalService.createDataEngineService(userInfo, formList.get(1), 
ucResource, "");
                assertFalse(creationResult);
 
                verify(computationalDAO).addComputational(eq(USER), 
eq(EXPLORATORY_NAME), refEq(ucResource));
@@ -387,7 +387,7 @@ public class ComputationalServiceImplTest {
                                .thenReturn(mock(UpdateResult.class));
 
                try {
-                       computationalService.createDataEngineService(userInfo, 
formList.get(1), ucResource);
+                       computationalService.createDataEngineService(userInfo, 
formList.get(1), ucResource, "");
                } catch (DlabException e) {
                        assertEquals("Could not send request for creation the 
computational resource compName: " +
                                        "Exploratory for user with name not 
found", e.getMessage());
@@ -417,7 +417,7 @@ public class ComputationalServiceImplTest {
 
                ComputationalCreateFormDTO computationalCreateFormDTO = 
formList.get(1);
                try {
-                       computationalService.createDataEngineService(userInfo, 
computationalCreateFormDTO, ucResource);
+                       computationalService.createDataEngineService(userInfo, 
computationalCreateFormDTO, ucResource, "");
                } catch (DlabException e) {
                        assertEquals("Could not send request for creation the 
computational resource compName: " +
                                        "Cannot create instance of resource 
class ", e.getMessage());
@@ -485,7 +485,7 @@ public class ComputationalServiceImplTest {
                                .thenReturn("someUuid");
                when(requestId.put(anyString(), 
anyString())).thenReturn("someUuid");
 
-               computationalService.startSparkCluster(userInfo, 
EXPLORATORY_NAME, COMP_NAME);
+               computationalService.startSparkCluster(userInfo, 
EXPLORATORY_NAME, COMP_NAME, "");
 
                
verify(computationalDAO).updateComputationalStatus(refEq(computationalStatusDTOWithStatusStarting,
 "self"));
                verify(exploratoryDAO).fetchExploratoryFields(USER, 
EXPLORATORY_NAME, true);
@@ -507,7 +507,7 @@ public class ComputationalServiceImplTest {
                expectedException.expect(IllegalStateException.class);
                expectedException.expectMessage("There is no stopped dataengine 
compName for exploratory expName");
 
-               computationalService.startSparkCluster(userInfo, 
EXPLORATORY_NAME, COMP_NAME);
+               computationalService.startSparkCluster(userInfo, 
EXPLORATORY_NAME, COMP_NAME, "");
        }
 
        @Test
diff --git 
a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/ExploratoryServiceImplTest.java
 
b/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/ExploratoryServiceImplTest.java
index 2c28539..a3d9682 100644
--- 
a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/ExploratoryServiceImplTest.java
+++ 
b/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/ExploratoryServiceImplTest.java
@@ -109,7 +109,7 @@ public class ExploratoryServiceImplTest {
                                .thenReturn(UUID);
                when(requestId.put(anyString(), anyString())).thenReturn(UUID);
 
-               String uuid = exploratoryService.start(userInfo, 
EXPLORATORY_NAME);
+               String uuid = exploratoryService.start(userInfo, 
EXPLORATORY_NAME, "");
                assertNotNull(uuid);
                assertEquals(UUID, uuid);
 
@@ -128,7 +128,7 @@ public class ExploratoryServiceImplTest {
                doThrow(new ResourceNotFoundException("Exploratory for user 
with name not found"))
                                
.when(exploratoryDAO).fetchExploratoryFields(anyString(), anyString());
                try {
-                       exploratoryService.start(userInfo, EXPLORATORY_NAME);
+                       exploratoryService.start(userInfo, EXPLORATORY_NAME, 
"");
                } catch (DlabException e) {
                        assertEquals("Could not exploratory/start exploratory 
environment expName: Exploratory for user with " +
                                        "name not found", e.getMessage());
@@ -260,7 +260,7 @@ public class ExploratoryServiceImplTest {
                                .thenReturn(UUID);
                when(requestId.put(anyString(), anyString())).thenReturn(UUID);
 
-               String uuid = exploratoryService.create(userInfo, exploratory);
+               String uuid = exploratoryService.create(userInfo, exploratory, 
"");
                assertNotNull(uuid);
                assertEquals(UUID, uuid);
 
@@ -283,7 +283,7 @@ public class ExploratoryServiceImplTest {
                                "Exploratory for user with name not found");
 
                Exploratory exploratory = 
Exploratory.builder().name(EXPLORATORY_NAME).build();
-               exploratoryService.create(userInfo, exploratory);
+               exploratoryService.create(userInfo, exploratory, "");
        }
 
        @Test
@@ -291,7 +291,7 @@ public class ExploratoryServiceImplTest {
                doThrow(new 
RuntimeException()).when(exploratoryDAO).insertExploratory(any(UserInstanceDTO.class));
                Exploratory exploratory = 
Exploratory.builder().name(EXPLORATORY_NAME).build();
                try {
-                       exploratoryService.create(userInfo, exploratory);
+                       exploratoryService.create(userInfo, exploratory, "");
                } catch (DlabException e) {
                        assertEquals("Could not create exploratory environment 
expName for user test: null",
                                        e.getMessage());
@@ -316,7 +316,7 @@ public class ExploratoryServiceImplTest {
 
                
when(exploratoryDAO.updateExploratoryStatus(any(StatusEnvBaseDTO.class))).thenReturn(mock(UpdateResult.class));
                try {
-                       exploratoryService.create(userInfo, exploratory);
+                       exploratoryService.create(userInfo, exploratory, "");
                } catch (DlabException e) {
                        assertEquals("Could not create exploratory environment 
expName for user test: Cannot create instance " +
                                        "of resource class ", e.getMessage());
diff --git 
a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/SchedulerJobServiceImplTest.java
 
b/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/SchedulerJobServiceImplTest.java
index 4ca2ca0..55bfcbc 100644
--- 
a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/SchedulerJobServiceImplTest.java
+++ 
b/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/SchedulerJobServiceImplTest.java
@@ -399,7 +399,7 @@ public class SchedulerJobServiceImplTest {
                verify(schedulerJobDAO)
                                
.getComputationalSchedulerDataWithOneOfStatus(RUNNING, 
DataEngineType.SPARK_STANDALONE, STOPPED);
                
verify(computationalService).startSparkCluster(refEq(getUserInfo()), 
eq(EXPLORATORY_NAME),
-                               eq(COMPUTATIONAL_NAME));
+                               eq(COMPUTATIONAL_NAME), eq(""));
                verifyNoMoreInteractions(systemUserService, schedulerJobDAO, 
computationalService);
        }
 
@@ -691,7 +691,7 @@ public class SchedulerJobServiceImplTest {
 
                verify(systemUserService).create(USER);
                
verify(schedulerJobDAO).getExploratorySchedulerDataWithStatus(STOPPED);
-               verify(exploratoryService).start(refEq(getUserInfo()), 
eq(EXPLORATORY_NAME));
+               verify(exploratoryService).start(refEq(getUserInfo()), 
eq(EXPLORATORY_NAME),  eq(""));
                verifyNoMoreInteractions(systemUserService, schedulerJobDAO, 
exploratoryService);
                verifyZeroInteractions(computationalService, computationalDAO);
        }
@@ -715,10 +715,10 @@ public class SchedulerJobServiceImplTest {
 
                verify(systemUserService, times(2)).create(USER);
                
verify(schedulerJobDAO).getExploratorySchedulerDataWithStatus(STOPPED);
-               verify(exploratoryService).start(refEq(getUserInfo()), 
eq(EXPLORATORY_NAME));
+               verify(exploratoryService).start(refEq(getUserInfo()), 
eq(EXPLORATORY_NAME), eq(""));
                
verify(computationalDAO).findComputationalResourcesWithStatus(USER, 
EXPLORATORY_NAME, STOPPED);
                
verify(computationalService).startSparkCluster(refEq(getUserInfo()), 
eq(EXPLORATORY_NAME),
-                               eq(COMPUTATIONAL_NAME));
+                               eq(COMPUTATIONAL_NAME),  eq(""));
                verifyNoMoreInteractions(systemUserService, schedulerJobDAO, 
exploratoryService, computationalService,
                                computationalDAO);
        }
@@ -742,7 +742,7 @@ public class SchedulerJobServiceImplTest {
 
                verify(systemUserService).create(USER);
                
verify(schedulerJobDAO).getExploratorySchedulerDataWithStatus(STOPPED);
-               verify(exploratoryService).start(refEq(getUserInfo()), 
eq(EXPLORATORY_NAME));
+               verify(exploratoryService).start(refEq(getUserInfo()), 
eq(EXPLORATORY_NAME),  eq(""));
                
verify(computationalDAO).findComputationalResourcesWithStatus(USER, 
EXPLORATORY_NAME, STOPPED);
                verifyNoMoreInteractions(systemUserService, schedulerJobDAO, 
exploratoryService, computationalDAO);
                verifyZeroInteractions(computationalService);
@@ -767,7 +767,7 @@ public class SchedulerJobServiceImplTest {
 
                verify(systemUserService).create(USER);
                
verify(schedulerJobDAO).getExploratorySchedulerDataWithStatus(STOPPED);
-               verify(exploratoryService).start(refEq(getUserInfo()), 
eq(EXPLORATORY_NAME));
+               verify(exploratoryService).start(refEq(getUserInfo()), 
eq(EXPLORATORY_NAME),  eq(""));
                
verify(computationalDAO).findComputationalResourcesWithStatus(USER, 
EXPLORATORY_NAME, STOPPED);
                verifyNoMoreInteractions(systemUserService, schedulerJobDAO, 
exploratoryService, computationalDAO);
                verifyZeroInteractions(computationalService);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to