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/01/23 14:07:48 UTC

[incubator-dlab] branch develop updated: [DLAB-1432] Multiple cloud support (#548)

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

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


The following commit(s) were added to refs/heads/develop by this push:
     new 24dc7ca  [DLAB-1432] Multiple cloud support (#548)
24dc7ca is described below

commit 24dc7ca87380508b1a25ff9e89a7ce8937fce238
Author: ofuks <54...@users.noreply.github.com>
AuthorDate: Thu Jan 23 16:07:39 2020 +0200

    [DLAB-1432] Multiple cloud support (#548)
    
    * [DLAB-1432] Support a multiple cloud functionality
---
 .../backendapi/ProvisioningServiceApplication.java |   5 +-
 .../healthcheck/ProvisioningHealthCheck.java       |  30 --
 .../resources/ProvisioningHealthCheckResource.java |  15 +-
 services/self-service/self-service.yml             |   8 -
 .../dlab/backendapi/SelfServiceApplication.java    |   8 +-
 .../conf/SelfServiceApplicationConfiguration.java  |  33 +-
 .../epam/dlab/backendapi/dao/BaseBillingDAO.java   |  33 +-
 .../com/epam/dlab/backendapi/dao/BillingDAO.java   |   5 +-
 .../java/com/epam/dlab/backendapi/dao/EnvDAO.java  |   8 +-
 .../java/com/epam/dlab/backendapi/dao/KeyDAO.java  | 190 ----------
 .../com/epam/dlab/backendapi/dao/MongoSetting.java |   2 +-
 .../com/epam/dlab/backendapi/dao/SettingsDAO.java  |   8 +-
 .../com/epam/dlab/backendapi/dao/UserRoleDao.java  |   7 +-
 .../epam/dlab/backendapi/dao/UserRoleDaoImpl.java  |  59 ++-
 .../dlab/backendapi/dao/aws/AwsBillingDAO.java     |  25 +-
 .../epam/dlab/backendapi/dao/aws/AwsKeyDao.java    |  45 ---
 .../dlab/backendapi/dao/azure/AzureBillingDAO.java |  15 +-
 .../dlab/backendapi/dao/azure/AzureKeyDao.java     |  47 ---
 .../dlab/backendapi/dao/gcp/GcpBillingDao.java     |  21 +-
 .../epam/dlab/backendapi/dao/gcp/GcpKeyDao.java    |  47 ---
 .../epam/dlab/backendapi/domain/EndpointDTO.java   |   7 +-
 .../dlab/backendapi/domain/EnvStatusListener.java  | 164 ---------
 .../backendapi/domain/ExploratoryLibCache.java     |  17 +-
 .../dropwizard/listeners/MongoStartupListener.java |  28 +-
 .../listeners/RestoreHandlerStartupListener.java   |  10 +-
 .../backendapi/modules/AwsSelfServiceModule.java   |  18 +-
 .../backendapi/modules/AzureSelfServiceModule.java |  24 +-
 ...ServiceModule.java => CloudProviderModule.java} |  71 ++--
 .../epam/dlab/backendapi/modules/DevModule.java    |   2 -
 .../backendapi/modules/GcpSelfServiceModule.java   |  16 -
 .../dlab/backendapi/modules/ModuleFactory.java     |   7 +-
 .../dlab/backendapi/modules/ProductionModule.java  |   2 -
 ...illingResourceGcp.java => BillingResource.java} |  34 +-
 .../dlab/backendapi/resources/EdgeResource.java    |  74 ----
 .../backendapi/resources/EndpointResource.java     |   2 +-
 .../backendapi/resources/EnvironmentResource.java  |  21 --
 .../backendapi/resources/KeyUploaderResource.java  | 131 -------
 .../backendapi/resources/SecurityResource.java     | 147 --------
 .../resources/aws/BillingResourceAws.java          |  80 ----
 .../resources/aws/ComputationalResourceAws.java    |   2 +-
 .../resources/azure/BillingResourceAzure.java      |  80 ----
 .../azure/ComputationalResourceAzure.java          |   2 +-
 .../resources/callback/ComputationalCallback.java  |   5 -
 .../resources/callback/ExploratoryCallback.java    |   9 +-
 .../resources/callback/aws/EdgeCallbackAws.java    |  65 ----
 .../callback/aws/KeyUploaderCallbackAws.java       |  66 ----
 .../callback/azure/EdgeCallbackAzure.java          |  63 ----
 .../callback/azure/KeyUploaderCallbackAzure.java   |  70 ----
 .../resources/callback/base/EdgeCallback.java      |  78 ----
 .../callback/base/KeyUploaderCallback.java         |  58 ---
 .../resources/callback/gcp/EdgeCallbackGcp.java    |  63 ----
 .../callback/gcp/KeyUploaderCallbackGcp.java       |  68 ----
 .../backendapi/resources/dto/BillingFilter.java    |  11 +-
 .../resources/dto/ProjectInfrastructureInfo.java   |   4 +
 .../resources/dto/aws/AwsBillingFilter.java        |  43 ---
 .../resources/dto/azure/AzureBillingFilter.java    |  41 ---
 .../resources/dto/gcp/GcpBillingFilter.java        |  42 ---
 .../resources/gcp/ComputationalResourceGcp.java    |   2 +-
 .../endpoint/CheckEndpointStatusScheduler.java     |   2 +-
 .../dlab/backendapi/service/AccessKeyService.java  |   9 -
 .../dlab/backendapi/service/BillingService.java    |  10 +-
 .../epam/dlab/backendapi/service/EdgeService.java  |  35 --
 .../dlab/backendapi/service/EndpointService.java   |   3 +-
 .../backendapi/service/EnvironmentService.java     |   4 -
 .../backendapi/service/ReuploadKeyService.java     |   4 -
 .../backendapi/service/UserResourceService.java    |  33 --
 .../backendapi/service/aws/AwsBillingService.java  |   6 +-
 .../service/aws/AwsInfrastructureInfoService.java  |  40 --
 .../aws/AwsInfrastructureTemplateService.java      |  56 ---
 .../service/azure/AzureBillingService.java         |   6 +-
 .../azure/AzureInfrastructureInfoService.java      |  45 ---
 .../azure/AzureInfrastructureTemplateService.java  |  37 --
 .../backendapi/service/gcp/GcpBillingService.java  |   6 +-
 .../service/gcp/GcpInfrastructureInfoService.java  |  40 --
 .../gcp/GcpInfrastructureTemplateService.java      |  55 ---
 .../service/impl/AccessKeyServiceImpl.java         | 119 ------
 .../service/impl/ComputationalServiceImpl.java     |  40 +-
 .../backendapi/service/impl/EdgeServiceImpl.java   | 153 --------
 .../service/impl/EndpointServiceImpl.java          |  41 ++-
 .../service/impl/EnvironmentServiceImpl.java       |  36 +-
 .../service/impl/ExploratoryServiceImpl.java       |  29 +-
 .../service/impl/GitCredentialServiceImpl.java     |   7 +-
 .../service/impl/ImageExploratoryServiceImpl.java  |   7 +-
 .../service/impl/InactivityServiceImpl.java        |  21 +-
 ...ase.java => InfrastructureInfoServiceImpl.java} |  59 ++-
 ...java => InfrastructureTemplateServiceImpl.java} |  80 +++-
 .../service/impl/LibraryServiceImpl.java           |  22 +-
 .../service/impl/ProjectServiceImpl.java           |  25 +-
 .../service/impl/ReuploadKeyServiceImpl.java       |  58 +--
 .../service/impl/UserResourceServiceImpl.java      |  95 -----
 .../epam/dlab/backendapi/util/RequestBuilder.java  | 258 ++++++-------
 ...fServiceCloudConfigurationSequenceProvider.java |  28 --
 .../project-form/project-form.component.html       |   2 +-
 .../project/project-form/project-form.component.ts |   3 +-
 .../services/applicationServiceFacade.service.ts   |  34 +-
 .../services/dataengineConfiguration.service.ts    |   8 +-
 .../src/app/core/services/userResource.service.ts  |  18 +-
 .../webapp/src/app/login/login.component.html      |   8 +-
 .../webapp/src/app/login/login.component.ts        |   5 -
 .../reporting-grid/reporting-grid.component.html   |  32 +-
 .../src/app/reporting/reporting.component.ts       |  24 +-
 .../cluster-details/cluster-details.component.html |  26 +-
 .../cluster-details/cluster-details.component.ts   |  10 +-
 ...utational-resource-create-dialog.component.html |  13 +-
 ...mputational-resource-create-dialog.component.ts |  22 +-
 .../computational-resource-create.model.ts         |  13 +-
 .../computational-resources-list.component.ts      |  18 +-
 .../ami-create-dialog.component.html               |  10 +-
 .../ami-create-dialog.component.ts                 |   7 +-
 .../cost-details-dialog.component.html             |  22 +-
 .../cost-details-dialog.component.ts               |   2 +
 .../create-environment.component.html              |  10 +-
 .../create-environment.component.ts                |   2 +-
 .../detail-dialog/detail-dialog.component.html     |  14 +-
 .../detail-dialog/detail-dialog.component.ts       |   1 +
 .../resources-grid/resources-grid.component.html   |  10 +-
 .../resources-grid/resources-grid.component.ts     |   9 +-
 .../resources-grid/resources-grid.model.ts         |  27 +-
 .../src/app/shared/navbar/navbar.component.ts      |   1 -
 .../webapp/src/dictionary/aws.dictionary.ts        |  41 +--
 .../webapp/src/dictionary/azure.dictionary.ts      |  42 +--
 .../webapp/src/dictionary/gcp.dictionary.ts        |  43 +--
 .../webapp/src/dictionary/global.dictionary.ts     |  43 ++-
 .../backendapi/resources/EdgeResourceTest.java     | 164 ---------
 .../resources/EnvironmentResourceTest.java         |  98 -----
 .../resources/KeyUploaderResourceTest.java         | 405 ---------------------
 .../service/aws/AwsBillingServiceTest.java         |  29 +-
 .../aws/AwsInfrastructureInfoServiceTest.java      |  47 ---
 .../aws/AwsInfrastructureTemplateServiceTest.java  |  84 -----
 .../service/azure/AzureBillingServiceTest.java     |  28 +-
 .../azure/AzureInfrastructureInfoServiceTest.java  |  57 ---
 .../AzureInfrastructureTemplateServiceTest.java    |  38 --
 .../gcp/GcpInfrastructureInfoServiceTest.java      |  47 ---
 .../gcp/GcpInfrastructureTemplateServiceTest.java  |  81 -----
 .../service/impl/AccessKeyServiceImplTest.java     | 311 ----------------
 .../service/impl/ComputationalServiceImplTest.java |  49 +--
 .../service/impl/EdgeServiceImplTest.java          | 241 ------------
 .../service/impl/EnvironmentServiceImplTest.java   | 126 +------
 .../service/impl/ExploratoryServiceImplTest.java   |  30 +-
 .../service/impl/GitCredentialServiceImplTest.java |  12 +-
 .../impl/ImageExploratoryServiceImplTest.java      |  13 +-
 .../InfrastructureTemplateServiceBaseTest.java     |  22 +-
 .../service/impl/LibraryServiceImplTest.java       |  29 +-
 .../service/impl/ReuploadKeyServiceImplTest.java   | 276 +-------------
 .../service/impl/UserResourceServiceImplTest.java  | 109 ------
 145 files changed, 963 insertions(+), 5560 deletions(-)

diff --git a/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/ProvisioningServiceApplication.java b/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/ProvisioningServiceApplication.java
index 5cc0d2d..6f1047b 100644
--- a/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/ProvisioningServiceApplication.java
+++ b/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/ProvisioningServiceApplication.java
@@ -24,7 +24,6 @@ import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.core.DirectoriesCreator;
 import com.epam.dlab.backendapi.core.DockerWarmuper;
 import com.epam.dlab.backendapi.core.response.handlers.ComputationalConfigure;
-import com.epam.dlab.backendapi.healthcheck.ProvisioningHealthCheck;
 import com.epam.dlab.backendapi.modules.CloudModuleConfigurator;
 import com.epam.dlab.backendapi.modules.ModuleFactory;
 import com.epam.dlab.backendapi.resources.*;
@@ -129,7 +128,6 @@ public class ProvisioningServiceApplication extends Application<ProvisioningServ
 			environment.lifecycle().manage(injector.getInstance(RestoreCallbackHandlerServiceImpl.class));
 		}
 		environment.lifecycle().manage(injector.getInstance(DockerWarmuper.class));
-		environment.healthChecks().register("ProvisioningHealthCheck", new ProvisioningHealthCheck());
 
 
 		JerseyEnvironment jersey = environment.jersey();
@@ -146,7 +144,6 @@ public class ProvisioningServiceApplication extends Application<ProvisioningServ
 		jersey.register(injector.getInstance(KeyResource.class));
 		jersey.register(injector.getInstance(CallbackHandlerResource.class));
 		jersey.register(injector.getInstance(ProjectResource.class));
-		jersey.register(new ProvisioningHealthCheckResource(environment.healthChecks()));
-
+		jersey.register(injector.getInstance(ProvisioningHealthCheckResource.class));
 	}
 }
diff --git a/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/healthcheck/ProvisioningHealthCheck.java b/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/healthcheck/ProvisioningHealthCheck.java
deleted file mode 100644
index 75fcb47..0000000
--- a/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/healthcheck/ProvisioningHealthCheck.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.healthcheck;
-
-import com.codahale.metrics.health.HealthCheck;
-
-public class ProvisioningHealthCheck extends HealthCheck {
-
-    @Override
-    protected Result check() {
-        return Result.healthy();
-    }
-}
\ No newline at end of file
diff --git a/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/resources/ProvisioningHealthCheckResource.java b/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/resources/ProvisioningHealthCheckResource.java
index cf93523..e50d7ae 100644
--- a/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/resources/ProvisioningHealthCheckResource.java
+++ b/services/provisioning-service/src/main/java/com/epam/dlab/backendapi/resources/ProvisioningHealthCheckResource.java
@@ -19,8 +19,10 @@
 
 package com.epam.dlab.backendapi.resources;
 
-import com.codahale.metrics.health.HealthCheckRegistry;
+
 import com.epam.dlab.auth.UserInfo;
+import com.epam.dlab.backendapi.ProvisioningServiceApplicationConfiguration;
+import com.google.inject.Inject;
 import io.dropwizard.auth.Auth;
 
 import javax.ws.rs.GET;
@@ -32,16 +34,13 @@ import javax.ws.rs.core.Response;
 @Path("/healthcheck")
 @Produces(MediaType.APPLICATION_JSON)
 public class ProvisioningHealthCheckResource {
-    private static final String HEALTH_CHECK= "ProvisioningHealthCheck";
-
-    private HealthCheckRegistry registry;
+    private static final String HEALTH_CHECK = "ProvisioningHealthCheck";
 
-    public ProvisioningHealthCheckResource(HealthCheckRegistry registry) {
-        this.registry = registry;
-    }
+    @Inject
+    private ProvisioningServiceApplicationConfiguration configuration;
 
     @GET
     public Response status(@Auth UserInfo ui) {
-        return Response.ok(registry.runHealthCheck(HEALTH_CHECK)).build();
+        return Response.ok(configuration.getCloudProvider()).build();
     }
 }
\ No newline at end of file
diff --git a/services/self-service/self-service.yml b/services/self-service/self-service.yml
index 389e855..53bd131 100644
--- a/services/self-service/self-service.yml
+++ b/services/self-service/self-service.yml
@@ -21,16 +21,13 @@
 
 <#include "ssn.yml">
 
-<#if CLOUD_TYPE == "aws">
 # Minimum and maximum number of slave EMR instances than could be created
 minEmrInstanceCount: 2
 maxEmrInstanceCount: 14
 # Minimum and maximum percentage cost for slave EMR spot instances biding
 minEmrSpotInstanceBidPct: 20
 maxEmrSpotInstanceBidPct: 90
-</#if>
 
-<#if CLOUD_TYPE == "gcp">
 # Maximum length for gcp user name (due to gcp restrictions)
 maxUserNameLength: 10
 # Minimum and maximum number of slave Dataproc instances that could be created
@@ -38,7 +35,6 @@ minInstanceCount: 3
 maxInstanceCount: 15
 minDataprocPreemptibleCount: 0
 gcpOuauth2AuthenticationEnabled: false
-</#if>
 
 # Boundaries for Spark cluster creation
 minSparkInstanceCount: 2
@@ -61,11 +57,7 @@ billingConfFile: ${sys['user.dir']}/../billing/billing.yml
 billingConfFile: ${DLAB_CONF_DIR}/billing.yml
 </#if>
 
-<#if CLOUD_TYPE == "azure">
-azureUseLdap: <LOGIN_USE_LDAP>
 ssnInstanceSize: <SSN_INSTANCE_SIZE>
-maxSessionDurabilityMilliseconds: 288000000
-</#if>
 
 serviceBaseName: SERVICE_BASE_NAME
 os: OPERATION_SYSTEM
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 da6a5c5..6a12ea5 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
@@ -21,7 +21,6 @@ package com.epam.dlab.backendapi;
 
 import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
 import com.epam.dlab.backendapi.dao.IndexCreator;
-import com.epam.dlab.backendapi.domain.EnvStatusListener;
 import com.epam.dlab.backendapi.domain.ExploratoryLibCache;
 import com.epam.dlab.backendapi.dropwizard.bundles.DlabKeycloakBundle;
 import com.epam.dlab.backendapi.dropwizard.listeners.MongoStartupListener;
@@ -31,6 +30,7 @@ import com.epam.dlab.backendapi.modules.ModuleFactory;
 import com.epam.dlab.backendapi.resources.*;
 import com.epam.dlab.backendapi.resources.callback.*;
 import com.epam.dlab.backendapi.schedulers.internal.ManagedScheduler;
+import com.epam.dlab.backendapi.service.EndpointService;
 import com.epam.dlab.backendapi.servlet.guacamole.GuacamoleServlet;
 import com.epam.dlab.cloud.CloudModule;
 import com.epam.dlab.constants.ServiceConsts;
@@ -106,11 +106,10 @@ public class SelfServiceApplication extends Application<SelfServiceApplicationCo
 		environment.lifecycle().addServerLifecycleListener(injector.getInstance(MongoStartupListener.class));
 		final RestoreHandlerStartupListener restoreHandlerStartupListener =
 				new RestoreHandlerStartupListener(injector.getInstance(Key.get(RESTService.class,
-						Names.named(ServiceConsts.PROVISIONING_SERVICE_NAME))));
+						Names.named(ServiceConsts.PROVISIONING_SERVICE_NAME))), injector.getInstance(EndpointService.class));
 		environment.lifecycle().addServerLifecycleListener(restoreHandlerStartupListener);
 		environment.lifecycle().addServerLifecycleListener(this::disableGzipHandlerForGuacamoleServlet);
 		environment.lifecycle().manage(injector.getInstance(IndexCreator.class));
-		environment.lifecycle().manage(injector.getInstance(EnvStatusListener.class));
 		environment.lifecycle().manage(injector.getInstance(ExploratoryLibCache.class));
 		environment.lifecycle().manage(injector.getInstance(ManagedScheduler.class));
 		environment.healthChecks().register(ServiceConsts.MONGO_NAME, injector.getInstance(MongoHealthCheck.class));
@@ -128,9 +127,6 @@ public class SelfServiceApplication extends Application<SelfServiceApplicationCo
 		jersey.register(new DlabValidationExceptionMapper());
 		jersey.register(new ValidationExceptionMapper());
 		jersey.register(new ResourceQuoteReachedExceptionMapper());
-		jersey.register(injector.getInstance(SecurityResource.class));
-		jersey.register(injector.getInstance(KeyUploaderResource.class));
-		jersey.register(injector.getInstance(EdgeResource.class));
 
 		jersey.register(injector.getInstance(InfrastructureTemplateResource.class));
 		jersey.register(injector.getInstance(InfrastructureInfoResource.class));
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/conf/SelfServiceApplicationConfiguration.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/conf/SelfServiceApplicationConfiguration.java
index 48410d1..aaface6 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/conf/SelfServiceApplicationConfiguration.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/conf/SelfServiceApplicationConfiguration.java
@@ -21,17 +21,12 @@ package com.epam.dlab.backendapi.conf;
 
 import com.epam.dlab.ServiceConfiguration;
 import com.epam.dlab.backendapi.domain.SchedulerConfigurationData;
-import com.epam.dlab.backendapi.validation.SelfServiceCloudConfigurationSequenceProvider;
 import com.epam.dlab.constants.ServiceConsts;
 import com.epam.dlab.rest.client.RESTServiceFactory;
-import com.epam.dlab.validation.AwsValidation;
-import com.epam.dlab.validation.AzureValidation;
-import com.epam.dlab.validation.GcpValidation;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import io.dropwizard.client.JerseyClientConfiguration;
 import io.dropwizard.util.Duration;
 import org.hibernate.validator.constraints.NotEmpty;
-import org.hibernate.validator.group.GroupSequenceProvider;
 
 import javax.validation.Valid;
 import javax.validation.constraints.Max;
@@ -42,37 +37,33 @@ import java.util.Map;
 /**
  * Configuration for Self Service.
  */
-@GroupSequenceProvider(SelfServiceCloudConfigurationSequenceProvider.class)
 public class SelfServiceApplicationConfiguration extends ServiceConfiguration {
 
-	@Min(value = 2, groups = AwsValidation.class)
+	@Min(value = 2)
 	@JsonProperty
 	private int minEmrInstanceCount;
 
-	@Max(value = 1000, groups = AwsValidation.class)
+	@Max(value = 1000)
 	@JsonProperty
 	private int maxEmrInstanceCount;
 
-	@Min(value = 10, groups = AwsValidation.class)
+	@Min(value = 10)
 	@JsonProperty
 	private int minEmrSpotInstanceBidPct;
 
-	@Max(value = 95, groups = AwsValidation.class)
+	@Max(value = 95)
 	@JsonProperty
 	private int maxEmrSpotInstanceBidPct;
 
-	@Min(value = 2, groups = {AzureValidation.class, AwsValidation.class, GcpValidation.class})
+	@Min(value = 2)
 	@JsonProperty
 	private int minSparkInstanceCount;
 
-	@Max(value = 1000, groups = {AzureValidation.class, AwsValidation.class, GcpValidation.class})
+	@Max(value = 1000)
 	@JsonProperty
 	private int maxSparkInstanceCount;
 
 	@JsonProperty
-	private boolean azureUseLdap;
-
-	@JsonProperty
 	private String ssnInstanceSize;
 
 	@JsonProperty
@@ -87,7 +78,7 @@ public class SelfServiceApplicationConfiguration extends ServiceConfiguration {
 	@JsonProperty
 	private boolean billingSchedulerEnabled = false;
 
-	@NotEmpty(groups = AwsValidation.class)
+	@NotEmpty
 	@JsonProperty
 	private String billingConfFile;
 	@JsonProperty
@@ -101,8 +92,6 @@ public class SelfServiceApplicationConfiguration extends ServiceConfiguration {
 	@JsonProperty
 	private boolean gcpOuauth2AuthenticationEnabled;
 	@JsonProperty
-	private long maxSessionDurabilityMilliseconds;
-	@JsonProperty
 	private boolean mongoMigrationEnabled;
 	@JsonProperty
 	private int privateKeySize = 2048;
@@ -146,10 +135,6 @@ public class SelfServiceApplicationConfiguration extends ServiceConfiguration {
 		return jerseyClient;
 	}
 
-	public long getMaxSessionDurabilityMilliseconds() {
-		return maxSessionDurabilityMilliseconds;
-	}
-
 	public Map<String, SchedulerConfigurationData> getSchedulers() {
 		return schedulers;
 	}
@@ -245,10 +230,6 @@ public class SelfServiceApplicationConfiguration extends ServiceConfiguration {
 		return privateKeySize;
 	}
 
-	public boolean isAzureUseLdap() {
-		return azureUseLdap;
-	}
-
 	public String getSsnInstanceSize() {
 		return ssnInstanceSize;
 	}
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 4fc374a..9edfaa8 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
@@ -47,7 +47,12 @@ import org.bson.Document;
 import org.bson.conversions.Bson;
 
 import java.math.BigDecimal;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
 import java.util.function.Supplier;
 import java.util.stream.StreamSupport;
 
@@ -61,12 +66,18 @@ import static com.epam.dlab.model.aws.ReportLine.FIELD_USAGE_DATE;
 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.*;
-import static com.mongodb.client.model.Projections.*;
+import static com.mongodb.client.model.Filters.eq;
+import static com.mongodb.client.model.Filters.gte;
+import static com.mongodb.client.model.Filters.in;
+import static com.mongodb.client.model.Filters.lte;
+import static com.mongodb.client.model.Filters.regex;
+import static com.mongodb.client.model.Projections.excludeId;
+import static com.mongodb.client.model.Projections.fields;
+import static com.mongodb.client.model.Projections.include;
 import static java.util.Collections.singletonList;
 
 @Slf4j
-public abstract class BaseBillingDAO<T extends BillingFilter> extends BaseDAO implements BillingDAO<T> {
+public abstract class BaseBillingDAO extends BaseDAO implements BillingDAO {
 
 	public static final String SHAPE = "shape";
 	public static final String SERVICE_BASE_NAME = "service_base_name";
@@ -100,7 +111,7 @@ public abstract class BaseBillingDAO<T extends BillingFilter> extends BaseDAO im
 	private ProjectDAO projectDAO;
 
 	@Override
-	public Document getReport(UserInfo userInfo, T filter) {
+	public Document getReport(UserInfo userInfo, BillingFilter filter) {
 		boolean isFullReport = UserRoles.checkAccess(userInfo, RoleType.PAGE, "/api/infrastructure_provision/billing",
 				userInfo.getRoles());
 		setUserFilter(userInfo, filter, isFullReport);
@@ -111,8 +122,8 @@ public abstract class BaseBillingDAO<T extends BillingFilter> extends BaseDAO im
 		}
 		pipeline.add(groupCriteria());
 		pipeline.add(sortCriteria());
-		final Map<String, BaseShape> shapes = getShapes(filter.getShapes());
-		return prepareReport(filter.getStatuses(), !filter.getShapes().isEmpty(),
+		final Map<String, BaseShape> shapes = getShapes(filter.getShape());
+		return prepareReport(filter.getStatuses(), !filter.getShape().isEmpty(),
 				getCollection(BILLING).aggregate(pipeline), shapes, isFullReport);
 	}
 
@@ -347,11 +358,11 @@ public abstract class BaseBillingDAO<T extends BillingFilter> extends BaseDAO im
 			searchCriteria.add(in(PROJECT, filter.getProjects()));
 		}
 
-		searchCriteria.addAll(cloudMatchCriteria((T) filter));
+		searchCriteria.addAll(cloudMatchCriteria(filter));
 		return searchCriteria;
 	}
 
-	protected abstract List<Bson> cloudMatchCriteria(T filter);
+	protected abstract List<Bson> cloudMatchCriteria(BillingFilter filter);
 
 	private Double aggregateBillingData(List<Bson> pipeline) {
 		return Optional.ofNullable(aggregate(BILLING, pipeline).first())
@@ -451,7 +462,9 @@ public abstract class BaseBillingDAO<T extends BillingFilter> extends BaseDAO im
 		return settings.getServiceBaseName();
 	}
 
-	protected abstract String getSsnShape();
+	protected String getSsnShape() {
+		return settings.getSsnInstanceSize();
+	}
 
 	protected void usersToLowerCase(List<String> users) {
 		if (users != null) {
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 cd03bff..1ea06b8 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
@@ -22,7 +22,7 @@ import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.resources.dto.BillingFilter;
 import org.bson.Document;
 
-public interface BillingDAO<T extends BillingFilter> {
+public interface BillingDAO {
 	Double getTotalCost();
 
 	Double getUserCost(String user);
@@ -32,6 +32,7 @@ public interface BillingDAO<T extends BillingFilter> {
 	int getBillingQuoteUsed();
 
 	int getBillingUserQuoteUsed(String user);
+
 	int getBillingProjectQuoteUsed(String project);
 
 	boolean isBillingQuoteReached();
@@ -40,5 +41,5 @@ public interface BillingDAO<T extends BillingFilter> {
 
 	boolean isProjectQuoteReached(String project);
 
-	Document getReport(UserInfo userInfo, T filter);
+	Document getReport(UserInfo userInfo, BillingFilter filter);
 }
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/EnvDAO.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/EnvDAO.java
index bbe0a2f..0e85908 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/EnvDAO.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/EnvDAO.java
@@ -22,11 +22,9 @@ package com.epam.dlab.backendapi.dao;
 import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.SelfServiceApplication;
 import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
-import com.epam.dlab.backendapi.domain.EnvStatusListener;
 import com.epam.dlab.backendapi.resources.aws.ComputationalResourceAws;
 import com.epam.dlab.backendapi.resources.dto.HealthStatusEnum;
 import com.epam.dlab.backendapi.resources.dto.HealthStatusPageDTO;
-import com.epam.dlab.cloud.CloudProvider;
 import com.epam.dlab.dto.UserInstanceDTO;
 import com.epam.dlab.dto.UserInstanceStatus;
 import com.epam.dlab.dto.base.DataEngineType;
@@ -421,7 +419,7 @@ public class EnvDAO extends BaseDAO {
 			LOGGER.debug("Computational status for user {} with exploratory {} and computational {} will be updated " +
 							"from {} to {}",
 					user, exploratoryName, computationalName, oldStatus, status);
-			if (configuration.getCloudProvider() == CloudProvider.AWS && status == UserInstanceStatus.TERMINATED &&
+			if (status == UserInstanceStatus.TERMINATED &&
 					terminateComputationalSpot(user, exploratoryName, computationalName)) {
 				return;
 			}
@@ -459,9 +457,7 @@ public class EnvDAO extends BaseDAO {
 			return false;
 		}
 
-		EnvStatusListener envStatusListener =
-				SelfServiceApplication.getInjector().getInstance(EnvStatusListener.class);
-		UserInfo userInfo = (envStatusListener != null) ? envStatusListener.getSession(user) : null;
+		UserInfo userInfo = null;
 		if (userInfo == null) {
 			// User logged off. Computational will be terminated when user logged in.
 			return true;
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/KeyDAO.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/KeyDAO.java
deleted file mode 100644
index 8bce841..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/KeyDAO.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * 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.dao;
-
-
-import com.epam.dlab.dto.UserInstanceStatus;
-import com.epam.dlab.dto.base.edge.EdgeInfo;
-import com.epam.dlab.dto.keyload.KeyLoadStatus;
-import com.epam.dlab.dto.keyload.UserKeyDTO;
-import com.epam.dlab.exceptions.DlabException;
-import com.mongodb.client.model.Updates;
-import org.bson.Document;
-
-import java.util.Date;
-import java.util.Optional;
-
-import static com.epam.dlab.backendapi.dao.MongoCollections.USER_EDGE;
-import static com.epam.dlab.backendapi.dao.MongoCollections.USER_KEYS;
-import static com.mongodb.client.model.Filters.*;
-import static com.mongodb.client.model.Projections.*;
-import static com.mongodb.client.model.Updates.set;
-
-/**
- * DAO for manage the user key.
- */
-public abstract class KeyDAO extends BaseDAO {
-	private static final String EDGE_STATUS = "edge_status";
-	private static final String KEY_CONTENT = "content";
-
-	/**
-	 * Write the status of user key to Mongo database.
-	 *
-	 * @param user   user name
-	 * @param status the status of user key.
-	 */
-	public void updateKey(String user, String status) {
-		updateOne(USER_KEYS, eq(ID, user), set(STATUS, status));
-	}
-
-	/**
-	 * Delete the user key from Mongo database.
-	 *
-	 * @param user user name
-	 */
-	public void deleteKey(String user) {
-		mongoService.getCollection(USER_KEYS).deleteOne(eq(ID, user));
-	}
-
-	/**
-	 * Inserts ('insertRequired' equals 'true') or updates ('insertRequired' equals 'false') the user key to/in Mongo
-	 * database.
-	 *
-	 * @param user           user name
-	 * @param content        key content
-	 * @param insertRequired true/false
-	 */
-	public void upsertKey(final String user, String content, boolean insertRequired) {
-		Document doc = new Document(SET,
-				new Document()
-						.append(ID, user)
-						.append(KEY_CONTENT, content)
-						.append(STATUS, insertRequired ? KeyLoadStatus.NEW.getStatus() :
-								KeyLoadStatus.SUCCESS.getStatus())
-						.append(TIMESTAMP, new Date()));
-		updateOne(USER_KEYS, eq(ID, user), doc, insertRequired);
-	}
-
-	/**
-	 * Finds and returns the user key with the specified status
-	 *
-	 * @param user   user name.
-	 * @param status key status
-	 */
-	public UserKeyDTO fetchKey(String user, KeyLoadStatus status) {
-		return findOne(USER_KEYS,
-				and(eq(ID, user), eq(STATUS, status.getStatus())),
-				UserKeyDTO.class)
-				.orElseThrow(() -> new DlabException(String.format("Key of user %s with status %s not found", user,
-						status.getStatus())));
-	}
-
-	/**
-	 * Store the EDGE of user to Mongo database.
-	 *
-	 * @param user     user name
-	 * @param edgeInfo the EDGE of user
-	 */
-	public void updateEdgeInfo(String user, EdgeInfo edgeInfo) {
-		Document d = new Document(SET,
-				convertToBson(edgeInfo)
-						.append(ID, user));
-		updateOne(USER_EDGE,
-				eq(ID, user),
-				d,
-				true);
-	}
-
-	public abstract EdgeInfo getEdgeInfo(String user);
-
-	public <T extends EdgeInfo> T getEdgeInfo(String user, Class<T> target, T defaultValue) {
-		return findOne(USER_EDGE,
-				eq(ID, user), target)
-				.orElse(defaultValue);
-	}
-
-	public abstract Optional<? extends EdgeInfo> getEdgeInfoWhereStatusIn(String user, UserInstanceStatus... statuses);
-
-	protected <T extends EdgeInfo> Optional<T> getEdgeInfoWhereStatusIn(String user, Class<T> target,
-																		UserInstanceStatus... statuses) {
-		return findOne(USER_EDGE,
-				and(eq(ID, user), in(EDGE_STATUS, statusList(statuses))),
-				target);
-	}
-
-	/**
-	 * Finds and returns the status of user key.
-	 *
-	 * @param user user name
-	 */
-	public KeyLoadStatus findKeyStatus(String user) {
-		return findOne(USER_KEYS, eq(ID, user), UserKeyDTO.class)
-				.map(UserKeyDTO::getStatus)
-				.map(KeyLoadStatus::findByStatus)
-				.orElse(KeyLoadStatus.NONE);
-	}
-
-	/**
-	 * Updates the status of EDGE node.
-	 *
-	 * @param user   user name
-	 * @param status status of EDGE node
-	 */
-	public void updateEdgeStatus(String user, String status) {
-		updateOne(USER_EDGE,
-				eq(ID, user),
-				Updates.set(EDGE_STATUS, status));
-	}
-
-	/**
-	 * Return the status of EDGE node.
-	 *
-	 * @param user user name
-	 */
-	public String getEdgeStatus(String user) {
-		Document d = findOne(USER_EDGE,
-				eq(ID, user),
-				fields(include(EDGE_STATUS), excludeId())).orElse(null);
-		return (d == null ? "" : d.getString(EDGE_STATUS));
-	}
-
-	public void removeEdge(String user) {
-		deleteOne(USER_EDGE, eq(ID, user));
-	}
-
-	public boolean edgeNodeExist(String user) {
-		return findOne(USER_EDGE, and(eq(ID, user), not(in(EDGE_STATUS, UserInstanceStatus.TERMINATING.toString(),
-				UserInstanceStatus.TERMINATED.toString()))))
-				.isPresent();
-	}
-
-	/**
-	 * Updates the field 'reupload_key_required' of EDGE node.
-	 *
-	 * @param user                user name
-	 * @param reuploadKeyRequired true/false
-	 * @param edgeStatuses        allowable edge statuses
-	 */
-	public void updateEdgeReuploadKey(String user, boolean reuploadKeyRequired, UserInstanceStatus... edgeStatuses) {
-		updateOne(USER_EDGE,
-				and(eq(ID, user), in(EDGE_STATUS, statusList(edgeStatuses))),
-				Updates.set(REUPLOAD_KEY_REQUIRED, reuploadKeyRequired));
-	}
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/MongoSetting.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/MongoSetting.java
index 4656b6b..bfa4e84 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/MongoSetting.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/MongoSetting.java
@@ -84,7 +84,7 @@ public enum MongoSetting {
 	AZURE_VPC_NAME("azure_vpc_name"),
 	AZURE_SECURITY_GROUP_NAME("azure_security_group_name"),
 	AZURE_EDGE_INSTANCE_SIZE("edge_instance_size"),
-	AZURE_SSN_INSTANCE_SIZE("ssn_instance_size"),
+	SSN_INSTANCE_SIZE("ssn_instance_size"),
 	AZURE_DATA_LAKE_NAME_TAG("datalake_tag_name"),
 	AZURE_DATA_LAKE_CLIENT_ID("azure_client_id"),
 
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/SettingsDAO.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/SettingsDAO.java
index ff58d4a..d5770e1 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/SettingsDAO.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/SettingsDAO.java
@@ -241,8 +241,8 @@ public class SettingsDAO extends BaseDAO {
 		return getSetting(AZURE_EDGE_INSTANCE_SIZE);
 	}
 
-	public String getAzureSsnInstanceSize() {
-		return getSetting(AZURE_SSN_INSTANCE_SIZE);
+	public String getSsnInstanceSize() {
+		return getSetting(SSN_INSTANCE_SIZE);
 	}
 
 	public String getAzureDataLakeNameTag() {
@@ -282,8 +282,8 @@ public class SettingsDAO extends BaseDAO {
 		setSetting(AZURE_EDGE_INSTANCE_SIZE, azureEdgeInstanceSize);
 	}
 
-	public void setAzureSsnInstanceSize(String ssnInstanceSize) {
-		setSetting(AZURE_SSN_INSTANCE_SIZE, ssnInstanceSize);
+	public void setSsnInstanceSize(String ssnInstanceSize) {
+		setSetting(SSN_INSTANCE_SIZE, ssnInstanceSize);
 	}
 
 	public void setAzureDataLakeNameTag(String dataLakeNameTag) {
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/UserRoleDao.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/UserRoleDao.java
index 33d00d9..c2a401b 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/UserRoleDao.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/UserRoleDao.java
@@ -21,6 +21,7 @@ package com.epam.dlab.backendapi.dao;
 
 import com.epam.dlab.backendapi.resources.dto.UserGroupDto;
 import com.epam.dlab.backendapi.resources.dto.UserRoleDto;
+import com.epam.dlab.cloud.CloudProvider;
 
 import java.util.List;
 import java.util.Set;
@@ -28,20 +29,22 @@ import java.util.Set;
 public interface UserRoleDao {
 	List<UserRoleDto> findAll();
 
-	void removeAll();
-
 	void insert(UserRoleDto dto);
 
 	void insert(List<UserRoleDto> roles);
 
 	boolean update(UserRoleDto dto);
 
+	void updateMissingRoles(CloudProvider cloudProvider);
+
 	boolean addGroupToRole(Set<String> groups, Set<String> roleIds);
 
 	boolean removeGroupFromRole(Set<String> groups, Set<String> roleIds);
 
 	void removeGroupWhenRoleNotIn(String group, Set<String> roleIds);
 
+	void removeUnnecessaryRoles(CloudProvider cloudProviderToBeRemoved, List<CloudProvider> remainingProviders);
+
 	void remove(String roleId);
 
 	boolean removeGroup(String groupId);
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/UserRoleDaoImpl.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/UserRoleDaoImpl.java
index f271723..0767be4 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/UserRoleDaoImpl.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/UserRoleDaoImpl.java
@@ -20,25 +20,38 @@ package com.epam.dlab.backendapi.dao;
 
 import com.epam.dlab.backendapi.resources.dto.UserGroupDto;
 import com.epam.dlab.backendapi.resources.dto.UserRoleDto;
+import com.epam.dlab.cloud.CloudProvider;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.inject.Singleton;
 import com.mongodb.client.model.BsonField;
 import com.mongodb.client.result.UpdateResult;
 import org.bson.Document;
 import org.bson.conversions.Bson;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
 import java.util.Set;
 
 import static com.epam.dlab.backendapi.dao.MongoCollections.USER_GROUPS;
-import static com.mongodb.client.model.Aggregates.*;
-import static com.mongodb.client.model.Filters.*;
+import static com.mongodb.client.model.Aggregates.group;
+import static com.mongodb.client.model.Aggregates.lookup;
+import static com.mongodb.client.model.Aggregates.project;
+import static com.mongodb.client.model.Aggregates.unwind;
+import static com.mongodb.client.model.Filters.eq;
+import static com.mongodb.client.model.Filters.in;
+import static com.mongodb.client.model.Filters.not;
+import static java.lang.String.format;
 import static java.util.stream.Collectors.toList;
 
 @Singleton
 public class UserRoleDaoImpl extends BaseDAO implements UserRoleDao {
-
+	private static final ObjectMapper MAPPER = new ObjectMapper();
+	private static final String ROLES_FILE_FORMAT = "/mongo/%s/mongo_roles.json";
 	private static final String USERS_FIELD = "users";
 	private static final String GROUPS_FIELD = "groups";
 	private static final String DESCRIPTION = "description";
@@ -58,11 +71,6 @@ public class UserRoleDaoImpl extends BaseDAO implements UserRoleDao {
 	}
 
 	@Override
-	public void removeAll() {
-		mongoService.getCollection(MongoCollections.ROLES).drop();
-	}
-
-	@Override
 	public void insert(UserRoleDto dto) {
 		insertOne(MongoCollections.ROLES, dto, dto.getId());
 	}
@@ -81,6 +89,15 @@ public class UserRoleDaoImpl extends BaseDAO implements UserRoleDao {
 	}
 
 	@Override
+	public void updateMissingRoles(CloudProvider cloudProvider) {
+		getUserRoleFromFile(cloudProvider).stream()
+				.filter(u -> findAll().stream()
+						.map(UserRoleDto::getId)
+						.noneMatch(id -> id.equals(u.getId())))
+				.forEach(this::insert);
+	}
+
+	@Override
 	public boolean addGroupToRole(Set<String> groups, Set<String> roleIds) {
 		return conditionMatched(updateMany(MongoCollections.ROLES, in(ID, roleIds), addToSet(GROUPS_FIELD,
 				groups)));
@@ -97,6 +114,23 @@ public class UserRoleDaoImpl extends BaseDAO implements UserRoleDao {
 	}
 
 	@Override
+	public void removeUnnecessaryRoles(CloudProvider cloudProviderToBeRemoved, List<CloudProvider> remainingProviders) {
+		if (remainingProviders.contains(cloudProviderToBeRemoved)) {
+			return;
+		}
+
+		List<UserRoleDto> remainingRoles = new ArrayList<>();
+		remainingProviders.forEach(p -> remainingRoles.addAll(getUserRoleFromFile(p)));
+
+		getUserRoleFromFile(cloudProviderToBeRemoved).stream()
+				.map(UserRoleDto::getId)
+				.filter(u -> remainingRoles.stream()
+						.map(UserRoleDto::getId)
+						.noneMatch(id -> id.equals(u)))
+				.forEach(this::remove);
+	}
+
+	@Override
 	public void remove(String roleId) {
 		deleteOne(MongoCollections.ROLES, eq(ID, roleId));
 	}
@@ -123,6 +157,15 @@ public class UserRoleDaoImpl extends BaseDAO implements UserRoleDao {
 				.collect(toList());
 	}
 
+	private List<UserRoleDto> getUserRoleFromFile(CloudProvider cloudProvider) {
+		try (InputStream is = getClass().getResourceAsStream(format(ROLES_FILE_FORMAT, cloudProvider.getName()))) {
+			return MAPPER.readValue(is, new TypeReference<List<UserRoleDto>>() {
+			});
+		} catch (IOException e) {
+			throw new IllegalStateException("Can not marshall dlab roles due to: " + e.getMessage());
+		}
+	}
+
 	private Document roleDocument() {
 		return new Document().append(ID, "$" + ID)
 				.append(DESCRIPTION, "$" + DESCRIPTION)
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/aws/AwsBillingDAO.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/aws/AwsBillingDAO.java
index 5205cc4..fde1d8f 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/aws/AwsBillingDAO.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/aws/AwsBillingDAO.java
@@ -21,22 +21,29 @@ package com.epam.dlab.backendapi.dao.aws;
 
 import com.epam.dlab.MongoKeyWords;
 import com.epam.dlab.backendapi.dao.BaseBillingDAO;
-import com.epam.dlab.backendapi.resources.dto.aws.AwsBillingFilter;
+import com.epam.dlab.backendapi.resources.dto.BillingFilter;
 import org.bson.Document;
 import org.bson.conversions.Bson;
 
 import java.util.Collections;
 import java.util.List;
 
-import static com.epam.dlab.model.aws.ReportLine.*;
-import static com.mongodb.client.model.Accumulators.*;
+import static com.epam.dlab.model.aws.ReportLine.FIELD_COST;
+import static com.epam.dlab.model.aws.ReportLine.FIELD_CURRENCY_CODE;
+import static com.epam.dlab.model.aws.ReportLine.FIELD_DLAB_ID;
+import static com.epam.dlab.model.aws.ReportLine.FIELD_PRODUCT;
+import static com.epam.dlab.model.aws.ReportLine.FIELD_RESOURCE_TYPE;
+import static com.epam.dlab.model.aws.ReportLine.FIELD_USAGE_DATE;
+import static com.mongodb.client.model.Accumulators.max;
+import static com.mongodb.client.model.Accumulators.min;
+import static com.mongodb.client.model.Accumulators.sum;
 import static com.mongodb.client.model.Aggregates.group;
 import static com.mongodb.client.model.Aggregates.sort;
 
 /**
  * DAO for user billing.
  */
-public class AwsBillingDAO extends BaseBillingDAO<AwsBillingFilter> {
+public class AwsBillingDAO extends BaseBillingDAO {
 
     public static final String DLAB_RESOURCE_TYPE = "dlab_resource_type";
     public static final String USAGE_DATE_START = "from";
@@ -61,15 +68,7 @@ public class AwsBillingDAO extends BaseBillingDAO<AwsBillingFilter> {
     }
 
     @Override
-    protected List<Bson> cloudMatchCriteria(AwsBillingFilter filter) {
+    protected List<Bson> cloudMatchCriteria(BillingFilter filter) {
         return Collections.emptyList();
     }
-
-
-    @Override
-    protected String getSsnShape() {
-        return "t2.medium";
-    }
-
-
 }
\ No newline at end of file
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/aws/AwsKeyDao.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/aws/AwsKeyDao.java
deleted file mode 100644
index 745a2cd..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/aws/AwsKeyDao.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.dao.aws;
-
-import com.epam.dlab.backendapi.dao.KeyDAO;
-import com.epam.dlab.dto.UserInstanceStatus;
-import com.epam.dlab.dto.aws.edge.EdgeInfoAws;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.Optional;
-
-@Slf4j
-public class AwsKeyDao extends KeyDAO {
-
-	public AwsKeyDao() {
-		log.info("{} is initialized", getClass().getSimpleName());
-	}
-
-	@Override
-	public EdgeInfoAws getEdgeInfo(String user) {
-		return super.getEdgeInfo(user, EdgeInfoAws.class, new EdgeInfoAws());
-	}
-
-	@Override
-	public Optional<EdgeInfoAws> getEdgeInfoWhereStatusIn(String user, UserInstanceStatus... statuses) {
-		return super.getEdgeInfoWhereStatusIn(user, EdgeInfoAws.class, statuses);
-	}
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/azure/AzureBillingDAO.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/azure/AzureBillingDAO.java
index 863f3eb..04c5e6d 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/azure/AzureBillingDAO.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/azure/AzureBillingDAO.java
@@ -21,7 +21,7 @@ package com.epam.dlab.backendapi.dao.azure;
 
 import com.epam.dlab.MongoKeyWords;
 import com.epam.dlab.backendapi.dao.BaseBillingDAO;
-import com.epam.dlab.backendapi.resources.dto.azure.AzureBillingFilter;
+import com.epam.dlab.backendapi.resources.dto.BillingFilter;
 import com.epam.dlab.billing.DlabResourceType;
 import com.google.inject.Singleton;
 import com.mongodb.client.model.Accumulators;
@@ -37,13 +37,13 @@ import java.util.List;
 
 @Singleton
 @Slf4j
-public class AzureBillingDAO extends BaseBillingDAO<AzureBillingFilter> {
+public class AzureBillingDAO extends BaseBillingDAO {
 	public static final String SIZE = "size";
 
 	@Override
-	protected List<Bson> cloudMatchCriteria(AzureBillingFilter filter) {
-		if (!filter.getCategory().isEmpty()) {
-			return Collections.singletonList(Filters.in(MongoKeyWords.METER_CATEGORY, filter.getCategory()));
+	protected List<Bson> cloudMatchCriteria(BillingFilter filter) {
+		if (!filter.getService().isEmpty()) {
+			return Collections.singletonList(Filters.in(MongoKeyWords.METER_CATEGORY, filter.getService()));
 		} else {
 			return Collections.emptyList();
 		}
@@ -79,11 +79,6 @@ public class AzureBillingDAO extends BaseBillingDAO<AzureBillingFilter> {
 	}
 
 	@Override
-	protected String getSsnShape() {
-		return settings.getAzureSsnInstanceSize();
-	}
-
-	@Override
 	protected String shapeFieldName() {
 		return SIZE;
 	}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/azure/AzureKeyDao.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/azure/AzureKeyDao.java
deleted file mode 100644
index 4a7ec1b..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/azure/AzureKeyDao.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.dao.azure;
-
-import com.epam.dlab.backendapi.dao.KeyDAO;
-import com.epam.dlab.dto.UserInstanceStatus;
-import com.epam.dlab.dto.azure.edge.EdgeInfoAzure;
-import com.google.inject.Singleton;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.Optional;
-
-@Slf4j
-@Singleton
-public class AzureKeyDao extends KeyDAO {
-
-	public AzureKeyDao() {
-		log.info("{} is initialized", getClass().getSimpleName());
-	}
-
-	@Override
-	public EdgeInfoAzure getEdgeInfo(String user) {
-		return super.getEdgeInfo(user, EdgeInfoAzure.class, new EdgeInfoAzure());
-	}
-
-	@Override
-	public Optional<EdgeInfoAzure> getEdgeInfoWhereStatusIn(String user, UserInstanceStatus... statuses) {
-		return super.getEdgeInfoWhereStatusIn(user, EdgeInfoAzure.class, statuses);
-	}
-}
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 b9d1488..1105066 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
@@ -20,7 +20,7 @@
 package com.epam.dlab.backendapi.dao.gcp;
 
 import com.epam.dlab.backendapi.dao.BaseBillingDAO;
-import com.epam.dlab.backendapi.resources.dto.gcp.GcpBillingFilter;
+import com.epam.dlab.backendapi.resources.dto.BillingFilter;
 import org.bson.Document;
 import org.bson.conversions.Bson;
 
@@ -30,12 +30,17 @@ import java.util.List;
 import static com.epam.dlab.MongoKeyWords.USAGE_FROM;
 import static com.epam.dlab.MongoKeyWords.USAGE_TO;
 import static com.epam.dlab.backendapi.dao.aws.AwsBillingDAO.DLAB_RESOURCE_TYPE;
-import static com.epam.dlab.model.aws.ReportLine.*;
-import static com.mongodb.client.model.Accumulators.*;
+import static com.epam.dlab.model.aws.ReportLine.FIELD_COST;
+import static com.epam.dlab.model.aws.ReportLine.FIELD_DLAB_ID;
+import static com.epam.dlab.model.aws.ReportLine.FIELD_PRODUCT;
+import static com.epam.dlab.model.aws.ReportLine.FIELD_USAGE_DATE;
+import static com.mongodb.client.model.Accumulators.max;
+import static com.mongodb.client.model.Accumulators.min;
+import static com.mongodb.client.model.Accumulators.sum;
 import static com.mongodb.client.model.Aggregates.group;
 import static com.mongodb.client.model.Aggregates.sort;
 
-public class GcpBillingDao extends BaseBillingDAO<GcpBillingFilter> {
+public class GcpBillingDao extends BaseBillingDAO {
     @Override
     protected Bson sortCriteria() {
         return sort(new Document(ID + "." + USER, 1)
@@ -54,13 +59,7 @@ public class GcpBillingDao extends BaseBillingDAO<GcpBillingFilter> {
     }
 
     @Override
-    protected List<Bson> cloudMatchCriteria(GcpBillingFilter filter) {
+    protected List<Bson> cloudMatchCriteria(BillingFilter filter) {
         return Collections.emptyList();
     }
-
-
-    @Override
-    protected String getSsnShape() {
-        return "t2.medium";
-    }
 }
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/gcp/GcpKeyDao.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/gcp/GcpKeyDao.java
deleted file mode 100644
index 7057f8d..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/gcp/GcpKeyDao.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.dao.gcp;
-
-import com.epam.dlab.backendapi.dao.KeyDAO;
-import com.epam.dlab.dto.UserInstanceStatus;
-import com.epam.dlab.dto.gcp.edge.EdgeInfoGcp;
-import com.google.inject.Singleton;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.Optional;
-
-
-@Slf4j
-@Singleton
-public class GcpKeyDao extends KeyDAO {
-	public GcpKeyDao() {
-		log.info("{} is initialized", getClass().getSimpleName());
-	}
-
-	@Override
-	public EdgeInfoGcp getEdgeInfo(String user) {
-		return super.getEdgeInfo(user, EdgeInfoGcp.class, new EdgeInfoGcp());
-	}
-
-	@Override
-	public Optional<EdgeInfoGcp> getEdgeInfoWhereStatusIn(String user, UserInstanceStatus... statuses) {
-		return super.getEdgeInfoWhereStatusIn(user, EdgeInfoGcp.class, statuses);
-	}
-}
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 c5a2d40..2fac97c 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
@@ -19,6 +19,7 @@
 
 package com.epam.dlab.backendapi.domain;
 
+import com.epam.dlab.cloud.CloudProvider;
 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import lombok.Data;
@@ -35,11 +36,7 @@ public class EndpointDTO {
 	@JsonProperty("endpoint_tag")
 	private final String tag;
 	private final EndpointStatus status;
-
-	public static EndpointDTO withEndpointStatus(EndpointDTO endpointDTO) {
-		return new EndpointDTO(endpointDTO.getName(), endpointDTO.getUrl(), endpointDTO.getAccount(),
-				endpointDTO.getTag(), EndpointDTO.EndpointStatus.ACTIVE);
-	}
+	private final CloudProvider cloudProvider;
 
 	public enum EndpointStatus {
 		ACTIVE,
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/EnvStatusListener.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/EnvStatusListener.java
deleted file mode 100644
index ab1f9a8..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/EnvStatusListener.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * 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.domain;
-
-import com.epam.dlab.auth.UserInfo;
-import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
-import com.epam.dlab.backendapi.dao.EnvDAO;
-import com.epam.dlab.backendapi.service.EndpointService;
-import com.epam.dlab.backendapi.util.RequestBuilder;
-import com.epam.dlab.constants.ServiceConsts;
-import com.epam.dlab.dto.UserEnvironmentResources;
-import com.epam.dlab.dto.status.EnvResourceList;
-import com.epam.dlab.rest.client.RESTService;
-import com.epam.dlab.rest.contracts.InfrasctructureAPI;
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.RemovalNotification;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import com.google.inject.name.Named;
-import io.dropwizard.lifecycle.Managed;
-import lombok.extern.slf4j.Slf4j;
-
-import java.util.Map;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Send requests to the docker to check environment status.
- */
-@Singleton
-@Slf4j
-public class EnvStatusListener implements Managed {
-
-	private final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
-
-	private final Cache<String, UserInfo> sessions;
-	private final EnvDAO dao;
-	private final RESTService provisioningService;
-	private final StatusChecker statusChecker = new StatusChecker();
-	private final long checkEnvStatusTimeout;
-	private final RequestBuilder requestBuilder;
-
-	@Inject
-	private RequestId requestId;
-	@Inject
-	private EndpointService endpointService;
-
-	@Inject
-	public EnvStatusListener(SelfServiceApplicationConfiguration configuration, EnvDAO dao,
-							 @Named(ServiceConsts.PROVISIONING_SERVICE_NAME) RESTService provisioningService,
-							 RequestBuilder requestBuilder) {
-
-		this.sessions = CacheBuilder.newBuilder()
-				.expireAfterAccess(configuration.getInactiveUserTimeoutMillSec(), TimeUnit.MILLISECONDS)
-				.removalListener((RemovalNotification<String, Object> notification) ->
-						log.info("User {} session is removed", notification.getKey()))
-				.build();
-
-		this.dao = dao;
-		this.provisioningService = provisioningService;
-		this.checkEnvStatusTimeout = configuration.getCheckEnvStatusTimeout().toMilliseconds();
-		this.requestBuilder = requestBuilder;
-	}
-
-	@Override
-	public void start() {
-		executorService.scheduleAtFixedRate(new StatusChecker(), checkEnvStatusTimeout, checkEnvStatusTimeout,
-				TimeUnit.MILLISECONDS);
-	}
-
-	@Override
-	public void stop() throws Exception {
-		statusChecker.shouldStop = true;
-		if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) {
-			executorService.shutdownNow();
-		}
-	}
-
-	public void registerSession(UserInfo userInfo) {
-		UserInfo ui = getSession(userInfo.getName());
-		log.info("Register session(existing = {}) for {}", ui != null, userInfo.getName());
-		sessions.put(userInfo.getName(), userInfo);
-	}
-
-	public void unregisterSession(UserInfo userInfo) {
-		log.info("Invalidate session for {}", userInfo.getName());
-		sessions.invalidate(userInfo.getName());
-	}
-
-	public UserInfo getSession(String username) {
-		return sessions.getIfPresent(username);
-	}
-
-	/**
-	 * Scheduled @{@link Runnable} that verifies status of users' resources
-	 */
-	private class StatusChecker implements Runnable {
-		private volatile boolean shouldStop = false;
-
-		@Override
-		public void run() {
-
-			log.debug("Start checking environment statuses");
-
-			sessions.cleanUp();
-
-			for (Map.Entry<String, UserInfo> entry : sessions.asMap().entrySet()) {
-				try {
-					if (!shouldStop) {
-						checkStatusThroughProvisioningService(entry.getValue());
-					} else {
-						log.info("Stopping env status listener");
-					}
-				} catch (RuntimeException e) {
-					log.error("Cannot check env status for user {}", entry.getKey(), e);
-				}
-			}
-		}
-
-		/**
-		 * Sends request to docker to check the status of user environment.
-		 *
-		 * @param userInfo username
-		 */
-		private void checkStatusThroughProvisioningService(UserInfo userInfo) {
-
-			final Map<String, EnvResourceList> envResources = dao.findEnvResources(userInfo.getName());
-			UserEnvironmentResources dto = requestBuilder.newUserEnvironmentStatus(userInfo);
-
-			envResources.forEach((endpoint, resourceList) -> {
-				log.trace("EnvStatus listener check status for user {} with resource list {}", userInfo.getName(),
-						resourceList);
-				dto.withResourceList(resourceList);
-				log.trace("Ask docker for the status of resources for user {}: {}", userInfo.getName(), dto);
-				String uuid =
-						provisioningService.post(endpointService.get(endpoint).getUrl() + InfrasctructureAPI.INFRASTRUCTURE_STATUS,
-								userInfo.getAccessToken(),
-								dto, String.class);
-				requestId.put(userInfo.getName(), uuid);
-
-			});
-		}
-	}
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/ExploratoryLibCache.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/ExploratoryLibCache.java
index 13c6cda..0faf66c 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/ExploratoryLibCache.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/domain/ExploratoryLibCache.java
@@ -223,18 +223,19 @@ public class ExploratoryLibCache implements Managed, Runnable {
 			String uuid;
 			if (userInstance.getResources() != null && !userInstance.getResources().isEmpty()) {
 				UserComputationalResource userComputationalResource = userInstance.getResources().get(0);
+				EndpointDTO endpointDTO = endpointService.get(userInstance.getEndpoint());
 				LibListComputationalDTO dto = requestBuilder.newLibComputationalList(userInfo, userInstance,
-						userComputationalResource);
-				uuid = provisioningService.post(endpointService
-								.get(userInstance.getEndpoint()).getUrl() + ComputationalAPI.COMPUTATIONAL_LIB_LIST,
+						userComputationalResource, endpointDTO);
+
+				uuid = provisioningService.post(endpointDTO.getUrl() + ComputationalAPI.COMPUTATIONAL_LIB_LIST,
 						userInfo.getAccessToken(),
 						dto, String.class);
 			} else {
-				ExploratoryActionDTO<?> dto = requestBuilder.newLibExploratoryList(userInfo, userInstance);
-				uuid =
-						provisioningService.post(endpointService.get(userInstance.getEndpoint()).getUrl() + ExploratoryAPI.EXPLORATORY_LIB_LIST,
-								userInfo.getAccessToken(), dto,
-								String.class);
+				EndpointDTO endpointDTO = endpointService.get(userInstance.getEndpoint());
+				ExploratoryActionDTO<?> dto = requestBuilder.newLibExploratoryList(userInfo, userInstance, endpointDTO);
+				uuid = provisioningService.post(endpointDTO.getUrl() + ExploratoryAPI.EXPLORATORY_LIB_LIST,
+						userInfo.getAccessToken(), dto,
+						String.class);
 			}
 
 			requestId.put(userInfo.getName(), uuid);
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dropwizard/listeners/MongoStartupListener.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dropwizard/listeners/MongoStartupListener.java
index 9d43df4..d25e2dd 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/dropwizard/listeners/MongoStartupListener.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/dropwizard/listeners/MongoStartupListener.java
@@ -1,6 +1,7 @@
 package com.epam.dlab.backendapi.dropwizard.listeners;
 
 import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
+import com.epam.dlab.backendapi.dao.EndpointDAO;
 import com.epam.dlab.backendapi.dao.SettingsDAO;
 import com.epam.dlab.backendapi.dao.UserRoleDao;
 import com.epam.dlab.backendapi.resources.dto.UserRoleDto;
@@ -14,9 +15,16 @@ import org.eclipse.jetty.server.Server;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
 
 import static java.lang.String.format;
+import static java.util.Comparator.comparing;
+import static java.util.stream.Collectors.collectingAndThen;
+import static java.util.stream.Collectors.toCollection;
 
 
 @Slf4j
@@ -27,22 +35,22 @@ public class MongoStartupListener implements ServerLifecycleListener {
 	private final UserRoleDao userRoleDao;
 	private final SelfServiceApplicationConfiguration configuration;
 	private final SettingsDAO settingsDAO;
+	private final EndpointDAO endpointDAO;
 
 	@Inject
-	public MongoStartupListener(UserRoleDao userRoleDao,
-								SelfServiceApplicationConfiguration configuration, SettingsDAO settingsDAO) {
+	public MongoStartupListener(UserRoleDao userRoleDao, SelfServiceApplicationConfiguration configuration,
+								SettingsDAO settingsDAO, EndpointDAO endpointDAO) {
 		this.userRoleDao = userRoleDao;
 		this.configuration = configuration;
 		this.settingsDAO = settingsDAO;
+		this.endpointDAO = endpointDAO;
 	}
 
 	@Override
 	public void serverStarted(Server server) {
 		settingsDAO.setServiceBaseName(configuration.getServiceBaseName());
 		settingsDAO.setConfOsFamily(configuration.getOs());
-		if (configuration.getCloudProvider() == CloudProvider.AZURE) {
-			settingsDAO.setAzureSsnInstanceSize(configuration.getSsnInstanceSize());
-		}
+		settingsDAO.setSsnInstanceSize(configuration.getSsnInstanceSize());
 		if (userRoleDao.findAll().isEmpty()) {
 			log.debug("Populating DLab roles into database");
 			userRoleDao.insert(getRoles());
@@ -52,8 +60,14 @@ public class MongoStartupListener implements ServerLifecycleListener {
 	}
 
 	private List<UserRoleDto> getRoles() {
-		try (InputStream is = getClass().getResourceAsStream(format(ROLES_FILE_FORMAT,
-				configuration.getCloudProvider().getName()))) {
+		Set<UserRoleDto> userRoles = new HashSet<>();
+		endpointDAO.getEndpoints().forEach(e -> userRoles.addAll(getUserRoleFromFile(e.getCloudProvider())));
+		return userRoles.stream().collect(collectingAndThen(toCollection(() -> new TreeSet<>(comparing(UserRoleDto::getId))),
+				ArrayList::new));
+	}
+
+	private List<UserRoleDto> getUserRoleFromFile(CloudProvider cloudProvider) {
+		try (InputStream is = getClass().getResourceAsStream(format(ROLES_FILE_FORMAT, cloudProvider.getName()))) {
 			return MAPPER.readValue(is, new TypeReference<List<UserRoleDto>>() {
 			});
 		} catch (IOException e) {
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/dropwizard/listeners/RestoreHandlerStartupListener.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/dropwizard/listeners/RestoreHandlerStartupListener.java
index 73f5961..0de166c 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/dropwizard/listeners/RestoreHandlerStartupListener.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/dropwizard/listeners/RestoreHandlerStartupListener.java
@@ -19,24 +19,30 @@
 
 package com.epam.dlab.backendapi.dropwizard.listeners;
 
+import com.epam.dlab.backendapi.domain.EndpointDTO;
+import com.epam.dlab.backendapi.service.EndpointService;
 import com.epam.dlab.rest.client.RESTService;
 import io.dropwizard.lifecycle.ServerLifecycleListener;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.eclipse.jetty.server.Server;
 
 @Slf4j
 public class RestoreHandlerStartupListener implements ServerLifecycleListener {
 
 	private final RESTService provisioningService;
+	private final EndpointService endpointService;
 
-	public RestoreHandlerStartupListener(RESTService provisioningService) {
+	public RestoreHandlerStartupListener(RESTService provisioningService, EndpointService endpointService) {
 		this.provisioningService = provisioningService;
+		this.endpointService = endpointService;
 	}
 
 	@Override
 	public void serverStarted(Server server) {
 		try {
-			provisioningService.post("/handler/restore", new Object(), Object.class);
+			endpointService.getEndpointsWithStatus(EndpointDTO.EndpointStatus.ACTIVE)
+					.forEach(e -> provisioningService.post(e.getUrl() + "/handler/restore", StringUtils.EMPTY, Object.class));
 		} catch (Exception e) {
 			log.error("Exception occurred during restore handler request: {}", e.getMessage());
 		}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/AwsSelfServiceModule.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/AwsSelfServiceModule.java
index f4db277..0fd45de 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/AwsSelfServiceModule.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/AwsSelfServiceModule.java
@@ -20,23 +20,14 @@
 package com.epam.dlab.backendapi.modules;
 
 import com.epam.dlab.backendapi.SelfServiceApplication;
-import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
 import com.epam.dlab.backendapi.annotation.BudgetLimited;
+import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
 import com.epam.dlab.backendapi.dao.BillingDAO;
-import com.epam.dlab.backendapi.dao.KeyDAO;
 import com.epam.dlab.backendapi.dao.aws.AwsBillingDAO;
-import com.epam.dlab.backendapi.dao.aws.AwsKeyDao;
 import com.epam.dlab.backendapi.interceptor.BudgetLimitInterceptor;
-import com.epam.dlab.backendapi.resources.aws.BillingResourceAws;
 import com.epam.dlab.backendapi.resources.aws.ComputationalResourceAws;
-import com.epam.dlab.backendapi.resources.callback.aws.EdgeCallbackAws;
-import com.epam.dlab.backendapi.resources.callback.aws.KeyUploaderCallbackAws;
 import com.epam.dlab.backendapi.service.BillingService;
-import com.epam.dlab.backendapi.service.InfrastructureInfoService;
-import com.epam.dlab.backendapi.service.InfrastructureTemplateService;
 import com.epam.dlab.backendapi.service.aws.AwsBillingService;
-import com.epam.dlab.backendapi.service.aws.AwsInfrastructureInfoService;
-import com.epam.dlab.backendapi.service.aws.AwsInfrastructureTemplateService;
 import com.epam.dlab.cloud.CloudModule;
 import com.epam.dlab.mongo.MongoServiceFactory;
 import com.fiestacabin.dropwizard.quartz.SchedulerConfiguration;
@@ -60,11 +51,8 @@ public class AwsSelfServiceModule extends CloudModule {
 	@Override
 	protected void configure() {
 		bind(BillingService.class).to(AwsBillingService.class);
-		bind((KeyDAO.class)).to(AwsKeyDao.class);
-		bind(InfrastructureInfoService.class).to(AwsInfrastructureInfoService.class);
 		bind(SchedulerConfiguration.class).toInstance(
 				new SchedulerConfiguration(SelfServiceApplication.class.getPackage().getName()));
-		bind(InfrastructureTemplateService.class).to(AwsInfrastructureTemplateService.class);
 		bind(BillingDAO.class).to(AwsBillingDAO.class);
 		final BudgetLimitInterceptor budgetLimitInterceptor = new BudgetLimitInterceptor();
 		requestInjection(budgetLimitInterceptor);
@@ -73,10 +61,8 @@ public class AwsSelfServiceModule extends CloudModule {
 
 	@Override
 	public void init(Environment environment, Injector injector) {
-		environment.jersey().register(injector.getInstance(EdgeCallbackAws.class));
-		environment.jersey().register(injector.getInstance(KeyUploaderCallbackAws.class));
 		environment.jersey().register(injector.getInstance(ComputationalResourceAws.class));
-		environment.jersey().register(injector.getInstance(BillingResourceAws.class));
+//
 
 		/*injector.getInstance(SecurityFactory.class).configure(injector, environment,
 				SelfServiceSecurityAuthenticator.class, injector.getInstance(Authorizer.class));*/
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/AzureSelfServiceModule.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/AzureSelfServiceModule.java
index f1b62e1..ee04041 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/AzureSelfServiceModule.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/AzureSelfServiceModule.java
@@ -20,23 +20,14 @@
 package com.epam.dlab.backendapi.modules;
 
 import com.epam.dlab.backendapi.SelfServiceApplication;
-import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
 import com.epam.dlab.backendapi.annotation.BudgetLimited;
+import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
 import com.epam.dlab.backendapi.dao.BillingDAO;
-import com.epam.dlab.backendapi.dao.KeyDAO;
 import com.epam.dlab.backendapi.dao.azure.AzureBillingDAO;
-import com.epam.dlab.backendapi.dao.azure.AzureKeyDao;
 import com.epam.dlab.backendapi.interceptor.BudgetLimitInterceptor;
-import com.epam.dlab.backendapi.resources.azure.BillingResourceAzure;
 import com.epam.dlab.backendapi.resources.azure.ComputationalResourceAzure;
-import com.epam.dlab.backendapi.resources.callback.azure.EdgeCallbackAzure;
-import com.epam.dlab.backendapi.resources.callback.azure.KeyUploaderCallbackAzure;
 import com.epam.dlab.backendapi.service.BillingService;
-import com.epam.dlab.backendapi.service.InfrastructureInfoService;
-import com.epam.dlab.backendapi.service.InfrastructureTemplateService;
 import com.epam.dlab.backendapi.service.azure.AzureBillingService;
-import com.epam.dlab.backendapi.service.azure.AzureInfrastructureInfoService;
-import com.epam.dlab.backendapi.service.azure.AzureInfrastructureTemplateService;
 import com.epam.dlab.cloud.CloudModule;
 import com.epam.dlab.mongo.MongoServiceFactory;
 import com.fiestacabin.dropwizard.quartz.SchedulerConfiguration;
@@ -58,22 +49,12 @@ public class AzureSelfServiceModule extends CloudModule {
 	private static final String MONGO_URI_FORMAT = "mongodb://%s:%s@%s:%d/%s";
 	private static final String QUARTZ_MONGO_URI_PROPERTY = "org.quartz.jobStore.mongoUri";
 	private static final String QUARTZ_DB_NAME = "org.quartz.jobStore.dbName";
-	private boolean useLdap;
-	private long maxSessionDurabilityMilliseconds;
-
-	public AzureSelfServiceModule(boolean useLdap, long maxSessionDurabilityMilliseconds) {
-		this.useLdap = useLdap;
-		this.maxSessionDurabilityMilliseconds = maxSessionDurabilityMilliseconds;
-	}
 
 	@Override
 	protected void configure() {
 		bind(BillingService.class).to(AzureBillingService.class);
-		bind((KeyDAO.class)).to(AzureKeyDao.class);
-		bind(InfrastructureInfoService.class).to(AzureInfrastructureInfoService.class);
 		bind(SchedulerConfiguration.class).toInstance(
 				new SchedulerConfiguration(SelfServiceApplication.class.getPackage().getName()));
-		bind(InfrastructureTemplateService.class).to(AzureInfrastructureTemplateService.class);
 		bind(BillingDAO.class).to(AzureBillingDAO.class);
 		final BudgetLimitInterceptor budgetLimitInterceptor = new BudgetLimitInterceptor();
 		requestInjection(budgetLimitInterceptor);
@@ -82,10 +63,7 @@ public class AzureSelfServiceModule extends CloudModule {
 
 	@Override
 	public void init(Environment environment, Injector injector) {
-		environment.jersey().register(injector.getInstance(EdgeCallbackAzure.class));
-		environment.jersey().register(injector.getInstance(KeyUploaderCallbackAzure.class));
 		environment.jersey().register(injector.getInstance(ComputationalResourceAzure.class));
-		environment.jersey().register(injector.getInstance(BillingResourceAzure.class));
 
 	}
 
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/GcpSelfServiceModule.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/CloudProviderModule.java
similarity index 59%
copy from services/self-service/src/main/java/com/epam/dlab/backendapi/modules/GcpSelfServiceModule.java
copy to services/self-service/src/main/java/com/epam/dlab/backendapi/modules/CloudProviderModule.java
index 90c3fde..7ea2739 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/GcpSelfServiceModule.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/CloudProviderModule.java
@@ -23,21 +23,23 @@ import com.epam.dlab.backendapi.SelfServiceApplication;
 import com.epam.dlab.backendapi.annotation.BudgetLimited;
 import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
 import com.epam.dlab.backendapi.dao.BillingDAO;
-import com.epam.dlab.backendapi.dao.KeyDAO;
+import com.epam.dlab.backendapi.dao.aws.AwsBillingDAO;
+import com.epam.dlab.backendapi.dao.azure.AzureBillingDAO;
 import com.epam.dlab.backendapi.dao.gcp.GcpBillingDao;
-import com.epam.dlab.backendapi.dao.gcp.GcpKeyDao;
 import com.epam.dlab.backendapi.interceptor.BudgetLimitInterceptor;
-import com.epam.dlab.backendapi.resources.callback.gcp.EdgeCallbackGcp;
-import com.epam.dlab.backendapi.resources.callback.gcp.KeyUploaderCallbackGcp;
-import com.epam.dlab.backendapi.resources.gcp.BillingResourceGcp;
+import com.epam.dlab.backendapi.resources.BillingResource;
+import com.epam.dlab.backendapi.resources.aws.ComputationalResourceAws;
+import com.epam.dlab.backendapi.resources.azure.ComputationalResourceAzure;
 import com.epam.dlab.backendapi.resources.gcp.ComputationalResourceGcp;
 import com.epam.dlab.backendapi.resources.gcp.GcpOauthResource;
 import com.epam.dlab.backendapi.service.BillingService;
 import com.epam.dlab.backendapi.service.InfrastructureInfoService;
 import com.epam.dlab.backendapi.service.InfrastructureTemplateService;
+import com.epam.dlab.backendapi.service.aws.AwsBillingService;
+import com.epam.dlab.backendapi.service.azure.AzureBillingService;
 import com.epam.dlab.backendapi.service.gcp.GcpBillingService;
-import com.epam.dlab.backendapi.service.gcp.GcpInfrastructureInfoService;
-import com.epam.dlab.backendapi.service.gcp.GcpInfrastructureTemplateService;
+import com.epam.dlab.backendapi.service.impl.InfrastructureInfoServiceImpl;
+import com.epam.dlab.backendapi.service.impl.InfrastructureTemplateServiceImpl;
 import com.epam.dlab.cloud.CloudModule;
 import com.epam.dlab.mongo.MongoServiceFactory;
 import com.fiestacabin.dropwizard.quartz.SchedulerConfiguration;
@@ -52,40 +54,42 @@ import org.quartz.impl.StdSchedulerFactory;
 import static com.google.inject.matcher.Matchers.annotatedWith;
 import static com.google.inject.matcher.Matchers.any;
 
-public class GcpSelfServiceModule extends CloudModule {
+public class CloudProviderModule extends CloudModule {
 
     private static final String MONGO_URI_FORMAT = "mongodb://%s:%s@%s:%d/%s";
     private static final String QUARTZ_MONGO_URI_PROPERTY = "org.quartz.jobStore.mongoUri";
     private static final String QUARTZ_DB_NAME = "org.quartz.jobStore.dbName";
 
-    @Override
-    @SuppressWarnings("unchecked")
-    public void init(Environment environment, Injector injector) {
-
-		environment.jersey().register(injector.getInstance(EdgeCallbackGcp.class));
-		environment.jersey().register(injector.getInstance(KeyUploaderCallbackGcp.class));
-		environment.jersey().register(injector.getInstance(ComputationalResourceGcp.class));
-		environment.jersey().register(injector.getInstance(BillingResourceGcp.class));
-		if (injector.getInstance(SelfServiceApplicationConfiguration.class).isGcpOuauth2AuthenticationEnabled()) {
-			environment.jersey().register(injector.getInstance(GcpOauthResource.class));
-		}
+    private SelfServiceApplicationConfiguration configuration;
 
+    public CloudProviderModule(SelfServiceApplicationConfiguration configuration) {
+        this.configuration = configuration;
     }
 
     @Override
     protected void configure() {
-        bind(BillingService.class).to(GcpBillingService.class);
-        bind((KeyDAO.class)).to(GcpKeyDao.class);
-        bind(InfrastructureInfoService.class).to(GcpInfrastructureInfoService.class);
-        bind(InfrastructureTemplateService.class).to(GcpInfrastructureTemplateService.class);
-        bind(BillingDAO.class).to(GcpBillingDao.class);
+        bindBilling();
+        bind(InfrastructureInfoService.class).to(InfrastructureInfoServiceImpl.class);
+        bind(InfrastructureTemplateService.class).to(InfrastructureTemplateServiceImpl.class);
         bind(SchedulerConfiguration.class).toInstance(
                 new SchedulerConfiguration(SelfServiceApplication.class.getPackage().getName()));
+
         final BudgetLimitInterceptor budgetLimitInterceptor = new BudgetLimitInterceptor();
         requestInjection(budgetLimitInterceptor);
         bindInterceptor(any(), annotatedWith(BudgetLimited.class), budgetLimitInterceptor);
     }
 
+    @Override
+    public void init(Environment environment, Injector injector) {
+        environment.jersey().register(injector.getInstance(BillingResource.class));
+        environment.jersey().register(injector.getInstance(ComputationalResourceAws.class));
+        environment.jersey().register(injector.getInstance(ComputationalResourceAzure.class));
+        environment.jersey().register(injector.getInstance(ComputationalResourceGcp.class));
+        if (injector.getInstance(SelfServiceApplicationConfiguration.class).isGcpOuauth2AuthenticationEnabled()) {
+            environment.jersey().register(injector.getInstance(GcpOauthResource.class));
+        }
+    }
+
     @Provides
     @Singleton
     Scheduler provideScheduler(SelfServiceApplicationConfiguration configuration) throws SchedulerException {
@@ -97,4 +101,23 @@ public class GcpSelfServiceModule extends CloudModule {
         System.setProperty(QUARTZ_DB_NAME, database);
         return StdSchedulerFactory.getDefaultScheduler();
     }
+
+    private void bindBilling() {
+        switch (configuration.getCloudProvider()) {
+            case AWS:
+                bind(BillingService.class).to(AwsBillingService.class);
+                bind(BillingDAO.class).to(AwsBillingDAO.class);
+                break;
+            case AZURE:
+                bind(BillingService.class).to(AzureBillingService.class);
+                bind(BillingDAO.class).to(AzureBillingDAO.class);
+                break;
+            case GCP:
+                bind(BillingService.class).to(GcpBillingService.class);
+                bind(BillingDAO.class).to(GcpBillingDao.class);
+                break;
+            default:
+                throw new UnsupportedOperationException("Unsupported cloud provider " + configuration.getCloudProvider());
+        }
+    }
 }
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/DevModule.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/DevModule.java
index 3594826..cf08d12 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/DevModule.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/DevModule.java
@@ -89,9 +89,7 @@ public class DevModule extends ModuleBase<SelfServiceApplicationConfiguration> i
 		bind(LibraryService.class).to(LibraryServiceImpl.class);
 		bind(SchedulerJobService.class).to(SchedulerJobServiceImpl.class);
 		bind(EnvironmentService.class).to(EnvironmentServiceImpl.class);
-		bind(EdgeService.class).to(EdgeServiceImpl.class);
 		bind(ReuploadKeyService.class).to(ReuploadKeyServiceImpl.class);
-		bind(UserResourceService.class).to(UserResourceServiceImpl.class);
 		bind(RESTService.class).annotatedWith(Names.named(ServiceConsts.MAVEN_SEARCH_API))
 				.toInstance(configuration.getMavenApiFactory().build(environment, ServiceConsts.MAVEN_SEARCH_API));
 
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/GcpSelfServiceModule.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/GcpSelfServiceModule.java
index 90c3fde..276238e 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/GcpSelfServiceModule.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/GcpSelfServiceModule.java
@@ -23,21 +23,12 @@ import com.epam.dlab.backendapi.SelfServiceApplication;
 import com.epam.dlab.backendapi.annotation.BudgetLimited;
 import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
 import com.epam.dlab.backendapi.dao.BillingDAO;
-import com.epam.dlab.backendapi.dao.KeyDAO;
 import com.epam.dlab.backendapi.dao.gcp.GcpBillingDao;
-import com.epam.dlab.backendapi.dao.gcp.GcpKeyDao;
 import com.epam.dlab.backendapi.interceptor.BudgetLimitInterceptor;
-import com.epam.dlab.backendapi.resources.callback.gcp.EdgeCallbackGcp;
-import com.epam.dlab.backendapi.resources.callback.gcp.KeyUploaderCallbackGcp;
-import com.epam.dlab.backendapi.resources.gcp.BillingResourceGcp;
 import com.epam.dlab.backendapi.resources.gcp.ComputationalResourceGcp;
 import com.epam.dlab.backendapi.resources.gcp.GcpOauthResource;
 import com.epam.dlab.backendapi.service.BillingService;
-import com.epam.dlab.backendapi.service.InfrastructureInfoService;
-import com.epam.dlab.backendapi.service.InfrastructureTemplateService;
 import com.epam.dlab.backendapi.service.gcp.GcpBillingService;
-import com.epam.dlab.backendapi.service.gcp.GcpInfrastructureInfoService;
-import com.epam.dlab.backendapi.service.gcp.GcpInfrastructureTemplateService;
 import com.epam.dlab.cloud.CloudModule;
 import com.epam.dlab.mongo.MongoServiceFactory;
 import com.fiestacabin.dropwizard.quartz.SchedulerConfiguration;
@@ -61,11 +52,7 @@ public class GcpSelfServiceModule extends CloudModule {
     @Override
     @SuppressWarnings("unchecked")
     public void init(Environment environment, Injector injector) {
-
-		environment.jersey().register(injector.getInstance(EdgeCallbackGcp.class));
-		environment.jersey().register(injector.getInstance(KeyUploaderCallbackGcp.class));
 		environment.jersey().register(injector.getInstance(ComputationalResourceGcp.class));
-		environment.jersey().register(injector.getInstance(BillingResourceGcp.class));
 		if (injector.getInstance(SelfServiceApplicationConfiguration.class).isGcpOuauth2AuthenticationEnabled()) {
 			environment.jersey().register(injector.getInstance(GcpOauthResource.class));
 		}
@@ -75,9 +62,6 @@ public class GcpSelfServiceModule extends CloudModule {
     @Override
     protected void configure() {
         bind(BillingService.class).to(GcpBillingService.class);
-        bind((KeyDAO.class)).to(GcpKeyDao.class);
-        bind(InfrastructureInfoService.class).to(GcpInfrastructureInfoService.class);
-        bind(InfrastructureTemplateService.class).to(GcpInfrastructureTemplateService.class);
         bind(BillingDAO.class).to(GcpBillingDao.class);
         bind(SchedulerConfiguration.class).toInstance(
                 new SchedulerConfiguration(SelfServiceApplication.class.getPackage().getName()));
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/ModuleFactory.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/ModuleFactory.java
index 06ac774..1480fe7 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/ModuleFactory.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/ModuleFactory.java
@@ -46,12 +46,15 @@ public class ModuleFactory {
 	}
 
 	public static CloudModule getCloudProviderModule(SelfServiceApplicationConfiguration configuration) {
+		return new CloudProviderModule(configuration);
+	}
+
+	private static CloudModule getCloudModule(SelfServiceApplicationConfiguration configuration) {
 		switch (configuration.getCloudProvider()) {
 			case AWS:
 				return new AwsSelfServiceModule();
 			case AZURE:
-				return new AzureSelfServiceModule(configuration.isAzureUseLdap(),
-						configuration.getMaxSessionDurabilityMilliseconds());
+				return new AzureSelfServiceModule();
 			case GCP:
 				return new GcpSelfServiceModule();
 			default:
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/ProductionModule.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/ProductionModule.java
index f66487a..0d0ae1d 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/ProductionModule.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/modules/ProductionModule.java
@@ -78,9 +78,7 @@ public class ProductionModule extends ModuleBase<SelfServiceApplicationConfigura
 		bind(LibraryService.class).to(LibraryServiceImpl.class);
 		bind(SchedulerJobService.class).to(SchedulerJobServiceImpl.class);
 		bind(EnvironmentService.class).to(EnvironmentServiceImpl.class);
-		bind(EdgeService.class).to(EdgeServiceImpl.class);
 		bind(ReuploadKeyService.class).to(ReuploadKeyServiceImpl.class);
-		bind(UserResourceService.class).to(UserResourceServiceImpl.class);
 		bind(RESTService.class).annotatedWith(Names.named(ServiceConsts.MAVEN_SEARCH_API))
 				.toInstance(configuration.getMavenApiFactory().build(environment, ServiceConsts.MAVEN_SEARCH_API));
 		bind(ExternalLibraryService.class).to(MavenCentralLibraryService.class);
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/gcp/BillingResourceGcp.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/BillingResource.java
similarity index 75%
rename from services/self-service/src/main/java/com/epam/dlab/backendapi/resources/gcp/BillingResourceGcp.java
rename to services/self-service/src/main/java/com/epam/dlab/backendapi/resources/BillingResource.java
index 7195c75..0d27fad 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/gcp/BillingResourceGcp.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/BillingResource.java
@@ -17,10 +17,10 @@
  * under the License.
  */
 
-package com.epam.dlab.backendapi.resources.gcp;
+package com.epam.dlab.backendapi.resources;
 
 import com.epam.dlab.auth.UserInfo;
-import com.epam.dlab.backendapi.resources.dto.gcp.GcpBillingFilter;
+import com.epam.dlab.backendapi.resources.dto.BillingFilter;
 import com.epam.dlab.backendapi.service.BillingService;
 import com.google.inject.Inject;
 import io.dropwizard.auth.Auth;
@@ -28,6 +28,7 @@ import org.bson.Document;
 
 import javax.validation.Valid;
 import javax.validation.constraints.NotNull;
+import javax.ws.rs.Consumes;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
@@ -36,41 +37,30 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
 @Path("/billing")
-public class BillingResourceGcp {
+@Consumes(MediaType.APPLICATION_JSON)
+public class BillingResource {
+
+    private final BillingService billingService;
 
     @Inject
-    private BillingService billingService;
+    public BillingResource(BillingService billingService) {
+        this.billingService = billingService;
+    }
 
-    /**
-     * Returns the billing report.
-     *
-     * @param userInfo user info.
-     * @param formDTO  filter for report data.
-     */
     @POST
     @Path("/report")
     @Produces(MediaType.APPLICATION_JSON)
-    @SuppressWarnings("unchecked")
-    public Document getBillingReport(@Auth UserInfo userInfo, @Valid @NotNull GcpBillingFilter formDTO) {
+    public Document getBillingReport(@Auth UserInfo userInfo, @Valid @NotNull BillingFilter formDTO) {
         return billingService.getBillingReport(userInfo, formDTO);
     }
 
-    /**
-     * Returns the billing report in csv file.
-     *
-     * @param userInfo user info.
-     * @param formDTO  filter for report data.
-     */
-
     @POST
     @Path("/report/download")
     @Produces(MediaType.APPLICATION_OCTET_STREAM)
-    @SuppressWarnings("unchecked")
-    public Response downloadBillingReport(@Auth UserInfo userInfo, @Valid @NotNull GcpBillingFilter formDTO) {
+    public Response downloadBillingReport(@Auth UserInfo userInfo, @Valid @NotNull BillingFilter formDTO) {
         return Response.ok(billingService.downloadReport(userInfo, formDTO))
                 .header(HttpHeaders.CONTENT_DISPOSITION,
                         "attachment; filename=\"" + billingService.getReportFileName(userInfo, formDTO) + "\"")
                 .build();
     }
-
 }
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/EdgeResource.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/EdgeResource.java
deleted file mode 100644
index 3ae31b3..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/EdgeResource.java
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.resources;
-
-import com.epam.dlab.auth.UserInfo;
-import com.epam.dlab.backendapi.service.EdgeService;
-import com.epam.dlab.rest.contracts.EdgeAPI;
-import com.google.inject.Inject;
-import io.dropwizard.auth.Auth;
-import lombok.extern.slf4j.Slf4j;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-
-/**
- * Provides the REST API to manage(start/stop) edge node
- */
-@Path("/infrastructure/edge")
-@Consumes(MediaType.APPLICATION_JSON)
-@Produces(MediaType.APPLICATION_JSON)
-@Slf4j
-public class EdgeResource implements EdgeAPI {
-
-	private final EdgeService edgeService;
-
-	@Inject
-	public EdgeResource(EdgeService edgeService) {
-		this.edgeService = edgeService;
-	}
-
-	/**
-	 * Starts EDGE node for user.
-	 *
-	 * @param userInfo user info.
-	 * @return Request Id.
-	 */
-	@POST
-	@Path("/start")
-	public String start(@Auth UserInfo userInfo) {
-		return edgeService.start(userInfo);
-	}
-
-	/**
-	 * Stop EDGE node for user.
-	 *
-	 * @param userInfo user info.
-	 * @return Request Id.
-	 */
-	@POST
-	@Path("/stop")
-	public String stop(@Auth UserInfo userInfo) {
-		return edgeService.stop(userInfo);
-	}
-}
\ No newline at end of file
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 71873eb..6707571 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
@@ -153,7 +153,7 @@ public class EndpointResource {
 	public Response checkEndpointUrl(@Parameter(hidden = true) @Auth UserInfo userInfo,
 									 @Parameter(description = "Endpoint url")
 									 @PathParam("url") String url) {
-		endpointService.checkEndpointUrl(userInfo, url);
+		endpointService.checkUrl(userInfo, url);
 		return Response.ok().build();
 	}
 }
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/EnvironmentResource.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/EnvironmentResource.java
index 1bd6826..f227f3f 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/EnvironmentResource.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/EnvironmentResource.java
@@ -62,17 +62,6 @@ public class EnvironmentResource {
 	@POST
 	@Consumes(MediaType.TEXT_PLAIN)
 	@Produces(MediaType.APPLICATION_JSON)
-	@Path("terminate")
-	public Response terminateEnv(@Auth UserInfo userInfo,
-								 @NotEmpty String user) {
-		log.info("User {} is terminating {} environment", userInfo.getName(), user);
-		environmentService.terminateEnvironment(userInfo, user);
-		return Response.ok().build();
-	}
-
-	@POST
-	@Consumes(MediaType.TEXT_PLAIN)
-	@Produces(MediaType.APPLICATION_JSON)
 	@Path("stop")
 	public Response stopEnv(@Auth UserInfo userInfo,
 							@NotEmpty String user) {
@@ -84,16 +73,6 @@ public class EnvironmentResource {
 	@POST
 	@Consumes(MediaType.TEXT_PLAIN)
 	@Produces(MediaType.APPLICATION_JSON)
-	@Path("stop/edge")
-	public Response stopEdge(@Auth UserInfo userInfo, @NotEmpty String user) {
-		log.info("Admin {} is stopping edge of user {}", userInfo.getName(), user);
-		environmentService.stopEdge(user);
-		return Response.ok().build();
-	}
-
-	@POST
-	@Consumes(MediaType.TEXT_PLAIN)
-	@Produces(MediaType.APPLICATION_JSON)
 	@Path("stop/{exploratoryName}")
 	public Response stopNotebook(@Auth UserInfo userInfo, @NotEmpty String user,
 								 @PathParam("exploratoryName") String exploratoryName) {
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/KeyUploaderResource.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/KeyUploaderResource.java
deleted file mode 100644
index a58f8dc..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/KeyUploaderResource.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.resources;
-
-import com.epam.dlab.auth.UserInfo;
-import com.epam.dlab.backendapi.service.AccessKeyService;
-import com.epam.dlab.dto.keyload.KeyLoadStatus;
-import com.epam.dlab.exceptions.DlabException;
-import com.epam.dlab.exceptions.DlabValidationException;
-import com.epam.dlab.exceptions.ResourceNotFoundException;
-import com.epam.dlab.rest.contracts.EdgeAPI;
-import com.google.inject.Inject;
-import io.dropwizard.auth.Auth;
-import lombok.extern.slf4j.Slf4j;
-import org.glassfish.jersey.media.multipart.FormDataParam;
-
-import javax.ws.rs.*;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-
-/**
- * Provides the REST API for upload the user key.
- */
-@Path("/user/access_key")
-@Consumes(MediaType.APPLICATION_JSON)
-@Produces(MediaType.APPLICATION_JSON)
-@Slf4j
-public class KeyUploaderResource implements EdgeAPI {
-
-	private static final String FILE_ATTACHMENT_FORMAT = "attachment; filename=\"%s.pem\"";
-	private AccessKeyService keyService;
-
-	@Inject
-	public KeyUploaderResource(AccessKeyService keyService) {
-		this.keyService = keyService;
-	}
-
-	/**
-	 * Finds and returns the status of the user key.
-	 *
-	 * @param userInfo user info.
-	 * @return <pre>
-	 * {@link Status#NOT_FOUND} the user key has been not found.
-	 * {@link Status#ACCEPTED} the user key is uploading now.
-	 * {@link Status#OK} the user key is valid.
-	 * {@link Status#INTERNAL_SERVER_ERROR} the check of the status is failed.
-	 * </pre>
-	 */
-	@GET
-	public Response checkKey(@Auth UserInfo userInfo) {
-		final KeyLoadStatus status = keyService.getUserKeyStatus(userInfo.getName());
-		if (KeyLoadStatus.NONE == status) {
-			throw new ResourceNotFoundException("Key for user " + userInfo.getName() + " not found");
-		} else if (KeyLoadStatus.ERROR == status) {
-			throw new DlabException("Key for user " + userInfo.getName() + " is in error state");
-		}
-		return Response.status(status.getHttpStatus()).build();
-	}
-
-	/**
-	 * Uploads/reuploads the user key to server. If param 'isPrimaryUploading' equals 'true', then it stores
-	 * the user key to the database and calls the post method of the provisioning service for the key uploading
-	 * and edge creating for user. Else if this param equals 'false', then only replacing keys in the database
-	 * will be performed (user's key will be reuploaded).
-	 *
-	 * @param userInfo           user info.
-	 * @param fileContent        content of the user key.
-	 * @param isPrimaryUploading true if key is being primarily uploaded, false - in case of reuploading
-	 * @return 200 Ok
-	 */
-	@POST
-	@Consumes(MediaType.MULTIPART_FORM_DATA)
-	public Response loadKey( @Auth UserInfo userInfo,
-							@FormDataParam("file") String fileContent,
-							@QueryParam("is_primary_uploading") @DefaultValue("true") boolean isPrimaryUploading) {
-
-		validate(fileContent);
-		keyService.uploadKey(userInfo, fileContent, isPrimaryUploading);
-		return Response.ok().build();
-	}
-
-	/**
-	 * Creates the EDGE node and upload the user key  for user.
-	 *
-	 * @param userInfo user info.
-	 * @return {@link Response.Status#OK} request for provisioning service has been accepted.<br>
-	 */
-	@POST
-	@Path("/recover")
-	public Response recover(@Auth UserInfo userInfo) {
-		return Response.ok(keyService.recoverEdge(userInfo)).build();
-	}
-
-
-	@POST
-	@Path("/generate")
-	@Produces(MediaType.APPLICATION_OCTET_STREAM)
-	public Response generate(@Auth UserInfo userInfo,
-							 @QueryParam("is_primary_uploading") @DefaultValue("true") boolean isPrimaryUploading) {
-		final Response.ResponseBuilder builder = Response.ok(keyService.generateKey(userInfo, isPrimaryUploading));
-		builder.header(HttpHeaders.CONTENT_DISPOSITION, String.format(FILE_ATTACHMENT_FORMAT, userInfo.getName()));
-		return builder.build();
-	}
-
-	private void validate(String publicKey) {
-		if (!publicKey.startsWith("ssh-")) {
-			log.error("Wrong key format. Key should be in openSSH format");
-			log.trace("Key content:\n{}", publicKey);
-			throw new DlabValidationException("Wrong key format. Key should be in openSSH format");
-		}
-	}
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/SecurityResource.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/SecurityResource.java
deleted file mode 100644
index 031ffa7..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/SecurityResource.java
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.resources;
-
-import com.epam.dlab.auth.UserInfo;
-import com.epam.dlab.auth.contract.SecurityAPI;
-import com.epam.dlab.auth.dto.UserCredentialDTO;
-import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
-import com.epam.dlab.backendapi.dao.SecurityDAO;
-import com.epam.dlab.backendapi.domain.EnvStatusListener;
-import com.epam.dlab.backendapi.roles.UserRoles;
-import com.epam.dlab.exceptions.DlabException;
-import com.epam.dlab.rest.client.RESTService;
-import com.epam.dlab.rest.dto.ErrorDTO;
-import com.epam.dlab.validation.AwsValidation;
-import com.google.inject.Inject;
-import io.dropwizard.auth.Auth;
-import lombok.extern.slf4j.Slf4j;
-import org.hibernate.validator.constraints.NotBlank;
-
-import javax.validation.Valid;
-import javax.validation.constraints.NotNull;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-
-/**
- * Provides the REST API for the user authorization.
- */
-@Path("/user")
-@Consumes(MediaType.APPLICATION_JSON)
-@Produces(MediaType.APPLICATION_JSON)
-@Slf4j
-public class SecurityResource implements SecurityAPI {
-
-	private SecurityDAO dao;
-	private RESTService securityService;
-	private EnvStatusListener envStatusListener;
-	private SelfServiceApplicationConfiguration configuration;
-
-	@Inject
-	public SecurityResource(SecurityDAO dao,
-							EnvStatusListener envStatusListener, SelfServiceApplicationConfiguration configuration) {
-		this.dao = dao;
-		this.securityService = null;
-		this.envStatusListener = envStatusListener;
-		this.configuration = configuration;
-	}
-
-	/**
-	 * Login method for the DLab user.
-	 *
-	 * @param credential user credential.
-	 * @return 500 Internal Server Error if post response fails.
-	 */
-	@POST
-	@Produces(MediaType.TEXT_PLAIN)
-	@Path("/login")
-	public Response userLogin(@Valid @NotNull UserCredentialDTO credential) {
-		log.debug("Try login for user {}", credential.getUsername());
-		try {
-			dao.writeLoginAttempt(credential);
-			return securityService.post(LOGIN, credential, Response.class);
-		} catch (Exception e) {
-			log.error("Try login for user {} fail", credential.getUsername(), e);
-			final Status internalServerError = Status.INTERNAL_SERVER_ERROR;
-			return Response.status(internalServerError)
-					.entity(new ErrorDTO(internalServerError.getStatusCode(), e.getMessage()))
-					.type(MediaType.APPLICATION_JSON)
-					.build();
-		}
-	}
-
-
-	/**
-	 * Authorize method for the dlab user.
-	 *
-	 * @param userInfo user info.
-	 * @param username user name.
-	 * @return 500 Internal Server Error if post request fails.
-	 */
-	@POST
-	@Consumes(MediaType.TEXT_PLAIN)
-	@Path("/authorize")
-	public Response authorize(@Auth UserInfo userInfo,
-							  @Valid @NotBlank(groups = AwsValidation.class) String username) {
-		log.debug("Try authorize accessToken {} for user info {}", userInfo.getAccessToken(), userInfo);
-		try {
-			Status status = userInfo.getName().equalsIgnoreCase(username) ?
-					Status.OK :
-					Status.FORBIDDEN;
-			if (status == Status.OK) {
-				envStatusListener.registerSession(userInfo);
-				if (configuration.isRolePolicyEnabled()) {
-					UserRoles.initialize(dao, configuration.getRoleDefaultAccess());
-				}
-			}
-			return Response.status(status).build();
-		} catch (Exception e) {
-			throw new DlabException("Cannot authorize user " + username + ". " + e.getLocalizedMessage(), e);
-		}
-	}
-
-	/**
-	 * Logout method for the DLab user.
-	 *
-	 * @param userInfo user info.
-	 * @return 200 OK or 403 Forbidden.
-	 */
-	@POST
-	@Path("/logout")
-	public Response userLogout(@Auth UserInfo userInfo) {
-		log.debug("Try logout for accessToken {}", userInfo.getAccessToken());
-		try {
-			envStatusListener.unregisterSession(userInfo);
-			return securityService.post(LOGOUT, userInfo.getAccessToken(), Response.class);
-		} catch (Exception e) {
-			log.error("Try logout for accessToken {}", userInfo.getAccessToken(), e);
-			final Status internalServerError = Status.INTERNAL_SERVER_ERROR;
-			return Response.status(internalServerError)
-					.entity(new ErrorDTO(internalServerError.getStatusCode(), e.getMessage()))
-					.type(MediaType.APPLICATION_JSON)
-					.build();
-		}
-	}
-}
\ No newline at end of file
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/aws/BillingResourceAws.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/aws/BillingResourceAws.java
deleted file mode 100644
index 1d6535d..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/aws/BillingResourceAws.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.resources.aws;
-
-import com.epam.dlab.auth.UserInfo;
-import com.epam.dlab.backendapi.resources.dto.aws.AwsBillingFilter;
-import com.epam.dlab.backendapi.service.BillingService;
-import com.google.inject.Inject;
-import io.dropwizard.auth.Auth;
-import org.bson.Document;
-
-import javax.validation.Valid;
-import javax.validation.constraints.NotNull;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-/**
- * Provides API to get or export billing information.
- */
-@Path("/billing")
-@Consumes(MediaType.APPLICATION_JSON)
-public class BillingResourceAws {
-
-	@Inject
-	private BillingService billingService;
-
-	/**
-	 * Returns the billing report.
-	 *
-	 * @param userInfo user info.
-	 * @param formDTO  filter for report data.
-	 */
-	@POST
-	@Path("/report")
-	@Produces(MediaType.APPLICATION_JSON)
-	@SuppressWarnings("unchecked")
-	public Document getBillingReport(@Auth UserInfo userInfo, @Valid @NotNull AwsBillingFilter formDTO) {
-		return billingService.getBillingReport(userInfo, formDTO);
-	}
-
-	/**
-	 * Returns the billing report in csv file.
-	 *
-	 * @param userInfo user info.
-	 * @param formDTO  filter for report data.
-	 */
-
-	@POST
-	@Path("/report/download")
-	@Produces(MediaType.APPLICATION_OCTET_STREAM)
-	@SuppressWarnings("unchecked")
-	public Response downloadBillingReport(@Auth UserInfo userInfo, @Valid @NotNull AwsBillingFilter formDTO) {
-		return Response.ok(billingService.downloadReport(userInfo, formDTO))
-				.header(HttpHeaders.CONTENT_DISPOSITION,
-						"attachment; filename=\"" + billingService.getReportFileName(userInfo, formDTO) + "\"")
-				.build();
-	}
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/aws/ComputationalResourceAws.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/aws/ComputationalResourceAws.java
index b5551be..d2ed15d 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/aws/ComputationalResourceAws.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/aws/ComputationalResourceAws.java
@@ -52,7 +52,7 @@ import static com.epam.dlab.dto.base.DataEngineType.SPARK_STANDALONE;
 /**
  * Provides the REST API for the computational resource on AWS.
  */
-@Path("/infrastructure_provision/computational_resources")
+@Path("/aws/infrastructure_provision/computational_resources")
 @Consumes(MediaType.APPLICATION_JSON)
 @Produces(MediaType.APPLICATION_JSON)
 @Slf4j
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/azure/BillingResourceAzure.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/azure/BillingResourceAzure.java
deleted file mode 100644
index e9169fd..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/azure/BillingResourceAzure.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.resources.azure;
-
-import com.epam.dlab.auth.UserInfo;
-import com.epam.dlab.backendapi.resources.dto.azure.AzureBillingFilter;
-import com.epam.dlab.backendapi.service.BillingService;
-import com.google.inject.Inject;
-import io.dropwizard.auth.Auth;
-import org.bson.Document;
-
-import javax.validation.Valid;
-import javax.validation.constraints.NotNull;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-/**
- * Provides API to get or export billing information.
- */
-@Path("/billing")
-@Consumes(MediaType.APPLICATION_JSON)
-public class BillingResourceAzure {
-
-    @Inject
-    private BillingService billingService;
-
-    /**
-     * Returns the billing report.
-     *
-     * @param userInfo user info.
-     * @param filter   filter for billing data.
-     */
-    @POST
-    @Path("/report")
-    @Produces(MediaType.APPLICATION_JSON)
-    @SuppressWarnings("unchecked")
-    public Document getBillingReport(@Auth UserInfo userInfo, @Valid @NotNull AzureBillingFilter filter) {
-        return billingService.getBillingReport(userInfo, filter);
-    }
-
-    /**
-     * Returns the billing report in csv file.
-     *
-     * @param userInfo user info.
-     * @param filter   filter for report data.
-     */
-
-    @POST
-    @Path("/report/download")
-    @Produces(MediaType.APPLICATION_OCTET_STREAM)
-    @SuppressWarnings("unchecked")
-    public Response downloadBillingReport(@Auth UserInfo userInfo, @Valid @NotNull AzureBillingFilter filter) {
-        return Response.ok(billingService.downloadReport(userInfo, filter))
-                .header(HttpHeaders.CONTENT_DISPOSITION,
-                        "attachment; filename=\"" + billingService.getReportFileName(userInfo, filter) + "\"")
-                .build();
-    }
-}
\ No newline at end of file
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/azure/ComputationalResourceAzure.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/azure/ComputationalResourceAzure.java
index 6b56386..1ba09d8 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/azure/ComputationalResourceAzure.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/azure/ComputationalResourceAzure.java
@@ -48,7 +48,7 @@ import java.util.List;
 /**
  * Provides the REST API for the computational resource on Azure.
  */
-@Path("/infrastructure_provision/computational_resources")
+@Path("/azure/infrastructure_provision/computational_resources")
 @Consumes(MediaType.APPLICATION_JSON)
 @Produces(MediaType.APPLICATION_JSON)
 @Slf4j
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/ComputationalCallback.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/ComputationalCallback.java
index b2da20c..04ca8fb 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/ComputationalCallback.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/ComputationalCallback.java
@@ -93,11 +93,6 @@ public class ComputationalCallback {
 			log.debug("Waiting for configuration of the computational resource {} for user {}",
 					dto.getComputationalName(), dto.getUser());
 			requestId.put(dto.getUser(), uuid);
-		} else if (UserInstanceStatus.of(dto.getStatus()) == RUNNING && compResource.isReuploadKeyRequired()) {
-			ResourceData resourceData = ResourceData.computationalResource(compResource.getComputationalId(),
-					dto.getExploratoryName(), dto.getComputationalName());
-			UserInfo userInfo = securityService.getUserInfoOffline(dto.getUser());
-			reuploadKeyService.reuploadKeyAction(userInfo, resourceData);
 		}
 		return Response.ok().build();
 	}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/ExploratoryCallback.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/ExploratoryCallback.java
index 62f6435..8e11c0b 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/ExploratoryCallback.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/ExploratoryCallback.java
@@ -19,7 +19,6 @@
 
 package com.epam.dlab.backendapi.resources.callback;
 
-import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.dao.ComputationalDAO;
 import com.epam.dlab.backendapi.dao.ExploratoryDAO;
 import com.epam.dlab.backendapi.domain.RequestId;
@@ -30,7 +29,6 @@ import com.epam.dlab.dto.UserInstanceDTO;
 import com.epam.dlab.dto.UserInstanceStatus;
 import com.epam.dlab.dto.exploratory.ExploratoryStatusDTO;
 import com.epam.dlab.exceptions.DlabException;
-import com.epam.dlab.model.ResourceData;
 import com.epam.dlab.rest.contracts.ApiCallbacks;
 import com.google.inject.Inject;
 import lombok.extern.slf4j.Slf4j;
@@ -103,12 +101,7 @@ public class ExploratoryCallback {
 			throw new DlabException("Could not update status for exploratory environment " + dto.getExploratoryName() +
 					" for user " + dto.getUser() + " to " + dto.getStatus() + ": " + e.getLocalizedMessage(), e);
 		}
-		if (UserInstanceStatus.of(dto.getStatus()) == RUNNING && instance.isReuploadKeyRequired()) {
-			ResourceData resourceData =
-					ResourceData.exploratoryResource(dto.getExploratoryId(), dto.getExploratoryName());
-			UserInfo userInfo = securityService.getUserInfoOffline(dto.getUser());
-			reuploadKeyService.reuploadKeyAction(userInfo, resourceData);
-		}
+
 		return Response.ok().build();
 	}
 
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/aws/EdgeCallbackAws.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/aws/EdgeCallbackAws.java
deleted file mode 100644
index 696e0ed..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/aws/EdgeCallbackAws.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.resources.callback.aws;
-
-import com.epam.dlab.auth.UserInfo;
-import com.epam.dlab.backendapi.domain.RequestId;
-import com.epam.dlab.backendapi.resources.callback.base.EdgeCallback;
-import com.epam.dlab.dto.aws.edge.EdgeInfoAws;
-import com.epam.dlab.dto.base.keyload.UploadFileResult;
-import com.epam.dlab.rest.contracts.ApiCallbacks;
-import com.google.inject.Inject;
-import io.dropwizard.auth.Auth;
-import lombok.extern.slf4j.Slf4j;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-@Path("/infrastructure/edge")
-@Consumes(MediaType.APPLICATION_JSON)
-@Produces(MediaType.APPLICATION_JSON)
-@Slf4j
-public class EdgeCallbackAws extends EdgeCallback {
-
-	@Inject
-	private RequestId requestId;
-
-    public EdgeCallbackAws() {
-        log.info("{} is initialized", getClass().getSimpleName());
-    }
-
-    /**
-     * Stores the result of the upload the user key.
-     *
-     * @param dto result of the upload the user key.
-     * @return 200 OK
-     */
-    @POST
-    @Path(ApiCallbacks.STATUS_URI)
-    public Response status(@Auth UserInfo ui, UploadFileResult<EdgeInfoAws> dto) {
-		requestId.checkAndRemove(dto.getRequestId());
-        handleEdgeCallback(dto.getUser(), dto.getStatus());
-        return Response.ok().build();
-    }
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/aws/KeyUploaderCallbackAws.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/aws/KeyUploaderCallbackAws.java
deleted file mode 100644
index b3561ed..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/aws/KeyUploaderCallbackAws.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.resources.callback.aws;
-
-import com.epam.dlab.backendapi.domain.RequestId;
-import com.epam.dlab.backendapi.resources.callback.base.KeyUploaderCallback;
-import com.epam.dlab.dto.aws.edge.EdgeInfoAws;
-import com.epam.dlab.dto.base.keyload.UploadFileResult;
-import com.google.inject.Inject;
-import lombok.extern.slf4j.Slf4j;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-@Path("/user/access_key")
-@Consumes(MediaType.APPLICATION_JSON)
-@Produces(MediaType.APPLICATION_JSON)
-@Slf4j
-public class KeyUploaderCallbackAws {
-	@Inject
-	private KeyUploaderCallback keyUploaderCallback;
-	@Inject
-	private RequestId requestId;
-
-	public KeyUploaderCallbackAws() {
-		log.info("{} is initialized", getClass().getSimpleName());
-	}
-
-	/**
-	 * Stores the result of the upload the user key.
-	 *
-	 * @param dto result of the upload the user key.
-	 * @return 200 OK
-	 */
-	@POST
-	@Path("/callback")
-	public Response loadKeyResponse(UploadFileResult<EdgeInfoAws> dto) {
-		log.debug("Upload the key result and EDGE node info for user {}: {}", dto.getUser(), dto);
-		requestId.checkAndRemove(dto.getRequestId());
-		keyUploaderCallback.handleCallback(dto.getStatus(), dto.getUser(), dto.getEdgeInfo());
-
-		return Response.ok().build();
-
-	}
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/azure/EdgeCallbackAzure.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/azure/EdgeCallbackAzure.java
deleted file mode 100644
index 0fe97b3..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/azure/EdgeCallbackAzure.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.resources.callback.azure;
-
-import com.epam.dlab.backendapi.domain.RequestId;
-import com.epam.dlab.backendapi.resources.callback.base.EdgeCallback;
-import com.epam.dlab.dto.azure.edge.EdgeInfoAzure;
-import com.epam.dlab.dto.base.keyload.UploadFileResult;
-import com.epam.dlab.rest.contracts.ApiCallbacks;
-import com.google.inject.Inject;
-import lombok.extern.slf4j.Slf4j;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-@Path("/infrastructure/edge")
-@Consumes(MediaType.APPLICATION_JSON)
-@Produces(MediaType.APPLICATION_JSON)
-@Slf4j
-public class EdgeCallbackAzure extends EdgeCallback {
-
-	@Inject
-	private RequestId requestId;
-
-	public EdgeCallbackAzure() {
-		log.info("{} is initialized", getClass().getSimpleName());
-	}
-
-	/**
-	 * Stores the result of the upload the user key.
-	 *
-	 * @param dto result of the upload the user key.
-	 * @return 200 OK
-	 */
-	@POST
-	@Path(ApiCallbacks.STATUS_URI)
-	public Response status(UploadFileResult<EdgeInfoAzure> dto) {
-		requestId.checkAndRemove(dto.getRequestId());
-		handleEdgeCallback(dto.getUser(), dto.getStatus());
-		return Response.ok().build();
-	}
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/azure/KeyUploaderCallbackAzure.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/azure/KeyUploaderCallbackAzure.java
deleted file mode 100644
index b383ce0..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/azure/KeyUploaderCallbackAzure.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.resources.callback.azure;
-
-import com.epam.dlab.auth.UserInfo;
-import com.epam.dlab.backendapi.domain.RequestId;
-import com.epam.dlab.backendapi.resources.callback.base.KeyUploaderCallback;
-import com.epam.dlab.dto.azure.edge.EdgeInfoAzure;
-import com.epam.dlab.dto.base.keyload.UploadFileResult;
-import com.google.inject.Inject;
-import io.dropwizard.auth.Auth;
-import lombok.extern.slf4j.Slf4j;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-@Path("/user/access_key")
-@Consumes(MediaType.APPLICATION_JSON)
-@Produces(MediaType.APPLICATION_JSON)
-@Slf4j
-public class KeyUploaderCallbackAzure {
-
-    @Inject
-    private KeyUploaderCallback keyUploaderCallback;
-
-	@Inject
-	private RequestId requestId;
-
-    public KeyUploaderCallbackAzure() {
-        log.info("{} is initialized", getClass().getSimpleName());
-    }
-
-    /**
-     * Stores the result of the upload the user key.
-     *
-     * @param dto result of the upload the user key.
-     * @return 200 OK
-     */
-    @POST
-    @Path("/callback")
-	public Response loadKeyResponse(UploadFileResult<EdgeInfoAzure> dto) {
-        log.debug("Upload the key result and EDGE node info for user {}: {}", dto.getUser(), dto);
-		requestId.checkAndRemove(dto.getRequestId());
-        keyUploaderCallback.handleCallback(dto.getStatus(), dto.getUser(), dto.getEdgeInfo());
-
-        return Response.ok().build();
-
-    }
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/base/EdgeCallback.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/base/EdgeCallback.java
deleted file mode 100644
index 48ca592..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/base/EdgeCallback.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.resources.callback.base;
-
-import com.epam.dlab.auth.UserInfo;
-import com.epam.dlab.backendapi.dao.KeyDAO;
-import com.epam.dlab.backendapi.service.ExploratoryService;
-import com.epam.dlab.backendapi.service.ReuploadKeyService;
-import com.epam.dlab.backendapi.service.SecurityService;
-import com.epam.dlab.dto.UserInstanceStatus;
-import com.epam.dlab.dto.base.edge.EdgeInfo;
-import com.epam.dlab.exceptions.DlabException;
-import com.epam.dlab.model.ResourceData;
-import com.google.inject.Inject;
-import lombok.extern.slf4j.Slf4j;
-
-import static com.epam.dlab.dto.UserInstanceStatus.RUNNING;
-
-@Slf4j
-public class EdgeCallback {
-	@Inject
-	private KeyDAO keyDAO;
-	@Inject
-	private ExploratoryService exploratoryService;
-	@Inject
-	private SecurityService securityService;
-	@Inject
-	private ReuploadKeyService reuploadKeyService;
-
-	protected EdgeCallback() {
-		log.info("{} is initialized", getClass().getSimpleName());
-	}
-
-	protected void handleEdgeCallback(String user, String status) {
-		EdgeInfo edgeInfo = keyDAO.getEdgeInfo(user);
-		log.debug("Current status of edge node for user {} is {}", user,
-				UserInstanceStatus.of(edgeInfo.getEdgeStatus()));
-
-		try {
-			if (UserInstanceStatus.of(status) == UserInstanceStatus.TERMINATED) {
-				log.debug("Removing key for user {}", user);
-				keyDAO.deleteKey(user);
-				keyDAO.removeEdge(user);
-			}
-			log.debug("Updating the status of EDGE node for user {} to {}", user, status);
-			keyDAO.updateEdgeStatus(user, status);
-
-		} catch (DlabException e) {
-			log.error("Could not update status of EDGE node for user {} to {}", user, status, e);
-			throw new DlabException(String.format("Could not update status of EDGE node to %s: %s",
-					status, e.getLocalizedMessage()), e);
-		}
-		if (UserInstanceStatus.of(status) == RUNNING && edgeInfo.isReuploadKeyRequired()) {
-			ResourceData resourceData = ResourceData.edgeResource(edgeInfo.getInstanceId());
-			UserInfo userInfo = securityService.getUserInfoOffline(user);
-			reuploadKeyService.reuploadKeyAction(userInfo, resourceData);
-		}
-	}
-
-
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/base/KeyUploaderCallback.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/base/KeyUploaderCallback.java
deleted file mode 100644
index 5c6e81d..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/base/KeyUploaderCallback.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.resources.callback.base;
-
-import com.epam.dlab.backendapi.dao.KeyDAO;
-import com.epam.dlab.dto.UserInstanceStatus;
-import com.epam.dlab.dto.base.edge.EdgeInfo;
-import com.epam.dlab.dto.keyload.KeyLoadStatus;
-import com.epam.dlab.exceptions.DlabException;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import lombok.extern.slf4j.Slf4j;
-
-@Singleton
-@Slf4j
-public class KeyUploaderCallback {
-    @Inject
-    private KeyDAO keyDAO;
-
-    public void handleCallback(String status, String user, EdgeInfo edgeInfo) {
-
-        boolean isSuccess = UserInstanceStatus.of(status) == UserInstanceStatus.RUNNING;
-        try {
-            keyDAO.updateKey(user, KeyLoadStatus.getStatus(isSuccess));
-            if (isSuccess) {
-                keyDAO.updateEdgeInfo(user, edgeInfo);
-            } else {
-                UserInstanceStatus instanceStatus = UserInstanceStatus.of(keyDAO.getEdgeStatus(user));
-                if (instanceStatus == null) {
-                    log.debug("Updating the key status for user {} to error", user);
-                    keyDAO.updateKey(user, "error");
-                } else {
-                    keyDAO.updateEdgeStatus(user, status);
-                }
-            }
-        } catch (DlabException e) {
-            log.error("Could not upload the key result and create EDGE node for user {}", user, e);
-            throw new DlabException("Could not upload the key result and create EDGE node for user " + user + ": " + e.getLocalizedMessage(), e);
-        }
-    }
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/gcp/EdgeCallbackGcp.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/gcp/EdgeCallbackGcp.java
deleted file mode 100644
index 57c521f..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/gcp/EdgeCallbackGcp.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.resources.callback.gcp;
-
-import com.epam.dlab.backendapi.domain.RequestId;
-import com.epam.dlab.backendapi.resources.callback.base.EdgeCallback;
-import com.epam.dlab.dto.base.keyload.UploadFileResult;
-import com.epam.dlab.dto.gcp.edge.EdgeInfoGcp;
-import com.epam.dlab.rest.contracts.ApiCallbacks;
-import com.google.inject.Inject;
-import lombok.extern.slf4j.Slf4j;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-@Path("/infrastructure/edge")
-@Consumes(MediaType.APPLICATION_JSON)
-@Produces(MediaType.APPLICATION_JSON)
-@Slf4j
-public class EdgeCallbackGcp extends EdgeCallback {
-
-	@Inject
-	private RequestId requestId;
-
-	public EdgeCallbackGcp() {
-		log.info("{} is initialized", getClass().getSimpleName());
-	}
-
-	/**
-	 * Stores the result of the upload the user key.
-	 *
-	 * @param dto result of the upload the user key.
-	 * @return 200 OK
-	 */
-	@POST
-	@Path(ApiCallbacks.STATUS_URI)
-	public Response status(UploadFileResult<EdgeInfoGcp> dto) {
-		requestId.checkAndRemove(dto.getRequestId());
-		handleEdgeCallback(dto.getUser(), dto.getStatus());
-		return Response.ok().build();
-	}
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/gcp/KeyUploaderCallbackGcp.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/gcp/KeyUploaderCallbackGcp.java
deleted file mode 100644
index 3a2ce34..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/callback/gcp/KeyUploaderCallbackGcp.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.resources.callback.gcp;
-
-import com.epam.dlab.backendapi.domain.RequestId;
-import com.epam.dlab.backendapi.resources.callback.base.KeyUploaderCallback;
-import com.epam.dlab.dto.base.keyload.UploadFileResult;
-import com.epam.dlab.dto.gcp.edge.EdgeInfoGcp;
-import com.google.inject.Inject;
-import lombok.extern.slf4j.Slf4j;
-
-import javax.ws.rs.Consumes;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-@Path("/user/access_key")
-@Consumes(MediaType.APPLICATION_JSON)
-@Produces(MediaType.APPLICATION_JSON)
-@Slf4j
-public class KeyUploaderCallbackGcp {
-
-	@Inject
-	private KeyUploaderCallback keyUploaderCallback;
-
-	@Inject
-	private RequestId requestId;
-
-	public KeyUploaderCallbackGcp() {
-		log.info("{} is initialized", getClass().getSimpleName());
-	}
-
-	/**
-	 * Stores the result of the upload the user key.
-	 *
-	 * @param dto result of the upload the user key.
-	 * @return 200 OK
-	 */
-	@POST
-	@Path("/callback")
-	public Response loadKeyResponse(UploadFileResult<EdgeInfoGcp> dto) {
-		log.debug("Upload the key result and EDGE node info for user {}: {}", dto.getUser(), dto);
-		requestId.checkAndRemove(dto.getRequestId());
-		keyUploaderCallback.handleCallback(dto.getStatus(), dto.getUser(), dto.getEdgeInfo());
-
-		return Response.ok().build();
-
-	}
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/BillingFilter.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/BillingFilter.java
index 60d9c1a..f820169 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/BillingFilter.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/BillingFilter.java
@@ -20,6 +20,7 @@
 package com.epam.dlab.backendapi.resources.dto;
 
 import com.epam.dlab.dto.UserInstanceStatus;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import lombok.Data;
 
@@ -27,7 +28,8 @@ import java.util.Collections;
 import java.util.List;
 
 @Data
-public abstract class BillingFilter {
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class BillingFilter {
 	@JsonProperty
 	protected List<String> user;
 	@JsonProperty("dlab_id")
@@ -40,9 +42,10 @@ public abstract class BillingFilter {
 	protected String dateEnd;
 	@JsonProperty("status")
 	protected List<UserInstanceStatus> statuses = Collections.emptyList();
-
 	@JsonProperty("project")
 	protected List<String> projects;
-
-	public abstract List<String> getShapes();
+	@JsonProperty
+	private List<String> service;
+	@JsonProperty
+	private List<String> shape;
 }
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/ProjectInfrastructureInfo.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/ProjectInfrastructureInfo.java
index 950893e..44837a2 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/ProjectInfrastructureInfo.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/ProjectInfrastructureInfo.java
@@ -19,11 +19,13 @@
 
 package com.epam.dlab.backendapi.resources.dto;
 
+import com.epam.dlab.backendapi.domain.EndpointDTO;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import lombok.AllArgsConstructor;
 import lombok.ToString;
 import org.bson.Document;
 
+import java.util.List;
 import java.util.Map;
 
 @AllArgsConstructor
@@ -37,4 +39,6 @@ public class ProjectInfrastructureInfo {
 	private Map<String, Map<String, String>> shared;
 	@JsonProperty
 	private Iterable<Document> exploratory;
+	@JsonProperty
+	private List<EndpointDTO> endpoints;
 }
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/aws/AwsBillingFilter.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/aws/AwsBillingFilter.java
deleted file mode 100644
index c6cc336..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/aws/AwsBillingFilter.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.resources.dto.aws;
-
-import com.epam.dlab.backendapi.resources.dto.BillingFilter;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import lombok.Data;
-
-import java.util.List;
-
-/**
- * Stores info about billing report filter.
- */
-@Data
-public class AwsBillingFilter extends BillingFilter {
-	@JsonProperty
-	private List<String> product;
-	@JsonProperty
-	private List<String> shape;
-
-
-	@Override
-	public List<String> getShapes() {
-		return shape;
-	}
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/azure/AzureBillingFilter.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/azure/AzureBillingFilter.java
deleted file mode 100644
index cabb762..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/azure/AzureBillingFilter.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.resources.dto.azure;
-
-import com.epam.dlab.backendapi.resources.dto.BillingFilter;
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import lombok.Data;
-
-import java.util.Collections;
-import java.util.List;
-
-@Data
-@JsonIgnoreProperties(ignoreUnknown = true)
-public class AzureBillingFilter extends BillingFilter {
-    @JsonProperty("size")
-    private List<String> nodeSize;
-    private List<String> category = Collections.emptyList();
-
-    @Override
-    public List<String> getShapes() {
-        return nodeSize;
-    }
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/gcp/GcpBillingFilter.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/gcp/GcpBillingFilter.java
deleted file mode 100644
index 3d855f2..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/gcp/GcpBillingFilter.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.resources.dto.gcp;
-
-import com.epam.dlab.backendapi.resources.dto.BillingFilter;
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import lombok.Data;
-
-import java.util.List;
-
-@Data
-@JsonIgnoreProperties(ignoreUnknown = true)
-public class GcpBillingFilter extends BillingFilter {
-
-    @JsonProperty
-    private List<String> shape;
-    @JsonProperty
-    private List<String> product;
-
-    @Override
-    public List<String> getShapes() {
-        return shape;
-    }
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/gcp/ComputationalResourceGcp.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/gcp/ComputationalResourceGcp.java
index ecacf84..43fca4a 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/gcp/ComputationalResourceGcp.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/gcp/ComputationalResourceGcp.java
@@ -50,7 +50,7 @@ import static com.epam.dlab.dto.UserInstanceStatus.CREATING;
 /**
  * Provides the REST API for the computational resource on GCP.
  */
-@Path("/infrastructure_provision/computational_resources")
+@Path("/gcp/infrastructure_provision/computational_resources")
 @Consumes(MediaType.APPLICATION_JSON)
 @Produces(MediaType.APPLICATION_JSON)
 @Slf4j
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/schedulers/endpoint/CheckEndpointStatusScheduler.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/schedulers/endpoint/CheckEndpointStatusScheduler.java
index 658370a..2f34688 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/schedulers/endpoint/CheckEndpointStatusScheduler.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/schedulers/endpoint/CheckEndpointStatusScheduler.java
@@ -49,7 +49,7 @@ public class CheckEndpointStatusScheduler implements Job {
 
     private boolean checkUrl(UserInfo serviceUser, EndpointDTO endpoint) {
         try {
-            endpointService.checkEndpointUrl(serviceUser, endpoint.getUrl());
+            endpointService.checkUrl(serviceUser, endpoint.getUrl());
         } catch (Exception e) {
             return true;
         }
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/AccessKeyService.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/AccessKeyService.java
index 145079e..c037285 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/AccessKeyService.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/AccessKeyService.java
@@ -21,17 +21,8 @@ package com.epam.dlab.backendapi.service;
 
 import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.resources.dto.KeysDTO;
-import com.epam.dlab.dto.keyload.KeyLoadStatus;
 
 public interface AccessKeyService {
 
-	KeyLoadStatus getUserKeyStatus(String user);
-
-	String uploadKey(UserInfo user, String keyContent, boolean isPrimaryUploading);
-
-	String recoverEdge(UserInfo userInfo);
-
-	String generateKey(UserInfo userInfo, boolean createEdge);
-
 	KeysDTO generateKeys(UserInfo userInfo);
 }
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 cced07c..5f79280 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
@@ -34,12 +34,12 @@ import java.text.ParseException;
 import java.util.List;
 
 @Slf4j
-public abstract class BillingService<T extends BillingFilter> {
+public abstract class BillingService {
 
     @Inject
     private BillingDAO billingDAO;
 
-    public Document getReport(UserInfo userInfo, T filter) {
+    public Document getReport(UserInfo userInfo, BillingFilter filter) {
         log.trace("Get billing report for user {} with filter {}", userInfo.getName(), filter);
         try {
             return billingDAO.getReport(userInfo, filter);
@@ -58,12 +58,12 @@ public abstract class BillingService<T extends BillingFilter> {
         return CSVFormatter.formatLine(getHeadersList(full), CSVFormatter.SEPARATOR);
     }
 
-    public Document getBillingReport(UserInfo userInfo, T filter) {
+    public Document getBillingReport(UserInfo userInfo, BillingFilter filter) {
         filter.getUser().replaceAll(s -> s.equalsIgnoreCase(BaseBillingDAO.SHARED_RESOURCE_NAME) ? null : s);
         return getReport(userInfo, filter);
     }
 
-    public byte[] downloadReport(UserInfo userInfo, T filter) {
+    public byte[] downloadReport(UserInfo userInfo, BillingFilter filter) {
         return prepareReport(getReport(userInfo, filter)).getBytes();
     }
 
@@ -97,5 +97,5 @@ public abstract class BillingService<T extends BillingFilter> {
 
     public abstract String getTotal(boolean full, Document document);
 
-    public abstract String getReportFileName(UserInfo userInfo, T filter);
+    public abstract String getReportFileName(UserInfo userInfo, BillingFilter filter);
 }
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/EdgeService.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/EdgeService.java
deleted file mode 100644
index 55661c7..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/EdgeService.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.service;
-
-import com.epam.dlab.auth.UserInfo;
-import com.epam.dlab.dto.UserInstanceStatus;
-
-public interface EdgeService {
-	String start(UserInfo userInfo);
-
-	String stop(UserInfo userInfo);
-
-	String terminate(UserInfo userInfo);
-
-	void updateReuploadKeyFlag(String user, boolean reuploadKeyRequired, UserInstanceStatus... edgeStatuses);
-
-	String getEdgeInfo(UserInfo userInfo, String projectName);
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/EndpointService.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/EndpointService.java
index 456d330..58afa39 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/EndpointService.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/EndpointService.java
@@ -4,6 +4,7 @@ import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.domain.EndpointDTO;
 import com.epam.dlab.backendapi.domain.EndpointResourcesDTO;
 import com.epam.dlab.backendapi.domain.ProjectDTO;
+import com.epam.dlab.cloud.CloudProvider;
 
 import java.util.List;
 
@@ -24,5 +25,5 @@ public interface EndpointService {
 
 	void removeEndpointInAllProjects(UserInfo userInfo, String endpointName, List<ProjectDTO> projects);
 
-    void checkEndpointUrl(UserInfo userInfo, String url);
+    CloudProvider checkUrl(UserInfo userInfo, String url);
 }
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 91d0ed7..5ef7cae 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
@@ -42,14 +42,10 @@ public interface EnvironmentService {
 
 	void stopProjectEnvironment(String project);
 
-	void stopEdge(String user);
-
 	void stopExploratory(UserInfo userInfo, String user, String exploratoryName);
 
 	void stopComputational(UserInfo userInfo, String user, String exploratoryName, String computationalName);
 
-	void terminateEnvironment(UserInfo userInfo, String user);
-
 	void terminateExploratory(UserInfo userInfo, String user, String exploratoryName);
 
 	void terminateComputational(UserInfo userInfo, String user, String exploratoryName, String computationalName);
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/ReuploadKeyService.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/ReuploadKeyService.java
index 88f1e9e..0c2b199 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/ReuploadKeyService.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/ReuploadKeyService.java
@@ -25,9 +25,5 @@ import com.epam.dlab.model.ResourceData;
 
 public interface ReuploadKeyService {
 
-	String reuploadKey(UserInfo user, String keyContent);
-
-	void reuploadKeyAction(UserInfo userInfo, ResourceData resourceData);
-
 	void updateResourceData(ReuploadKeyStatusDTO dto);
 }
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/UserResourceService.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/UserResourceService.java
deleted file mode 100644
index 972e78f..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/UserResourceService.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-
-package com.epam.dlab.backendapi.service;
-
-import com.epam.dlab.dto.UserInstanceDTO;
-import com.epam.dlab.model.ResourceData;
-
-import java.util.List;
-
-public interface UserResourceService {
-
-	List<ResourceData> convertToResourceData(List<UserInstanceDTO> userInstances);
-
-	void updateReuploadKeyFlagForUserResources(String user, boolean reuploadKeyRequired);
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/aws/AwsBillingService.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/aws/AwsBillingService.java
index 14a57a9..eb94ea5 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/aws/AwsBillingService.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/aws/AwsBillingService.java
@@ -21,7 +21,7 @@ package com.epam.dlab.backendapi.service.aws;
 
 import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.dao.aws.AwsBillingDAO;
-import com.epam.dlab.backendapi.resources.dto.aws.AwsBillingFilter;
+import com.epam.dlab.backendapi.resources.dto.BillingFilter;
 import com.epam.dlab.backendapi.service.BillingService;
 import com.epam.dlab.backendapi.util.CSVFormatter;
 import com.epam.dlab.model.aws.ReportLine;
@@ -36,10 +36,10 @@ import java.util.List;
 
 @Slf4j
 @Singleton
-public class AwsBillingService extends BillingService<AwsBillingFilter> {
+public class AwsBillingService extends BillingService {
 
 	@Override
-	public String getReportFileName(UserInfo userInfo, AwsBillingFilter filter) {
+	public String getReportFileName(UserInfo userInfo, BillingFilter filter) {
 		return "aws-billing-report.csv";
 	}
 
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/aws/AwsInfrastructureInfoService.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/aws/AwsInfrastructureInfoService.java
deleted file mode 100644
index 43335cc..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/aws/AwsInfrastructureInfoService.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.service.aws;
-
-import com.epam.dlab.backendapi.service.impl.InfrastructureInfoServiceBase;
-import com.epam.dlab.dto.aws.edge.EdgeInfoAws;
-import com.google.inject.Singleton;
-
-import java.util.HashMap;
-import java.util.Map;
-
-@Singleton
-public class AwsInfrastructureInfoService extends InfrastructureInfoServiceBase<EdgeInfoAws> {
-
-	@Override
-	protected Map<String, String> getSharedInfo(EdgeInfoAws edgeInfo) {
-		Map<String, String> shared = new HashMap<>();
-		shared.put("edge_node_ip", edgeInfo.getPublicIp());
-		shared.put("user_own_bicket_name", edgeInfo.getUserOwnBucketName());
-		shared.put("shared_bucket_name", edgeInfo.getSharedBucketName());
-		return shared;
-	}
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/aws/AwsInfrastructureTemplateService.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/aws/AwsInfrastructureTemplateService.java
deleted file mode 100644
index 62a8f3f..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/aws/AwsInfrastructureTemplateService.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.service.aws;
-
-import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
-import com.epam.dlab.backendapi.resources.dto.aws.AwsEmrConfiguration;
-import com.epam.dlab.backendapi.service.impl.InfrastructureTemplateServiceBase;
-import com.epam.dlab.dto.base.computational.FullComputationalTemplate;
-import com.epam.dlab.dto.imagemetadata.ComputationalMetadataDTO;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.inject.Inject;
-
-public class AwsInfrastructureTemplateService extends InfrastructureTemplateServiceBase {
-
-	@Inject
-	private SelfServiceApplicationConfiguration configuration;
-
-	@Override
-	protected FullComputationalTemplate getCloudFullComputationalTemplate(ComputationalMetadataDTO metadataDTO) {
-		return new AwsFullComputationalTemplate(metadataDTO,
-				AwsEmrConfiguration.builder()
-						.minEmrInstanceCount(configuration.getMinEmrInstanceCount())
-						.maxEmrInstanceCount(configuration.getMaxEmrInstanceCount())
-						.maxEmrSpotInstanceBidPct(configuration.getMaxEmrSpotInstanceBidPct())
-						.minEmrSpotInstanceBidPct(configuration.getMinEmrSpotInstanceBidPct())
-						.build());
-	}
-
-	private class AwsFullComputationalTemplate extends FullComputationalTemplate {
-		@JsonProperty("limits")
-		private AwsEmrConfiguration awsEmrConfiguration;
-
-		AwsFullComputationalTemplate(ComputationalMetadataDTO metadataDTO,
-									 AwsEmrConfiguration awsEmrConfiguration) {
-			super(metadataDTO);
-			this.awsEmrConfiguration = awsEmrConfiguration;
-		}
-	}
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/azure/AzureBillingService.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/azure/AzureBillingService.java
index 5b329be..9ff33a8 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/azure/AzureBillingService.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/azure/AzureBillingService.java
@@ -24,7 +24,7 @@ import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.dao.BaseBillingDAO;
 import com.epam.dlab.backendapi.dao.BillingDAO;
 import com.epam.dlab.backendapi.dao.azure.AzureBillingDAO;
-import com.epam.dlab.backendapi.resources.dto.azure.AzureBillingFilter;
+import com.epam.dlab.backendapi.resources.dto.BillingFilter;
 import com.epam.dlab.backendapi.service.BillingService;
 import com.epam.dlab.backendapi.util.CSVFormatter;
 import com.epam.dlab.model.aws.ReportLine;
@@ -40,13 +40,13 @@ import java.util.List;
 
 @Slf4j
 @Singleton
-public class AzureBillingService extends BillingService<AzureBillingFilter> {
+public class AzureBillingService extends BillingService {
 
     @Inject
     private BillingDAO billingDAO;
 
     @Override
-    public String getReportFileName(UserInfo userInfo, AzureBillingFilter filter) {
+    public String getReportFileName(UserInfo userInfo, BillingFilter filter) {
         return "azure-billing-report.csv";
     }
 
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/azure/AzureInfrastructureInfoService.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/azure/AzureInfrastructureInfoService.java
deleted file mode 100644
index 6338152..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/azure/AzureInfrastructureInfoService.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.service.azure;
-
-import com.epam.dlab.backendapi.service.impl.InfrastructureInfoServiceBase;
-import com.epam.dlab.dto.azure.edge.EdgeInfoAzure;
-import com.google.inject.Singleton;
-
-import java.util.HashMap;
-import java.util.Map;
-
-@Singleton
-public class AzureInfrastructureInfoService extends InfrastructureInfoServiceBase<EdgeInfoAzure> {
-
-	@Override
-	protected Map<String, String> getSharedInfo(EdgeInfoAzure edgeInfo) {
-		Map<String, String> shared = new HashMap<>();
-		shared.put("edge_node_ip", edgeInfo.getPublicIp());
-		shared.put("user_container_name", edgeInfo.getUserContainerName());
-		shared.put("shared_container_name", edgeInfo.getSharedContainerName());
-		shared.put("user_storage_account_name", edgeInfo.getUserStorageAccountName());
-		shared.put("shared_storage_account_name", edgeInfo.getSharedStorageAccountName());
-		shared.put("datalake_name", edgeInfo.getDataLakeName());
-		shared.put("datalake_user_directory_name", edgeInfo.getDataLakeDirectoryName());
-		shared.put("datalake_shared_directory_name", edgeInfo.getDataLakeSharedDirectoryName());
-		return shared;
-	}
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/azure/AzureInfrastructureTemplateService.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/azure/AzureInfrastructureTemplateService.java
deleted file mode 100644
index 595ae2e..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/azure/AzureInfrastructureTemplateService.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.service.azure;
-
-import com.epam.dlab.backendapi.service.impl.InfrastructureTemplateServiceBase;
-import com.epam.dlab.dto.base.computational.FullComputationalTemplate;
-import com.epam.dlab.dto.imagemetadata.ComputationalMetadataDTO;
-import com.google.inject.Singleton;
-import lombok.extern.slf4j.Slf4j;
-
-@Singleton
-@Slf4j
-public class AzureInfrastructureTemplateService extends InfrastructureTemplateServiceBase {
-
-	@Override
-	protected FullComputationalTemplate getCloudFullComputationalTemplate(ComputationalMetadataDTO metadataDTO) {
-		log.error("Operation is not supported currently");
-		throw new UnsupportedOperationException("Operation is not supported currently");
-	}
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/gcp/GcpBillingService.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/gcp/GcpBillingService.java
index 4b89e4b..a7599f7 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/gcp/GcpBillingService.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/gcp/GcpBillingService.java
@@ -21,7 +21,7 @@ package com.epam.dlab.backendapi.service.gcp;
 
 import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.dao.aws.AwsBillingDAO;
-import com.epam.dlab.backendapi.resources.dto.gcp.GcpBillingFilter;
+import com.epam.dlab.backendapi.resources.dto.BillingFilter;
 import com.epam.dlab.backendapi.service.BillingService;
 import com.epam.dlab.backendapi.util.CSVFormatter;
 import com.epam.dlab.model.aws.ReportLine;
@@ -32,7 +32,7 @@ import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.List;
 
-public class GcpBillingService extends BillingService<GcpBillingFilter> {
+public class GcpBillingService extends BillingService {
     @Override
     public String getFirstLine(Document document) throws ParseException {
         SimpleDateFormat from = new SimpleDateFormat("yyyy-MM-dd");
@@ -98,7 +98,7 @@ public class GcpBillingService extends BillingService<GcpBillingFilter> {
     }
 
     @Override
-    public String getReportFileName(UserInfo userInfo, GcpBillingFilter filter) {
+    public String getReportFileName(UserInfo userInfo, BillingFilter filter) {
         return "gcp-billing-report.csv";
     }
 }
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/gcp/GcpInfrastructureInfoService.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/gcp/GcpInfrastructureInfoService.java
deleted file mode 100644
index c517486..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/gcp/GcpInfrastructureInfoService.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.service.gcp;
-
-import com.epam.dlab.backendapi.service.impl.InfrastructureInfoServiceBase;
-import com.epam.dlab.dto.gcp.edge.EdgeInfoGcp;
-import com.google.inject.Singleton;
-
-import java.util.HashMap;
-import java.util.Map;
-
-@Singleton
-public class GcpInfrastructureInfoService extends InfrastructureInfoServiceBase<EdgeInfoGcp> {
-
-	@Override
-	protected Map<String, String> getSharedInfo(EdgeInfoGcp edgeInfo) {
-		Map<String, String> shared = new HashMap<>();
-		shared.put("edge_node_ip", edgeInfo.getPublicIp());
-		shared.put("user_own_bucket_name", edgeInfo.getUserOwnBucketName());
-		shared.put("shared_bucket_name", edgeInfo.getSharedBucketName());
-		return shared;
-	}
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/gcp/GcpInfrastructureTemplateService.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/gcp/GcpInfrastructureTemplateService.java
deleted file mode 100644
index 314698d..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/gcp/GcpInfrastructureTemplateService.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.service.gcp;
-
-import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
-import com.epam.dlab.backendapi.resources.dto.gcp.GcpDataprocConfiguration;
-import com.epam.dlab.backendapi.service.impl.InfrastructureTemplateServiceBase;
-import com.epam.dlab.dto.base.computational.FullComputationalTemplate;
-import com.epam.dlab.dto.imagemetadata.ComputationalMetadataDTO;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.inject.Inject;
-
-public class GcpInfrastructureTemplateService extends InfrastructureTemplateServiceBase {
-	@Inject
-	private SelfServiceApplicationConfiguration configuration;
-
-	@Override
-	protected FullComputationalTemplate getCloudFullComputationalTemplate(ComputationalMetadataDTO metadataDTO) {
-		return new GcpFullComputationalTemplate(metadataDTO,
-				GcpDataprocConfiguration.builder()
-						.minInstanceCount(configuration.getMinInstanceCount())
-						.maxInstanceCount(configuration.getMaxInstanceCount())
-						.minDataprocPreemptibleInstanceCount(configuration.getMinDataprocPreemptibleCount())
-						.build());
-	}
-
-
-	private class GcpFullComputationalTemplate extends FullComputationalTemplate {
-		@JsonProperty("limits")
-		private GcpDataprocConfiguration gcpDataprocConfiguration;
-
-		GcpFullComputationalTemplate(ComputationalMetadataDTO metadataDTO,
-									 GcpDataprocConfiguration gcpDataprocConfiguration) {
-			super(metadataDTO);
-			this.gcpDataprocConfiguration = gcpDataprocConfiguration;
-		}
-	}
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/AccessKeyServiceImpl.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/AccessKeyServiceImpl.java
index 193e28a..11c8ef4 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/AccessKeyServiceImpl.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/AccessKeyServiceImpl.java
@@ -21,23 +21,11 @@ package com.epam.dlab.backendapi.service.impl;
 
 import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
-import com.epam.dlab.backendapi.annotation.BudgetLimited;
-import com.epam.dlab.backendapi.dao.KeyDAO;
-import com.epam.dlab.backendapi.domain.RequestId;
 import com.epam.dlab.backendapi.resources.dto.KeysDTO;
 import com.epam.dlab.backendapi.service.AccessKeyService;
-import com.epam.dlab.backendapi.service.ReuploadKeyService;
-import com.epam.dlab.backendapi.util.RequestBuilder;
-import com.epam.dlab.dto.UserInstanceStatus;
-import com.epam.dlab.dto.base.edge.EdgeInfo;
-import com.epam.dlab.dto.base.keyload.UploadFile;
-import com.epam.dlab.dto.keyload.KeyLoadStatus;
-import com.epam.dlab.dto.keyload.UserKeyDTO;
 import com.epam.dlab.exceptions.DlabException;
-import com.epam.dlab.rest.client.RESTService;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
-import com.google.inject.name.Named;
 import com.jcraft.jsch.JSch;
 import com.jcraft.jsch.JSchException;
 import com.jcraft.jsch.KeyPair;
@@ -46,90 +34,12 @@ import lombok.extern.slf4j.Slf4j;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 
-import static com.epam.dlab.constants.ServiceConsts.PROVISIONING_SERVICE_NAME;
-import static com.epam.dlab.dto.UserInstanceStatus.FAILED;
-import static com.epam.dlab.dto.UserInstanceStatus.TERMINATED;
-import static com.epam.dlab.rest.contracts.EdgeAPI.EDGE_CREATE;
-
 @Singleton
 @Slf4j
 public class AccessKeyServiceImpl implements AccessKeyService {
-
-	@Inject
-	private KeyDAO keyDAO;
-	@Inject
-	@Named(PROVISIONING_SERVICE_NAME)
-	private RESTService provisioningService;
-	@Inject
-	private RequestBuilder requestBuilder;
-	@Inject
-	private RequestId requestId;
 	@Inject
 	private SelfServiceApplicationConfiguration configuration;
-	@Inject
-	private ReuploadKeyService reuploadKeyService;
-
-	@Override
-	public KeyLoadStatus getUserKeyStatus(String user) {
-		log.debug("Check the status of the user key for {}", user);
-		try {
-			return keyDAO.findKeyStatus(user);
-		} catch (DlabException e) {
-			log.error("Check the status of the user key for {} fails", user, e);
-			return KeyLoadStatus.ERROR;
-		}
-	}
-
-	@BudgetLimited
-	@Override
-	public String uploadKey(UserInfo user, String keyContent, boolean isPrimaryUploading) {
-		log.debug(isPrimaryUploading ? "The key uploading and EDGE node creating for user {} is starting..." :
-				"The key reuploading for user {} is starting...", user);
-		keyDAO.upsertKey(user.getName(), keyContent, isPrimaryUploading);
-		try {
-			return isPrimaryUploading ? createEdge(user, keyContent) : reuploadKeyService.reuploadKey(user,
-					keyContent);
-		} catch (Exception e) {
-			log.error(isPrimaryUploading ? "The key uploading and EDGE node creating for user {} fails" :
-					"The key reuploading for user {} fails", user.getName(), e);
-			keyDAO.deleteKey(user.getName());
-			throw new DlabException(isPrimaryUploading ? "Could not upload the key and create EDGE node: " :
-					"Could not reupload the key. Previous key has been deleted: " + e.getLocalizedMessage(), e);
-		}
-	}
 
-	@BudgetLimited
-	@Override
-	public String recoverEdge(UserInfo userInfo) {
-		log.debug("Recreating edge node for user {}", userInfo.getName());
-		try {
-			String userName = userInfo.getName();
-			EdgeInfo edgeInfo = getEdgeInfo(userName);
-			UserKeyDTO key = keyDAO.fetchKey(userName, KeyLoadStatus.SUCCESS);
-			updateEdgeStatusToCreating(userName, edgeInfo);
-			return createEdge(userInfo, key.getContent());
-		} catch (Exception e) {
-			log.error("Could not create the EDGE node for user {}", userInfo.getName(), e);
-			keyDAO.updateEdgeStatus(userInfo.getName(), FAILED.toString());
-			throw new DlabException("Could not upload the key and create EDGE node: " + e.getLocalizedMessage(), e);
-		}
-	}
-
-	@Override
-	public String generateKey(UserInfo userInfo, boolean createEdge) {
-		log.debug("Generating new key pair for user {}", userInfo.getName());
-		try (ByteArrayOutputStream publicKeyOut = new ByteArrayOutputStream();
-			 ByteArrayOutputStream privateKeyOut = new ByteArrayOutputStream()) {
-			KeyPair pair = KeyPair.genKeyPair(new JSch(), KeyPair.RSA, configuration.getPrivateKeySize());
-			pair.writePublicKey(publicKeyOut, userInfo.getName());
-			pair.writePrivateKey(privateKeyOut);
-			uploadKey(userInfo, new String(publicKeyOut.toByteArray()), createEdge);
-			return new String(privateKeyOut.toByteArray());
-		} catch (JSchException | IOException e) {
-			log.error("Can not generate private/public key pair due to: {}", e.getMessage());
-			throw new DlabException("Can not generate private/public key pair due to: " + e.getMessage(), e);
-		}
-	}
 
 	@Override
 	public KeysDTO generateKeys(UserInfo userInfo) {
@@ -146,33 +56,4 @@ public class AccessKeyServiceImpl implements AccessKeyService {
 			throw new DlabException("Can not generate private/public key pair due to: " + e.getMessage(), e);
 		}
 	}
-
-	private EdgeInfo getEdgeInfo(String userName) {
-		EdgeInfo edgeInfo = keyDAO.getEdgeInfo(userName);
-		UserInstanceStatus status = UserInstanceStatus.of(edgeInfo.getEdgeStatus());
-		if (status == null || !status.in(FAILED, TERMINATED)) {
-			log.error("Could not create EDGE node for user {} because the status of instance is {}", userName,
-					status);
-			throw new DlabException("Could not create EDGE node because the status of instance is " + status);
-		}
-		return edgeInfo;
-	}
-
-	private void updateEdgeStatusToCreating(String userName, EdgeInfo edgeInfo) {
-		edgeInfo.setInstanceId(null);
-		edgeInfo.setEdgeStatus(UserInstanceStatus.CREATING.toString());
-		try {
-			keyDAO.updateEdgeInfo(userName, edgeInfo);
-		} catch (DlabException e) {
-			log.error("Could not update the status of EDGE node for user {}", userName, e);
-			throw new DlabException("Could not create EDGE node: " + e.getLocalizedMessage(), e);
-		}
-	}
-
-	private String createEdge(UserInfo user, String keyContent) {
-		UploadFile uploadFile = requestBuilder.newEdgeKeyUpload(user, keyContent);
-		String uuid = provisioningService.post(EDGE_CREATE, user.getAccessToken(), uploadFile, String.class);
-		requestId.put(user.getName(), uuid);
-		return uuid;
-	}
 }
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 ab26b7c..52decf8 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
@@ -25,6 +25,7 @@ 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.EndpointDTO;
 import com.epam.dlab.backendapi.domain.ProjectDTO;
 import com.epam.dlab.backendapi.domain.RequestId;
 import com.epam.dlab.backendapi.resources.dto.ComputationalCreateFormDTO;
@@ -108,11 +109,11 @@ public class ComputationalServiceImpl implements ComputationalService {
 				form.getCustomTag()));
 		if (computationalDAO.addComputational(userInfo.getName(), form.getNotebookName(), compResource)) {
 			try {
-				ComputationalBase<?> dto = requestBuilder.newComputationalCreate(userInfo, projectDTO, instance, form);
+				EndpointDTO endpointDTO = endpointService.get(instance.getEndpoint());
+				ComputationalBase<?> dto = requestBuilder.newComputationalCreate(userInfo, projectDTO, instance, form, endpointDTO);
 
 				String uuid =
-						provisioningService.post(endpointService.get(instance.getEndpoint()).getUrl() +
-										ComputationalAPI.COMPUTATIONAL_CREATE_SPARK,
+						provisioningService.post(endpointDTO.getUrl() + ComputationalAPI.COMPUTATIONAL_CREATE_SPARK,
 								userInfo.getAccessToken(), dto, String.class);
 				requestId.put(userInfo.getName(), uuid);
 				return true;
@@ -143,12 +144,13 @@ public class ComputationalServiceImpl implements ComputationalService {
 					.getName(), exploratoryName, computationalName);
 
 			final DataEngineType dataEngineType = compResource.getDataEngineType();
-			ComputationalTerminateDTO dto = requestBuilder.newComputationalTerminate(userInfo, userInstanceDTO, compResource);
+			EndpointDTO endpointDTO = endpointService.get(userInstanceDTO.getEndpoint());
+			ComputationalTerminateDTO dto = requestBuilder.newComputationalTerminate(userInfo, userInstanceDTO, compResource, endpointDTO);
 
 			final String provisioningUrl = Optional.ofNullable(DATA_ENGINE_TYPE_TERMINATE_URLS.get(dataEngineType))
 					.orElseThrow(UnsupportedOperationException::new);
 			String uuid =
-					provisioningService.post(endpointService.get(userInstanceDTO.getEndpoint()).getUrl() + provisioningUrl,
+					provisioningService.post(endpointDTO.getUrl() + provisioningUrl,
 							userInfo.getAccessToken(), dto, String.class);
 			requestId.put(userInfo.getName(), uuid);
 		} catch (RuntimeException re) {
@@ -179,10 +181,11 @@ public class ComputationalServiceImpl implements ComputationalService {
 
 		if (isAdded) {
 			try {
+				EndpointDTO endpointDTO = endpointService.get(instance.getEndpoint());
 				String uuid =
-						provisioningService.post(endpointService.get(instance.getEndpoint()).getUrl() +
-										COMPUTATIONAL_CREATE_CLOUD_SPECIFIC, userInfo.getAccessToken(),
-								requestBuilder.newComputationalCreate(userInfo, projectDTO, instance, formDTO),
+						provisioningService.post(endpointDTO.getUrl() + COMPUTATIONAL_CREATE_CLOUD_SPECIFIC,
+								userInfo.getAccessToken(),
+								requestBuilder.newComputationalCreate(userInfo, projectDTO, instance, formDTO, endpointDTO),
 								String.class);
 				requestId.put(userInfo.getName(), uuid);
 				return true;
@@ -209,10 +212,12 @@ public class ComputationalServiceImpl implements ComputationalService {
 		if (computationalWithStatusResourceExist(compName, userInstance, requiredStatus)) {
 			log.debug("{} spark cluster {} for userInstance {}", STOPPING.toString(), compName, expName);
 			updateComputationalStatus(userInfo.getName(), expName, compName, STOPPING);
+			EndpointDTO endpointDTO = endpointService.get(userInstance.getEndpoint());
 			final String uuid =
-					provisioningService.post(endpointService.get(userInstance.getEndpoint()).getUrl() + ComputationalAPI.COMPUTATIONAL_STOP_SPARK,
+					provisioningService.post(endpointDTO.getUrl() + ComputationalAPI.COMPUTATIONAL_STOP_SPARK,
 							userInfo.getAccessToken(),
-							requestBuilder.newComputationalStop(userInfo, userInstance, compName), String.class);
+							requestBuilder.newComputationalStop(userInfo, userInstance, compName, endpointDTO),
+							String.class);
 			requestId.put(userInfo.getName(), uuid);
 		} else {
 			throw new IllegalStateException(String.format(DATAENGINE_NOT_PRESENT_FORMAT,
@@ -230,10 +235,12 @@ public class ComputationalServiceImpl implements ComputationalService {
 		if (computationalWithStatusResourceExist(compName, userInstance, requiredStatus)) {
 			log.debug("{} spark cluster {} for userInstance {}", STARTING.toString(), compName, expName);
 			updateComputationalStatus(userInfo.getName(), expName, compName, STARTING);
+			EndpointDTO endpointDTO = endpointService.get(userInstance.getEndpoint());
 			final String uuid =
-					provisioningService.post(endpointService.get(userInstance.getEndpoint()).getUrl() + ComputationalAPI.COMPUTATIONAL_START_SPARK,
-							userInfo.getAccessToken(), requestBuilder.newComputationalStart(userInfo, userInstance,
-									compName), String.class);
+					provisioningService.post(endpointDTO.getUrl() + ComputationalAPI.COMPUTATIONAL_START_SPARK,
+							userInfo.getAccessToken(),
+							requestBuilder.newComputationalStart(userInfo, userInstance, compName, endpointDTO),
+							String.class);
 			requestId.put(userInfo.getName(), uuid);
 		} else {
 			throw new IllegalStateException(String.format(DATAENGINE_NOT_PRESENT_FORMAT,
@@ -255,11 +262,12 @@ public class ComputationalServiceImpl implements ComputationalService {
 				.findAny()
 				.orElseThrow(() -> new ResourceNotFoundException(String.format(RUNNING_COMP_RES_NOT_FOUND,
 						computationalName, exploratoryName)));
+		EndpointDTO endpointDTO = endpointService.get(userInstanceDTO.getEndpoint());
 		final ComputationalClusterConfigDTO clusterConfigDto = requestBuilder.newClusterConfigUpdate(userInfo,
-				userInstanceDTO, compResource, config);
+				userInstanceDTO, compResource, config, endpointDTO);
 		final String uuid =
-				provisioningService.post(endpointService.get(userInstanceDTO.getEndpoint()).getUrl() + ComputationalAPI.COMPUTATIONAL_RECONFIGURE_SPARK, token,
-						clusterConfigDto, String.class);
+				provisioningService.post(endpointDTO.getUrl() + ComputationalAPI.COMPUTATIONAL_RECONFIGURE_SPARK,
+						token, clusterConfigDto, String.class);
 		computationalDAO.updateComputationalFields(new ComputationalStatusDTO()
 				.withComputationalName(computationalName)
 				.withExploratoryName(exploratoryName)
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/EdgeServiceImpl.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/EdgeServiceImpl.java
deleted file mode 100644
index e62b52f..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/EdgeServiceImpl.java
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.service.impl;
-
-import com.epam.dlab.auth.UserInfo;
-import com.epam.dlab.backendapi.annotation.BudgetLimited;
-import com.epam.dlab.backendapi.dao.KeyDAO;
-import com.epam.dlab.backendapi.dao.ProjectDAO;
-import com.epam.dlab.backendapi.domain.RequestId;
-import com.epam.dlab.backendapi.service.EdgeService;
-import com.epam.dlab.backendapi.util.RequestBuilder;
-import com.epam.dlab.constants.ServiceConsts;
-import com.epam.dlab.dto.ResourceSysBaseDTO;
-import com.epam.dlab.dto.UserInstanceStatus;
-import com.epam.dlab.exceptions.DlabException;
-import com.epam.dlab.rest.client.RESTService;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import com.google.inject.name.Named;
-import lombok.extern.slf4j.Slf4j;
-
-import static com.epam.dlab.dto.UserInstanceStatus.*;
-import static com.epam.dlab.rest.contracts.EdgeAPI.*;
-
-@Singleton
-@Slf4j
-public class EdgeServiceImpl implements EdgeService {
-
-	@Inject
-	private KeyDAO keyDAO;
-	@Inject
-	private ProjectDAO projectDAO;
-
-	@Inject
-	@Named(ServiceConsts.PROVISIONING_SERVICE_NAME)
-	private RESTService provisioningService;
-
-	@Inject
-	private RequestBuilder requestBuilder;
-
-	@Inject
-	private RequestId requestId;
-
-
-	@BudgetLimited
-	@Override
-	public String start(UserInfo userInfo) {
-		log.debug("Starting EDGE node for user {}", userInfo.getName());
-		UserInstanceStatus status = UserInstanceStatus.of(keyDAO.getEdgeStatus(userInfo.getName()));
-		if (status == null || !status.in(STOPPED)) {
-			log.error("Could not start EDGE node for user {} because the status of instance is {}",
-					userInfo.getName(), status);
-			throw new DlabException("Could not start EDGE node because the status of instance is " + status);
-		}
-		try {
-			return action(userInfo, EDGE_START, STARTING);
-		} catch (DlabException e) {
-			log.error("Could not start EDGE node for user {}", userInfo.getName(), e);
-			throw new DlabException("Could not start EDGE node: " + e.getLocalizedMessage(), e);
-		}
-	}
-
-	@Override
-	public String stop(UserInfo userInfo) {
-		log.debug("Stopping EDGE node for user {}", userInfo.getName());
-		UserInstanceStatus status = UserInstanceStatus.of(keyDAO.getEdgeStatus(userInfo.getName()));
-		if (status == null || !status.in(RUNNING)) {
-			log.error("Could not stop EDGE node for user {} because the status of instance is {}",
-					userInfo.getName(), status);
-			throw new DlabException("Could not stop EDGE node because the status of instance is " + status);
-		}
-
-		try {
-			return action(userInfo, EDGE_STOP, STOPPING);
-		} catch (DlabException e) {
-			log.error("Could not stop EDGE node for user {}", userInfo.getName(), e);
-			throw new DlabException("Could not stop EDGE node: " + e.getLocalizedMessage(), e);
-		}
-	}
-
-	@Override
-	public String terminate(UserInfo userInfo) {
-		log.debug("Terminating EDGE node for user {}", userInfo.getName());
-		UserInstanceStatus status = UserInstanceStatus.of(keyDAO.getEdgeStatus(userInfo.getName()));
-		if (status == null) {
-			log.error("Could not terminate EDGE node for user {} because the status of instance is null",
-					userInfo.getName());
-			throw new DlabException("Could not terminate EDGE node because the status of instance is null");
-		}
-
-		try {
-			return action(userInfo, EDGE_TERMINATE, TERMINATING);
-		} catch (DlabException e) {
-			log.error("Could not terminate EDGE node for user {}", userInfo.getName(), e);
-			throw new DlabException("Could not terminate EDGE node: " + e.getLocalizedMessage(), e);
-		}
-	}
-
-	/**
-	 * Updates parameter 'reuploadKeyRequired' for user's edge node with allowable statuses.
-	 *
-	 * @param user                user.
-	 * @param reuploadKeyRequired true/false.
-	 * @param edgeStatuses        allowable statuses of edge node.
-	 */
-	@Override
-	public void updateReuploadKeyFlag(String user, boolean reuploadKeyRequired, UserInstanceStatus... edgeStatuses) {
-		keyDAO.updateEdgeReuploadKey(user, reuploadKeyRequired, edgeStatuses);
-	}
-
-	@Override
-	public String getEdgeInfo(UserInfo userInfo, String projectName) {
-		return null;
-	}
-
-	/**
-	 * Sends the post request to the provisioning service and update the status of EDGE node.
-	 *
-	 * @param userInfo user info.
-	 * @param action   action for EDGE node.
-	 * @param status   status of EDGE node.
-	 * @return Request Id.
-	 */
-	private String action(UserInfo userInfo, String action, UserInstanceStatus status) {
-		try {
-			keyDAO.updateEdgeStatus(userInfo.getName(), status.toString());
-			ResourceSysBaseDTO<?> dto = requestBuilder.newEdgeAction(userInfo);
-			String uuid = provisioningService.post(action, userInfo.getAccessToken(), dto, String.class);
-			requestId.put(userInfo.getName(), uuid);
-			return uuid;
-		} catch (Exception t) {
-			keyDAO.updateEdgeStatus(userInfo.getName(), FAILED.toString());
-			throw new DlabException("Could not " + action + " EDGE node " + ": " + t.getLocalizedMessage(), t);
-		}
-	}
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/EndpointServiceImpl.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/EndpointServiceImpl.java
index 169857d..a8e1177 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/EndpointServiceImpl.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/EndpointServiceImpl.java
@@ -3,11 +3,13 @@ package com.epam.dlab.backendapi.service.impl;
 import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.dao.EndpointDAO;
 import com.epam.dlab.backendapi.dao.ExploratoryDAO;
+import com.epam.dlab.backendapi.dao.UserRoleDao;
 import com.epam.dlab.backendapi.domain.EndpointDTO;
 import com.epam.dlab.backendapi.domain.EndpointResourcesDTO;
 import com.epam.dlab.backendapi.domain.ProjectDTO;
 import com.epam.dlab.backendapi.service.EndpointService;
 import com.epam.dlab.backendapi.service.ProjectService;
+import com.epam.dlab.cloud.CloudProvider;
 import com.epam.dlab.constants.ServiceConsts;
 import com.epam.dlab.dto.UserInstanceDTO;
 import com.epam.dlab.dto.UserInstanceStatus;
@@ -23,23 +25,29 @@ import javax.ws.rs.core.Response;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
 
 @Slf4j
 public class EndpointServiceImpl implements EndpointService {
-	private static final String HEALTHCHECK = "healthcheck";
+	private static final String HEALTH_CHECK = "healthcheck";
 	private final EndpointDAO endpointDAO;
 	private final ProjectService projectService;
 	private final ExploratoryDAO exploratoryDAO;
 	private final RESTService provisioningService;
+	private final UserRoleDao userRoleDao;
 
 	@Inject
 	public EndpointServiceImpl(EndpointDAO endpointDAO, ProjectService projectService, ExploratoryDAO exploratoryDAO,
-							   @Named(ServiceConsts.PROVISIONING_SERVICE_NAME) RESTService provisioningService) {
+							   @Named(ServiceConsts.PROVISIONING_SERVICE_NAME) RESTService provisioningService,
+							   UserRoleDao userRoleDao) {
 
 		this.endpointDAO = endpointDAO;
 		this.projectService = projectService;
 		this.exploratoryDAO = exploratoryDAO;
 		this.provisioningService = provisioningService;
+		this.userRoleDao = userRoleDao;
 	}
 
 	@Override
@@ -70,9 +78,14 @@ public class EndpointServiceImpl implements EndpointService {
 
 	@Override
 	public void create(UserInfo userInfo, EndpointDTO endpointDTO) {
-		checkEndpointUrl(userInfo, endpointDTO.getUrl());
+		CloudProvider cloudProvider = checkUrl(userInfo, endpointDTO.getUrl());
 		if (!endpointDAO.get(endpointDTO.getName()).isPresent()) {
-			endpointDAO.create(EndpointDTO.withEndpointStatus(endpointDTO));
+			if (!Objects.nonNull(cloudProvider)) {
+				throw new DlabException("CloudProvider cannot be null");
+			}
+			endpointDAO.create(new EndpointDTO(endpointDTO.getName(), endpointDTO.getUrl(), endpointDTO.getAccount(),
+					endpointDTO.getTag(), EndpointDTO.EndpointStatus.ACTIVE, cloudProvider));
+			userRoleDao.updateMissingRoles(cloudProvider);
 		} else {
 			throw new ResourceConflictException("Endpoint with passed name already exist in system");
 		}
@@ -85,13 +98,20 @@ public class EndpointServiceImpl implements EndpointService {
 
 	@Override
 	public void remove(UserInfo userInfo, String name, boolean withResources) {
+		Optional<EndpointDTO> endpointDTO = endpointDAO.get(name);
+		endpointDTO.orElseThrow(() -> new ResourceNotFoundException(String.format("Endpoint %s does not exist", name)));
 		List<ProjectDTO> projects = projectService.getProjectsByEndpoint(name);
 		checkProjectEndpointResourcesStatuses(projects, name);
 
 		if (withResources) {
 			removeEndpointInAllProjects(userInfo, name, projects);
 		}
+		CloudProvider cloudProvider = endpointDTO.get().getCloudProvider();
 		endpointDAO.remove(name);
+		List<CloudProvider> remainingProviders = endpointDAO.getEndpoints().stream()
+				.map(EndpointDTO::getCloudProvider)
+				.collect(Collectors.toList());
+		userRoleDao.removeUnnecessaryRoles(cloudProvider, remainingProviders);
 	}
 
 	@Override
@@ -100,18 +120,21 @@ public class EndpointServiceImpl implements EndpointService {
 	}
 
 	@Override
-	public void checkEndpointUrl(UserInfo userInfo, String url) {
+	public CloudProvider checkUrl(UserInfo userInfo, String url) {
 		Response response;
+		CloudProvider cloudProvider;
 		try {
-			response = provisioningService.get(url + HEALTHCHECK, userInfo.getAccessToken(), Response.class);
+			response = provisioningService.get(url + HEALTH_CHECK, userInfo.getAccessToken(), Response.class);
+			cloudProvider = response.readEntity(CloudProvider.class);
 		} catch (Exception e) {
-			log.error("Cannot connect to url \'{}\'", url);
-			throw new DlabException(String.format("Cannot connect to url \'%s\'", url), e);
+			log.error("Cannot connect to url '{}'", url);
+			throw new DlabException(String.format("Cannot connect to url '%s'", url), e);
 		}
 		if (response.getStatus() != 200) {
 			log.warn("Endpoint url {} is not valid", url);
-			throw new ResourceNotFoundException(String.format("Endpoint url \'%s\' is not valid", url));
+			throw new ResourceNotFoundException(String.format("Endpoint url '%s' is not valid", url));
 		}
+		return cloudProvider;
 	}
 
 	private void checkProjectEndpointResourcesStatuses(List<ProjectDTO> projects, String endpoint) {
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 1d70935..349dfdb 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
@@ -22,7 +22,6 @@ package com.epam.dlab.backendapi.service.impl;
 import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.dao.EnvDAO;
 import com.epam.dlab.backendapi.dao.ExploratoryDAO;
-import com.epam.dlab.backendapi.dao.KeyDAO;
 import com.epam.dlab.backendapi.dao.UserSettingsDAO;
 import com.epam.dlab.backendapi.domain.ProjectDTO;
 import com.epam.dlab.backendapi.resources.dto.UserDTO;
@@ -63,10 +62,6 @@ public class EnvironmentServiceImpl implements EnvironmentService {
 	@Inject
 	private SecurityService securityService;
 	@Inject
-	private KeyDAO keyDAO;
-	@Inject
-	private EdgeService edgeService;
-	@Inject
 	private ProjectService projectService;
 	@Inject
 	private UserSettingsDAO settingsDAO;
@@ -118,7 +113,6 @@ public class EnvironmentServiceImpl implements EnvironmentService {
 		checkState(user, "stop");
 		exploratoryDAO.fetchRunningExploratoryFields(user)
 				.forEach(e -> stopExploratory(userInfo, user, e.getExploratoryName()));
-		stopEdge(user);
 	}
 
 	@Override
@@ -127,7 +121,6 @@ public class EnvironmentServiceImpl implements EnvironmentService {
 		checkState(user, "stop");
 		exploratoryDAO.fetchRunningExploratoryFields(user)
 				.forEach(this::stopNotebookWithServiceAccount);
-		stopEdge(user);
 	}
 
 	@Override
@@ -144,13 +137,6 @@ public class EnvironmentServiceImpl implements EnvironmentService {
 	}
 
 	@Override
-	public void stopEdge(String user) {
-		if (UserInstanceStatus.RUNNING.toString().equals(keyDAO.getEdgeStatus(user))) {
-			edgeService.stop(securityService.getUserInfoOffline(user));
-		}
-	}
-
-	@Override
 	public void stopExploratory(UserInfo userInfo, String user, String exploratoryName) {
 		exploratoryService.stop(new UserInfo(user, userInfo.getAccessToken()), exploratoryName);
 	}
@@ -162,17 +148,6 @@ public class EnvironmentServiceImpl implements EnvironmentService {
 	}
 
 	@Override
-	public void terminateEnvironment(UserInfo userInfo, String user) {
-		log.debug("Terminating environment for user {}", user);
-		checkState(user, "terminate");
-		if (!terminateEdge(user)) {
-			exploratoryDAO.fetchUserExploratoriesWhereStatusNotIn(user, UserInstanceStatus.TERMINATED,
-					UserInstanceStatus.FAILED, UserInstanceStatus.TERMINATING)
-					.forEach(e -> terminateExploratory(userInfo, user, e.getExploratoryName()));
-		}
-	}
-
-	@Override
 	public void terminateExploratory(UserInfo userInfo, String user, String exploratoryName) {
 		exploratoryService.terminate(new UserInfo(user, userInfo.getAccessToken()), exploratoryName);
 	}
@@ -194,7 +169,7 @@ public class EnvironmentServiceImpl implements EnvironmentService {
 								UserInstanceStatus.STARTING, UserInstanceStatus.CREATING_IMAGE),
 						UserInstanceStatus.CREATING,
 						UserInstanceStatus.STARTING, UserInstanceStatus.CREATING_IMAGE);
-		if (UserInstanceStatus.STARTING.toString().equals(keyDAO.getEdgeStatus(user)) || !userInstances.isEmpty()) {
+		if (!userInstances.isEmpty()) {
 			log.error(String.format(ERROR_MSG_FORMAT, action));
 			throw new ResourceConflictException(String.format(ERROR_MSG_FORMAT, action));
 		}
@@ -205,15 +180,6 @@ public class EnvironmentServiceImpl implements EnvironmentService {
 		exploratoryService.stop(userInfo, instance.getExploratoryName());
 	}
 
-	private boolean terminateEdge(String user) {
-		final boolean nodeExists = keyDAO.edgeNodeExist(user);
-		if (nodeExists) {
-			edgeService.terminate(securityService.getUserInfoOffline(user));
-			exploratoryService.updateExploratoryStatuses(user, UserInstanceStatus.TERMINATING);
-		}
-		return nodeExists;
-	}
-
 	private List<UserResourceInfo> getProjectEnv(ProjectDTO projectDTO, List<UserInstanceDTO> allInstances) {
 		final Stream<UserResourceInfo> userResources = allInstances.stream()
 				.filter(instance -> instance.getProject().equals(projectDTO.getName())).map(this::toUserResourceInfo);
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 fe710f5..9bce79d 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
@@ -26,6 +26,7 @@ import com.epam.dlab.backendapi.dao.ComputationalDAO;
 import com.epam.dlab.backendapi.dao.ExploratoryDAO;
 import com.epam.dlab.backendapi.dao.GitCredsDAO;
 import com.epam.dlab.backendapi.dao.ImageExploratoryDao;
+import com.epam.dlab.backendapi.domain.EndpointDTO;
 import com.epam.dlab.backendapi.domain.ProjectDTO;
 import com.epam.dlab.backendapi.domain.RequestId;
 import com.epam.dlab.backendapi.service.EndpointService;
@@ -110,11 +111,12 @@ public class ExploratoryServiceImpl implements ExploratoryService {
 			isAdded = true;
 			final ExploratoryGitCredsDTO gitCreds = gitCredsDAO.findGitCreds(userInfo.getName());
 			log.debug("Created exploratory environment {} for user {}", exploratory.getName(), userInfo.getName());
+			EndpointDTO endpointDTO = endpointService.get(userInstanceDTO.getEndpoint());
 			final String uuid =
-					provisioningService.post(endpointService.get(userInstanceDTO.getEndpoint()).getUrl() + EXPLORATORY_CREATE,
+					provisioningService.post(endpointDTO.getUrl() + EXPLORATORY_CREATE,
 							userInfo.getAccessToken(),
-							requestBuilder.newExploratoryCreate(projectDTO, exploratory, userInfo, gitCreds,
-									userInstanceDTO.getTags()),
+							requestBuilder.newExploratoryCreate(projectDTO, endpointDTO, exploratory, userInfo,
+									gitCreds, userInstanceDTO.getTags()),
 							String.class);
 			requestId.put(userInfo.getName(), uuid);
 			return uuid;
@@ -177,11 +179,12 @@ public class ExploratoryServiceImpl implements ExploratoryService {
 		final String token = userInfo.getAccessToken();
 		final UserInstanceDTO userInstanceDTO = exploratoryDAO.fetchRunningExploratoryFields(userName,
 				exploratoryName);
+		EndpointDTO endpointDTO = endpointService.get(userInstanceDTO.getEndpoint());
 		final ExploratoryReconfigureSparkClusterActionDTO updateClusterConfigDTO =
-				requestBuilder.newClusterConfigUpdate(userInfo, userInstanceDTO, config);
-		final String uuid =
-				provisioningService.post(endpointService.get(userInstanceDTO.getEndpoint()).getUrl() + EXPLORATORY_RECONFIGURE_SPARK, token, updateClusterConfigDTO,
-						String.class);
+				requestBuilder.newClusterConfigUpdate(userInfo, userInstanceDTO, config, endpointDTO);
+		final String uuid = provisioningService.post(endpointDTO.getUrl() + EXPLORATORY_RECONFIGURE_SPARK,
+				token, updateClusterConfigDTO,
+				String.class);
 		requestId.put(userName, uuid);
 		exploratoryDAO.updateExploratoryFields(new ExploratoryStatusDTO()
 				.withUser(userName)
@@ -245,10 +248,10 @@ public class ExploratoryServiceImpl implements ExploratoryService {
 			updateExploratoryStatus(exploratoryName, status, userInfo.getName());
 
 			UserInstanceDTO userInstance = exploratoryDAO.fetchExploratoryFields(userInfo.getName(), exploratoryName);
+			EndpointDTO endpointDTO = endpointService.get(userInstance.getEndpoint());
 			final String uuid =
-					provisioningService.post(endpointService.get(userInstance.getEndpoint()).getUrl() + action,
-							userInfo.getAccessToken(),
-							getExploratoryActionDto(userInfo, status, userInstance), String.class);
+					provisioningService.post(endpointDTO.getUrl() + action, userInfo.getAccessToken(),
+							getExploratoryActionDto(userInfo, status, userInstance, endpointDTO), String.class);
 			requestId.put(userInfo.getName(), uuid);
 			return uuid;
 		} catch (Exception t) {
@@ -275,13 +278,13 @@ public class ExploratoryServiceImpl implements ExploratoryService {
 	}
 
 	private ExploratoryActionDTO<?> getExploratoryActionDto(UserInfo userInfo, UserInstanceStatus status,
-															UserInstanceDTO userInstance) {
+															UserInstanceDTO userInstance, EndpointDTO endpointDTO) {
 		ExploratoryActionDTO<?> dto;
 		if (status != UserInstanceStatus.STARTING) {
-			dto = requestBuilder.newExploratoryStop(userInfo, userInstance);
+			dto = requestBuilder.newExploratoryStop(userInfo, userInstance, endpointDTO);
 		} else {
 			dto = requestBuilder.newExploratoryStart(
-					userInfo, userInstance, gitCredsDAO.findGitCreds(userInfo.getName()));
+					userInfo, userInstance, endpointDTO, gitCredsDAO.findGitCreds(userInfo.getName()));
 
 		}
 		return dto;
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/GitCredentialServiceImpl.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/GitCredentialServiceImpl.java
index 4931276..6d94a0b 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/GitCredentialServiceImpl.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/GitCredentialServiceImpl.java
@@ -22,6 +22,7 @@ package com.epam.dlab.backendapi.service.impl;
 import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.dao.ExploratoryDAO;
 import com.epam.dlab.backendapi.dao.GitCredsDAO;
+import com.epam.dlab.backendapi.domain.EndpointDTO;
 import com.epam.dlab.backendapi.domain.RequestId;
 import com.epam.dlab.backendapi.service.EndpointService;
 import com.epam.dlab.backendapi.service.GitCredentialService;
@@ -98,9 +99,9 @@ public class GitCredentialServiceImpl implements GitCredentialService {
 		try {
 			log.debug("Updating GIT creds for user {} on exploratory {}",
 					userInfo.getName(), instance.getExploratoryName());
-			ExploratoryGitCredsUpdateDTO dto = requestBuilder.newGitCredentialsUpdate(userInfo, instance, formDTO);
-			final String uuid = provisioningService
-					.post(endpointService.get(instance.getEndpoint()).getUrl() + EXPLORATORY_GIT_CREDS,
+			EndpointDTO endpointDTO = endpointService.get(instance.getEndpoint());
+			ExploratoryGitCredsUpdateDTO dto = requestBuilder.newGitCredentialsUpdate(userInfo, instance, endpointDTO, formDTO);
+			final String uuid = provisioningService.post(endpointDTO.getUrl() + EXPLORATORY_GIT_CREDS,
 							userInfo.getAccessToken(), dto, String.class);
 			requestId.put(userInfo.getName(), uuid);
 		} catch (Exception t) {
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ImageExploratoryServiceImpl.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ImageExploratoryServiceImpl.java
index 467dcf4..bd00f38 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ImageExploratoryServiceImpl.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ImageExploratoryServiceImpl.java
@@ -23,6 +23,7 @@ import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.dao.ExploratoryDAO;
 import com.epam.dlab.backendapi.dao.ExploratoryLibDAO;
 import com.epam.dlab.backendapi.dao.ImageExploratoryDao;
+import com.epam.dlab.backendapi.domain.EndpointDTO;
 import com.epam.dlab.backendapi.resources.dto.ImageInfoRecord;
 import com.epam.dlab.backendapi.service.EndpointService;
 import com.epam.dlab.backendapi.service.ImageExploratoryService;
@@ -100,8 +101,10 @@ public class ImageExploratoryServiceImpl implements ImageExploratoryService {
 				.withExploratoryName(exploratoryName)
 				.withStatus(UserInstanceStatus.CREATING_IMAGE));
 
-		return provisioningService.post(endpointService.get(userInstance.getEndpoint()).getUrl() + ExploratoryAPI.EXPLORATORY_IMAGE, user.getAccessToken(),
-				requestBuilder.newExploratoryImageCreate(user, userInstance, imageName), String.class);
+		EndpointDTO endpointDTO = endpointService.get(userInstance.getEndpoint());
+		return provisioningService.post(endpointDTO.getUrl() + ExploratoryAPI.EXPLORATORY_IMAGE,
+				user.getAccessToken(),
+				requestBuilder.newExploratoryImageCreate(user, userInstance, imageName, endpointDTO), String.class);
 	}
 
 	@Override
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InactivityServiceImpl.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InactivityServiceImpl.java
index 866808d..1d3230f 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InactivityServiceImpl.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InactivityServiceImpl.java
@@ -22,9 +22,9 @@ import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.dao.ComputationalDAO;
 import com.epam.dlab.backendapi.dao.EnvDAO;
 import com.epam.dlab.backendapi.dao.ExploratoryDAO;
+import com.epam.dlab.backendapi.domain.EndpointDTO;
 import com.epam.dlab.backendapi.domain.RequestId;
-import com.epam.dlab.backendapi.service.ComputationalService;
-import com.epam.dlab.backendapi.service.ExploratoryService;
+import com.epam.dlab.backendapi.service.EndpointService;
 import com.epam.dlab.backendapi.service.InactivityService;
 import com.epam.dlab.backendapi.service.SecurityService;
 import com.epam.dlab.backendapi.util.RequestBuilder;
@@ -58,11 +58,9 @@ public class InactivityServiceImpl implements InactivityService {
 	@Inject
 	private RequestId requestId;
 	@Inject
-	private ComputationalService computationalService;
-	@Inject
-	private ExploratoryService exploratoryService;
-	@Inject
 	private SecurityService securityService;
+	@Inject
+	private EndpointService endpointService;
 
 	@Override
 	public void updateRunningResourcesLastActivity() {
@@ -93,19 +91,20 @@ public class InactivityServiceImpl implements InactivityService {
 	}
 
 	private void updateComputationalLastActivity(UserInfo userInfo, UserInstanceDTO ui, UserComputationalResource cr) {
-		final ComputationalCheckInactivityDTO dto =
-				requestBuilder.newComputationalCheckInactivity(userInfo, ui, cr);
+		EndpointDTO endpointDTO = endpointService.get(ui.getEndpoint());
+		final ComputationalCheckInactivityDTO dto = requestBuilder.newComputationalCheckInactivity(userInfo, ui, cr, endpointDTO);
 		final String uuid =
-				provisioningService.post(InfrasctructureAPI.COMPUTATIONAL_CHECK_INACTIVITY,
+				provisioningService.post(endpointDTO.getUrl() + InfrasctructureAPI.COMPUTATIONAL_CHECK_INACTIVITY,
 						userInfo.getAccessToken(), dto, String.class);
 		requestId.put(userInfo.getName(), uuid);
 	}
 
 	private void updateExploratoryLastActivity(UserInfo userInfo, UserInstanceDTO ui) {
+		EndpointDTO endpointDTO = endpointService.get(ui.getEndpoint());
 		final ExploratoryCheckInactivityAction dto =
-				requestBuilder.newExploratoryCheckInactivityAction(userInfo, ui);
+				requestBuilder.newExploratoryCheckInactivityAction(userInfo, ui, endpointDTO);
 		final String uuid =
-				provisioningService.post(InfrasctructureAPI.EXPLORATORY_CHECK_INACTIVITY,
+				provisioningService.post(endpointDTO.getUrl() + InfrasctructureAPI.EXPLORATORY_CHECK_INACTIVITY,
 						userInfo.getAccessToken(), dto, String.class);
 		requestId.put(userInfo.getName(), uuid);
 	}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InfrastructureInfoServiceBase.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InfrastructureInfoServiceImpl.java
similarity index 66%
rename from services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InfrastructureInfoServiceBase.java
rename to services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InfrastructureInfoServiceImpl.java
index 751d399..91306af 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InfrastructureInfoServiceBase.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InfrastructureInfoServiceImpl.java
@@ -24,35 +24,38 @@ import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
 import com.epam.dlab.backendapi.dao.BillingDAO;
 import com.epam.dlab.backendapi.dao.EnvDAO;
 import com.epam.dlab.backendapi.dao.ExploratoryDAO;
-import com.epam.dlab.backendapi.dao.KeyDAO;
+import com.epam.dlab.backendapi.domain.EndpointDTO;
 import com.epam.dlab.backendapi.domain.ProjectEndpointDTO;
 import com.epam.dlab.backendapi.resources.dto.HealthStatusPageDTO;
 import com.epam.dlab.backendapi.resources.dto.ProjectInfrastructureInfo;
+import com.epam.dlab.backendapi.service.EndpointService;
 import com.epam.dlab.backendapi.service.InfrastructureInfoService;
 import com.epam.dlab.backendapi.service.ProjectService;
 import com.epam.dlab.dto.InfrastructureMetaInfoDTO;
+import com.epam.dlab.dto.aws.edge.EdgeInfoAws;
+import com.epam.dlab.dto.azure.edge.EdgeInfoAzure;
 import com.epam.dlab.dto.base.edge.EdgeInfo;
+import com.epam.dlab.dto.gcp.edge.EdgeInfoGcp;
 import com.epam.dlab.exceptions.DlabException;
 import com.google.inject.Inject;
 import com.jcabi.manifests.Manifests;
 import lombok.extern.slf4j.Slf4j;
 import org.bson.Document;
 
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 import java.util.stream.StreamSupport;
 
 @Slf4j
-public abstract class InfrastructureInfoServiceBase<T> implements InfrastructureInfoService {
+public class InfrastructureInfoServiceImpl implements InfrastructureInfoService {
 
 	private static final String RELEASE_NOTES_FORMAT = "https://github.com/apache/incubator-dlab/blob/%s" +
 			"/RELEASE_NOTES.md";
 	@Inject
 	private ExploratoryDAO expDAO;
 	@Inject
-	private KeyDAO keyDAO;
-	@Inject
 	private EnvDAO envDAO;
 	@Inject
 	private SelfServiceApplicationConfiguration configuration;
@@ -60,33 +63,33 @@ public abstract class InfrastructureInfoServiceBase<T> implements Infrastructure
 	private BillingDAO billingDAO;
 	@Inject
 	private ProjectService projectService;
+	@Inject
+	private EndpointService endpointService;
 
 
-	@SuppressWarnings("unchecked")
-	private Map<String, String> getSharedInfo(EdgeInfo edgeInfo) {
-		return getSharedInfo((T) edgeInfo);
-	}
-
 	@Override
 	public List<ProjectInfrastructureInfo> getUserResources(String user) {
 		log.debug("Loading list of provisioned resources for user {}", user);
 		try {
 			Iterable<Document> documents = expDAO.findExploratory(user);
-
+			List<EndpointDTO> allEndpoints = endpointService.getEndpoints();
 			return StreamSupport.stream(documents.spliterator(),
 					false)
 					.collect(Collectors.groupingBy(d -> d.getString("project")))
 					.entrySet()
 					.stream()
 					.map(e -> {
-
+						List<ProjectEndpointDTO> endpoints = projectService.get(e.getKey()).getEndpoints();
+						List<EndpointDTO> endpointResult = allEndpoints.stream()
+								.filter(endpoint -> endpoints.stream()
+										.anyMatch(endpoint1 -> endpoint1.getName().equals(endpoint.getName())))
+								.collect(Collectors.toList());
 						final Map<String, Map<String, String>> projectEdges =
-								projectService.get(e.getKey()).getEndpoints().stream()
+								endpoints.stream()
 										.collect(Collectors.toMap(ProjectEndpointDTO::getName,
 												endpointDTO -> getSharedInfo(endpointDTO.getEdgeInfo())));
 						return new ProjectInfrastructureInfo(e.getKey(),
-								billingDAO.getBillingProjectQuoteUsed(e.getKey()),
-								projectEdges, e.getValue());
+								billingDAO.getBillingProjectQuoteUsed(e.getKey()), projectEdges, e.getValue(), endpointResult);
 					})
 					.collect(Collectors.toList());
 		} catch (Exception e) {
@@ -124,5 +127,31 @@ public abstract class InfrastructureInfoServiceBase<T> implements Infrastructure
 				.build();
 	}
 
-	protected abstract Map<String, String> getSharedInfo(T sharedInfo);
+	private Map<String, String> getSharedInfo(EdgeInfo edgeInfo) {
+		Map<String, String> shared = new HashMap<>();
+		shared.put("edge_node_ip", edgeInfo.getPublicIp());
+		if (edgeInfo instanceof EdgeInfoAws) {
+			EdgeInfoAws edgeInfoAws = (EdgeInfoAws) edgeInfo;
+
+			shared.put("user_own_bicket_name", edgeInfoAws.getUserOwnBucketName());
+			shared.put("shared_bucket_name", edgeInfoAws.getSharedBucketName());
+		} else if (edgeInfo instanceof EdgeInfoAzure) {
+			EdgeInfoAzure edgeInfoAzure = (EdgeInfoAzure) edgeInfo;
+
+			shared.put("user_container_name", edgeInfoAzure.getUserContainerName());
+			shared.put("shared_container_name", edgeInfoAzure.getSharedContainerName());
+			shared.put("user_storage_account_name", edgeInfoAzure.getUserStorageAccountName());
+			shared.put("shared_storage_account_name", edgeInfoAzure.getSharedStorageAccountName());
+			shared.put("datalake_name", edgeInfoAzure.getDataLakeName());
+			shared.put("datalake_user_directory_name", edgeInfoAzure.getDataLakeDirectoryName());
+			shared.put("datalake_shared_directory_name", edgeInfoAzure.getDataLakeSharedDirectoryName());
+		} else if (edgeInfo instanceof EdgeInfoGcp) {
+			EdgeInfoGcp edgeInfoGcp = (EdgeInfoGcp) edgeInfo;
+
+			shared.put("user_own_bucket_name", edgeInfoGcp.getUserOwnBucketName());
+			shared.put("shared_bucket_name", edgeInfoGcp.getSharedBucketName());
+		}
+
+		return shared;
+	}
 }
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InfrastructureTemplateServiceBase.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InfrastructureTemplateServiceImpl.java
similarity index 68%
rename from services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InfrastructureTemplateServiceBase.java
rename to services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InfrastructureTemplateServiceImpl.java
index 25fa56b..ca718d4 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InfrastructureTemplateServiceBase.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InfrastructureTemplateServiceImpl.java
@@ -24,8 +24,11 @@ import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
 import com.epam.dlab.backendapi.dao.ProjectDAO;
 import com.epam.dlab.backendapi.dao.SettingsDAO;
 import com.epam.dlab.backendapi.dao.UserGroupDao;
+import com.epam.dlab.backendapi.domain.EndpointDTO;
 import com.epam.dlab.backendapi.domain.ProjectDTO;
 import com.epam.dlab.backendapi.resources.dto.SparkStandaloneConfiguration;
+import com.epam.dlab.backendapi.resources.dto.aws.AwsEmrConfiguration;
+import com.epam.dlab.backendapi.resources.dto.gcp.GcpDataprocConfiguration;
 import com.epam.dlab.backendapi.roles.RoleType;
 import com.epam.dlab.backendapi.roles.UserRoles;
 import com.epam.dlab.backendapi.service.EndpointService;
@@ -54,7 +57,7 @@ import static com.epam.dlab.rest.contracts.DockerAPI.DOCKER_COMPUTATIONAL;
 import static com.epam.dlab.rest.contracts.DockerAPI.DOCKER_EXPLORATORY;
 
 @Slf4j
-public abstract class InfrastructureTemplateServiceBase implements InfrastructureTemplateService {
+public class InfrastructureTemplateServiceImpl implements InfrastructureTemplateService {
 
 	@Inject
 	private SelfServiceApplicationConfiguration configuration;
@@ -77,15 +80,16 @@ public abstract class InfrastructureTemplateServiceBase implements Infrastructur
 
 		log.debug("Loading list of exploratory templates for user {} for project {}", user.getName(), project);
 		try {
+			EndpointDTO endpointDTO = endpointService.get(endpoint);
 			ExploratoryMetadataDTO[] array =
-					provisioningService.get(endpointService.get(endpoint).getUrl() + DOCKER_EXPLORATORY,
+					provisioningService.get(endpointDTO.getUrl() + DOCKER_EXPLORATORY,
 							user.getAccessToken(),
 							ExploratoryMetadataDTO[].class);
 
 			final Set<String> roles = userGroupDao.getUserGroups(user.getName());
 			return Arrays.stream(array)
 					.peek(e -> e.setImage(getSimpleImageName(e.getImage())))
-					.filter(e -> exploratoryGpuIssuesAzureFilter(e) &&
+					.filter(e -> exploratoryGpuIssuesAzureFilter(e, endpointDTO.getCloudProvider()) &&
 							UserRoles.checkAccess(user, RoleType.EXPLORATORY, e.getImage(), roles))
 					.peek(e -> filterShapes(user, e.getExploratoryEnvironmentShapes(), RoleType.EXPLORATORY_SHAPES,
 							roles))
@@ -116,8 +120,9 @@ public abstract class InfrastructureTemplateServiceBase implements Infrastructur
 
 		log.debug("Loading list of computational templates for user {}", user.getName());
 		try {
+			EndpointDTO endpointDTO = endpointService.get(endpoint);
 			ComputationalMetadataDTO[] array =
-					provisioningService.get(endpointService.get(endpoint).getUrl() + DOCKER_COMPUTATIONAL,
+					provisioningService.get(endpointDTO.getUrl() + DOCKER_COMPUTATIONAL,
 							user.getAccessToken(), ComputationalMetadataDTO[]
 									.class);
 
@@ -128,7 +133,7 @@ public abstract class InfrastructureTemplateServiceBase implements Infrastructur
 					.peek(e -> filterShapes(user, e.getComputationResourceShapes(), RoleType.COMPUTATIONAL_SHAPES,
 							user.getRoles()))
 					.filter(e -> UserRoles.checkAccess(user, RoleType.COMPUTATIONAL, e.getImage(), roles))
-					.map(this::fullComputationalTemplate)
+					.map(comp -> fullComputationalTemplate(comp, endpointDTO.getCloudProvider()))
 					.collect(Collectors.toList());
 
 		} catch (DlabException e) {
@@ -143,16 +148,12 @@ public abstract class InfrastructureTemplateServiceBase implements Infrastructur
 				.orElse(user.getRoles());
 	}
 
-	protected abstract FullComputationalTemplate getCloudFullComputationalTemplate(ComputationalMetadataDTO
-																						   metadataDTO);
-
 	/**
 	 * Temporary filter for creation of exploratory env due to Azure issues
 	 */
-	private boolean exploratoryGpuIssuesAzureFilter(ExploratoryMetadataDTO e) {
-		return (!"redhat".equals(settingsDAO.getConfOsFamily()) || configuration.getCloudProvider() != CloudProvider
-				.AZURE)
-				|| !(e.getImage().endsWith("deeplearning") || e.getImage().endsWith("tensor"));
+	private boolean exploratoryGpuIssuesAzureFilter(ExploratoryMetadataDTO e, CloudProvider cloudProvider) {
+		return (!"redhat".equals(settingsDAO.getConfOsFamily()) || cloudProvider != CloudProvider.AZURE) ||
+				!(e.getImage().endsWith("deeplearning") || e.getImage().endsWith("tensor"));
 	}
 
 	/**
@@ -168,16 +169,18 @@ public abstract class InfrastructureTemplateServiceBase implements Infrastructur
 	/**
 	 * Wraps metadata with limits
 	 *
-	 * @param metadataDTO metadata
+	 * @param metadataDTO   metadata
+	 * @param cloudProvider cloudProvider
 	 * @return wrapped object
 	 */
 
-	private FullComputationalTemplate fullComputationalTemplate(ComputationalMetadataDTO metadataDTO) {
+	private FullComputationalTemplate fullComputationalTemplate(ComputationalMetadataDTO metadataDTO,
+																CloudProvider cloudProvider) {
 
 		DataEngineType dataEngineType = DataEngineType.fromDockerImageName(metadataDTO.getImage());
 
 		if (dataEngineType == DataEngineType.CLOUD_SERVICE) {
-			return getCloudFullComputationalTemplate(metadataDTO);
+			return getCloudFullComputationalTemplate(metadataDTO, cloudProvider);
 		} else if (dataEngineType == DataEngineType.SPARK_STANDALONE) {
 			return new SparkFullComputationalTemplate(metadataDTO,
 					SparkStandaloneConfiguration.builder()
@@ -189,6 +192,53 @@ public abstract class InfrastructureTemplateServiceBase implements Infrastructur
 		}
 	}
 
+	protected FullComputationalTemplate getCloudFullComputationalTemplate(ComputationalMetadataDTO metadataDTO,
+																		CloudProvider cloudProvider) {
+		switch (cloudProvider) {
+			case AWS:
+				return new AwsFullComputationalTemplate(metadataDTO,
+						AwsEmrConfiguration.builder()
+								.minEmrInstanceCount(configuration.getMinEmrInstanceCount())
+								.maxEmrInstanceCount(configuration.getMaxEmrInstanceCount())
+								.maxEmrSpotInstanceBidPct(configuration.getMaxEmrSpotInstanceBidPct())
+								.minEmrSpotInstanceBidPct(configuration.getMinEmrSpotInstanceBidPct())
+								.build());
+			case GCP:
+				return new GcpFullComputationalTemplate(metadataDTO,
+						GcpDataprocConfiguration.builder()
+								.minInstanceCount(configuration.getMinInstanceCount())
+								.maxInstanceCount(configuration.getMaxInstanceCount())
+								.minDataprocPreemptibleInstanceCount(configuration.getMinDataprocPreemptibleCount())
+								.build());
+			case AZURE:
+				log.error("Dataengine service is not supported currently for {}", cloudProvider);
+			default:
+				throw new UnsupportedOperationException("Dataengine service is not supported currently for " + cloudProvider);
+		}
+	}
+
+	private class AwsFullComputationalTemplate extends FullComputationalTemplate {
+		@JsonProperty("limits")
+		private AwsEmrConfiguration awsEmrConfiguration;
+
+		AwsFullComputationalTemplate(ComputationalMetadataDTO metadataDTO,
+									 AwsEmrConfiguration awsEmrConfiguration) {
+			super(metadataDTO);
+			this.awsEmrConfiguration = awsEmrConfiguration;
+		}
+	}
+
+	private class GcpFullComputationalTemplate extends FullComputationalTemplate {
+		@JsonProperty("limits")
+		private GcpDataprocConfiguration gcpDataprocConfiguration;
+
+		GcpFullComputationalTemplate(ComputationalMetadataDTO metadataDTO,
+									 GcpDataprocConfiguration gcpDataprocConfiguration) {
+			super(metadataDTO);
+			this.gcpDataprocConfiguration = gcpDataprocConfiguration;
+		}
+	}
+
 	private class SparkFullComputationalTemplate extends FullComputationalTemplate {
 		@JsonProperty("limits")
 		private SparkStandaloneConfiguration sparkStandaloneConfiguration;
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/LibraryServiceImpl.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/LibraryServiceImpl.java
index afadbf6..3d65a15 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/LibraryServiceImpl.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/LibraryServiceImpl.java
@@ -23,6 +23,7 @@ import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.dao.BaseDAO;
 import com.epam.dlab.backendapi.dao.ExploratoryDAO;
 import com.epam.dlab.backendapi.dao.ExploratoryLibDAO;
+import com.epam.dlab.backendapi.domain.EndpointDTO;
 import com.epam.dlab.backendapi.domain.RequestId;
 import com.epam.dlab.backendapi.resources.dto.LibInfoRecord;
 import com.epam.dlab.backendapi.resources.dto.LibKey;
@@ -127,10 +128,11 @@ public class LibraryServiceImpl implements LibraryService {
 										   List<LibInstallDTO> libs) {
 
 		final UserInstanceDTO userInstance = exploratoryDAO.fetchExploratoryFields(ui.getName(), expName, compName);
+		EndpointDTO endpointDTO = endpointService.get(userInstance.getEndpoint());
 		final String uuid =
-				provisioningService.post(endpointService.get(userInstance.getEndpoint()).getUrl() + ComputationalAPI.COMPUTATIONAL_LIB_INSTALL,
-						ui.getAccessToken(), toComputationalLibraryInstallDto(ui, expName, compName, libs,
-								userInstance),
+				provisioningService.post(endpointDTO.getUrl() + ComputationalAPI.COMPUTATIONAL_LIB_INSTALL,
+						ui.getAccessToken(),
+						toComputationalLibraryInstallDto(ui, expName, compName, libs, userInstance, endpointDTO),
 						String.class);
 		requestId.put(ui.getName(), uuid);
 		return uuid;
@@ -139,26 +141,28 @@ public class LibraryServiceImpl implements LibraryService {
 	@Override
 	public String installExploratoryLibs(UserInfo ui, String expName, List<LibInstallDTO> libs) {
 		final UserInstanceDTO userInstance = exploratoryDAO.fetchRunningExploratoryFields(ui.getName(), expName);
+		EndpointDTO endpointDTO = endpointService.get(userInstance.getEndpoint());
 		final String uuid =
-				provisioningService.post(endpointService.get(userInstance.getEndpoint()).getUrl() + ExploratoryAPI.EXPLORATORY_LIB_INSTALL, ui.getAccessToken(),
-				toExploratoryLibraryInstallDto(ui, expName, libs, userInstance), String.class);
+				provisioningService.post(endpointDTO.getUrl() + ExploratoryAPI.EXPLORATORY_LIB_INSTALL,
+						ui.getAccessToken(), toExploratoryLibraryInstallDto(ui, expName, libs, userInstance, endpointDTO),
+						String.class);
 		requestId.put(ui.getName(), uuid);
 		return uuid;
 	}
 
 	private LibraryInstallDTO toExploratoryLibraryInstallDto(UserInfo userInfo, String exploratoryName,
-															 List<LibInstallDTO> libs, UserInstanceDTO userInstance) {
+															 List<LibInstallDTO> libs, UserInstanceDTO userInstance, EndpointDTO endpointDTO) {
 		final List<LibInstallDTO> libsToInstall = libs.stream()
 				.map(lib -> toLibInstallDto(lib, libraryDAO.getLibrary(userInfo.getName(), exploratoryName,
 						lib.getGroup(), lib.getName())))
 				.peek(l -> libraryDAO.addLibrary(userInfo.getName(), exploratoryName, l, l.isOverride()))
 				.collect(Collectors.toList());
-		return requestBuilder.newLibInstall(userInfo, userInstance, libsToInstall);
+		return requestBuilder.newLibInstall(userInfo, userInstance, endpointDTO, libsToInstall);
 	}
 
 	private LibraryInstallDTO toComputationalLibraryInstallDto(UserInfo userInfo, String expName, String compName,
 															   List<LibInstallDTO> libs,
-															   UserInstanceDTO userInstance) {
+															   UserInstanceDTO userInstance, EndpointDTO endpointDTO) {
 
 		final UserComputationalResource computationalResource = getComputationalResource(compName, userInstance);
 		final List<LibInstallDTO> libsToInstall = libs.stream()
@@ -167,7 +171,7 @@ public class LibraryServiceImpl implements LibraryService {
 				.peek(l -> libraryDAO.addLibrary(userInfo.getName(), expName, compName, l,
 						l.isOverride()))
 				.collect(Collectors.toList());
-		return requestBuilder.newLibInstall(userInfo, userInstance, computationalResource, libsToInstall);
+		return requestBuilder.newLibInstall(userInfo, userInstance, computationalResource, libsToInstall, endpointDTO);
 	}
 
 	private UserComputationalResource getComputationalResource(String computationalName,
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 bdafb26..5355dee 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
@@ -6,11 +6,7 @@ import com.epam.dlab.backendapi.annotation.Project;
 import com.epam.dlab.backendapi.dao.ExploratoryDAO;
 import com.epam.dlab.backendapi.dao.ProjectDAO;
 import com.epam.dlab.backendapi.dao.UserGroupDao;
-import com.epam.dlab.backendapi.domain.ProjectDTO;
-import com.epam.dlab.backendapi.domain.ProjectEndpointDTO;
-import com.epam.dlab.backendapi.domain.ProjectManagingDTO;
-import com.epam.dlab.backendapi.domain.RequestId;
-import com.epam.dlab.backendapi.domain.UpdateProjectDTO;
+import com.epam.dlab.backendapi.domain.*;
 import com.epam.dlab.backendapi.service.EndpointService;
 import com.epam.dlab.backendapi.service.ExploratoryService;
 import com.epam.dlab.backendapi.service.ProjectService;
@@ -25,11 +21,7 @@ import com.google.inject.Inject;
 import com.google.inject.name.Named;
 import lombok.extern.slf4j.Slf4j;
 
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
+import java.util.*;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
 
@@ -233,18 +225,17 @@ public class ProjectServiceImpl implements ProjectService {
 	}
 
 	private void createEndpoint(UserInfo user, ProjectDTO projectDTO, String endpointName) {
-		String uuid =
-				provisioningService.post(endpointService.get(endpointName).getUrl() + CREATE_PRJ_API,
-						user.getAccessToken(),
-						requestBuilder.newProjectCreate(user, projectDTO, endpointName), String.class);
+		EndpointDTO endpointDTO = endpointService.get(endpointName);
+		String uuid = provisioningService.post(endpointDTO.getUrl() + CREATE_PRJ_API, user.getAccessToken(),
+						requestBuilder.newProjectCreate(user, projectDTO, endpointDTO), String.class);
 		requestId.put(user.getName(), uuid);
 	}
 
 	private void projectActionOnCloud(UserInfo user, String projectName, String provisioningApiUri, String endpoint) {
 		try {
-			String uuid = provisioningService.post(endpointService.get(endpoint).getUrl() + provisioningApiUri,
-					user.getAccessToken(),
-					requestBuilder.newProjectAction(user, projectName, endpoint), String.class);
+			EndpointDTO endpointDTO = endpointService.get(endpoint);
+			String uuid = provisioningService.post(endpointDTO.getUrl() + provisioningApiUri, user.getAccessToken(),
+					requestBuilder.newProjectAction(user, projectName, endpointDTO), String.class);
 			requestId.put(user.getName(), uuid);
 		} catch (Exception e) {
 			log.error("Can not terminate project due to: {}", e.getMessage());
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ReuploadKeyServiceImpl.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ReuploadKeyServiceImpl.java
index e783d9c..0efe7f6 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ReuploadKeyServiceImpl.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/ReuploadKeyServiceImpl.java
@@ -22,11 +22,9 @@ package com.epam.dlab.backendapi.service.impl;
 import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.dao.ComputationalDAO;
 import com.epam.dlab.backendapi.dao.ExploratoryDAO;
-import com.epam.dlab.backendapi.dao.KeyDAO;
 import com.epam.dlab.backendapi.domain.RequestId;
 import com.epam.dlab.backendapi.service.ExploratoryService;
 import com.epam.dlab.backendapi.service.ReuploadKeyService;
-import com.epam.dlab.backendapi.service.UserResourceService;
 import com.epam.dlab.backendapi.util.RequestBuilder;
 import com.epam.dlab.dto.UserInstanceStatus;
 import com.epam.dlab.dto.base.DataEngineType;
@@ -45,7 +43,6 @@ import org.apache.commons.lang3.StringUtils;
 
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.List;
 import java.util.UUID;
 
 import static com.epam.dlab.constants.ServiceConsts.PROVISIONING_SERVICE_NAME;
@@ -58,8 +55,6 @@ import static com.epam.dlab.rest.contracts.KeyAPI.REUPLOAD_KEY;
 public class ReuploadKeyServiceImpl implements ReuploadKeyService {
 
 	@Inject
-	private KeyDAO keyDAO;
-	@Inject
 	@Named(PROVISIONING_SERVICE_NAME)
 	private RESTService provisioningService;
 	@Inject
@@ -72,32 +67,12 @@ public class ReuploadKeyServiceImpl implements ReuploadKeyService {
 	private ComputationalDAO computationalDAO;
 	@Inject
 	private ExploratoryDAO exploratoryDAO;
-	@Inject
-	private UserResourceService userResourceService;
 
 	private static final String REUPLOAD_KEY_UPDATE_MSG = "Reuploading key process is successfully finished. " +
 			"Updating 'reupload_key_required' flag to 'false' for {}.";
 	private static final String REUPLOAD_KEY_ERROR_MSG = "Reuploading key process is failed for {}. The next attempt" +
 			"starts after resource restarting.";
 
-
-	@Override
-	public String reuploadKey(UserInfo user, String keyContent) {
-		userResourceService.updateReuploadKeyFlagForUserResources(user.getName(), true);
-		List<ResourceData> resourcesForKeyReuploading = userResourceService.convertToResourceData(
-				exploratoryService.getInstancesWithStatuses(user.getName(), RUNNING, RUNNING));
-		keyDAO.getEdgeInfoWhereStatusIn(user.getName(), RUNNING)
-				.ifPresent(edgeInfo -> {
-					resourcesForKeyReuploading.add(ResourceData.edgeResource(edgeInfo.getInstanceId()));
-					keyDAO.updateEdgeStatus(user.getName(), REUPLOADING_KEY.toString());
-				});
-		updateStatusForUserInstances(user.getName(), REUPLOADING_KEY);
-
-		ReuploadKeyDTO reuploadKeyDTO = requestBuilder.newKeyReupload(user, UUID.randomUUID().toString(), keyContent,
-				resourcesForKeyReuploading);
-		return provisioningService.post(REUPLOAD_KEY, user.getAccessToken(), reuploadKeyDTO, String.class);
-	}
-
 	@Override
 	public void updateResourceData(ReuploadKeyStatusDTO dto) {
 		String user = dto.getUser();
@@ -112,27 +87,8 @@ public class ReuploadKeyServiceImpl implements ReuploadKeyService {
 		}
 	}
 
-	@Override
-	public void reuploadKeyAction(UserInfo userInfo, ResourceData resourceData) {
-		try {
-			updateResourceStatus(userInfo.getName(), resourceData, REUPLOADING_KEY);
-			ReuploadKeyDTO reuploadKeyDTO = requestBuilder.newKeyReupload(userInfo, UUID.randomUUID().toString(),
-					StringUtils.EMPTY, Collections.singletonList(resourceData));
-			String uuid = provisioningService.post(REUPLOAD_KEY, userInfo.getAccessToken(), reuploadKeyDTO,
-					String.class, Collections.singletonMap("is_primary_reuploading", false));
-			requestId.put(userInfo.getName(), uuid);
-		} catch (Exception t) {
-			log.error("Couldn't reupload key to " + resourceData.toString() + " for user {}", userInfo.getName(), t);
-			updateResourceStatus(userInfo.getName(), resourceData, RUNNING);
-			throw new DlabException("Couldn't reupload key to " + resourceData.toString() + " for user " +
-					userInfo.getName() + ":	" + t.getLocalizedMessage(), t);
-		}
-	}
-
 	private void updateResourceStatus(String user, ResourceData resourceData, UserInstanceStatus newStatus) {
-		if (resourceData.getResourceType() == ResourceType.EDGE) {
-			keyDAO.updateEdgeStatus(user, newStatus.toString());
-		} else if (resourceData.getResourceType() == ResourceType.EXPLORATORY) {
+		if (resourceData.getResourceType() == ResourceType.EXPLORATORY) {
 			exploratoryDAO.updateStatusForExploratory(user, resourceData.getExploratoryName(), newStatus);
 		} else if (resourceData.getResourceType() == ResourceType.COMPUTATIONAL) {
 			computationalDAO.updateStatusForComputationalResource(user, resourceData.getExploratoryName(),
@@ -141,9 +97,7 @@ public class ReuploadKeyServiceImpl implements ReuploadKeyService {
 	}
 
 	private void updateResourceReuploadKeyFlag(String user, ResourceData resourceData, boolean reuploadKeyRequired) {
-		if (resourceData.getResourceType() == ResourceType.EDGE) {
-			keyDAO.updateEdgeReuploadKey(user, reuploadKeyRequired, UserInstanceStatus.values());
-		} else if (resourceData.getResourceType() == ResourceType.EXPLORATORY) {
+		if (resourceData.getResourceType() == ResourceType.EXPLORATORY) {
 			exploratoryDAO.updateReuploadKeyForExploratory(user, resourceData.getExploratoryName(),
 					reuploadKeyRequired);
 		} else if (resourceData.getResourceType() == ResourceType.COMPUTATIONAL) {
@@ -151,12 +105,4 @@ public class ReuploadKeyServiceImpl implements ReuploadKeyService {
 					resourceData.getComputationalName(), reuploadKeyRequired);
 		}
 	}
-
-	private void updateStatusForUserInstances(String user, UserInstanceStatus newStatus) {
-		exploratoryDAO.updateStatusForExploratories(newStatus, user, RUNNING);
-		computationalDAO.updateStatusForComputationalResources(newStatus, user,
-				Arrays.asList(RUNNING, REUPLOADING_KEY), Arrays.asList(DataEngineType.SPARK_STANDALONE,
-						DataEngineType.CLOUD_SERVICE), RUNNING);
-	}
-
 }
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/UserResourceServiceImpl.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/UserResourceServiceImpl.java
deleted file mode 100644
index 7a1c27c..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/UserResourceServiceImpl.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-
-package com.epam.dlab.backendapi.service.impl;
-
-import com.epam.dlab.backendapi.service.ComputationalService;
-import com.epam.dlab.backendapi.service.EdgeService;
-import com.epam.dlab.backendapi.service.ExploratoryService;
-import com.epam.dlab.backendapi.service.UserResourceService;
-import com.epam.dlab.dto.UserInstanceDTO;
-import com.epam.dlab.dto.base.DataEngineType;
-import com.epam.dlab.model.ResourceData;
-import com.google.inject.Inject;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static com.epam.dlab.dto.UserInstanceStatus.*;
-
-public class UserResourceServiceImpl implements UserResourceService {
-
-	@Inject
-	private ExploratoryService exploratoryService;
-	@Inject
-	private ComputationalService computationalService;
-	@Inject
-	private EdgeService edgeService;
-
-	/**
-	 * Converts user's instances to another data type.
-	 *
-	 * @param userInstances list of user instances.
-	 * @return converted list of resources' data.
-	 */
-	@Override
-	public List<ResourceData> convertToResourceData(List<UserInstanceDTO> userInstances) {
-		return userInstances
-				.stream()
-				.flatMap(this::resourceDataStream)
-				.collect(Collectors.toList());
-	}
-
-	/**
-	 * Updates flag 'reuploadKeyRequired' for user's resources with predefined statuses.
-	 *
-	 * @param user                user's name.
-	 * @param reuploadKeyRequired true/false.
-	 */
-	@Override
-	public void updateReuploadKeyFlagForUserResources(String user, boolean reuploadKeyRequired) {
-		exploratoryService.updateExploratoriesReuploadKeyFlag(user, reuploadKeyRequired,
-				CREATING, CONFIGURING, STARTING, RUNNING, STOPPING, STOPPED);
-		computationalService.updateComputationalsReuploadKeyFlag(user,
-				Arrays.asList(STARTING, RUNNING, STOPPING, STOPPED),
-				Collections.singletonList(DataEngineType.SPARK_STANDALONE),
-				reuploadKeyRequired,
-				CREATING, CONFIGURING, STARTING, RUNNING, STOPPING, STOPPED);
-		computationalService.updateComputationalsReuploadKeyFlag(user,
-				Collections.singletonList(RUNNING),
-				Collections.singletonList(DataEngineType.CLOUD_SERVICE),
-				reuploadKeyRequired,
-				CREATING, CONFIGURING, STARTING, RUNNING);
-		edgeService.updateReuploadKeyFlag(user, reuploadKeyRequired, STARTING, RUNNING, STOPPING, STOPPED);
-	}
-
-	private Stream<ResourceData> resourceDataStream(UserInstanceDTO ui) {
-		final Stream<ResourceData> exploratoryStream =
-				Stream.of(ResourceData.exploratoryResource(ui.getExploratoryId(), ui.getExploratoryName()));
-		final Stream<ResourceData> computationalStream = ui.getResources()
-				.stream()
-				.map(cr -> ResourceData.computationalResource(cr.getComputationalId(),
-						ui.getExploratoryName(), cr.getComputationalName()));
-		return Stream.concat(exploratoryStream, computationalStream);
-	}
-}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/util/RequestBuilder.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/util/RequestBuilder.java
index d4f690e..0e29820 100644
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/util/RequestBuilder.java
+++ b/services/self-service/src/main/java/com/epam/dlab/backendapi/util/RequestBuilder.java
@@ -22,6 +22,7 @@ package com.epam.dlab.backendapi.util;
 import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
 import com.epam.dlab.backendapi.dao.SettingsDAO;
+import com.epam.dlab.backendapi.domain.EndpointDTO;
 import com.epam.dlab.backendapi.domain.ExploratoryLibCache;
 import com.epam.dlab.backendapi.domain.ProjectDTO;
 import com.epam.dlab.backendapi.resources.dto.BackupFormDTO;
@@ -30,41 +31,35 @@ import com.epam.dlab.backendapi.resources.dto.SparkStandaloneClusterCreateForm;
 import com.epam.dlab.backendapi.resources.dto.aws.AwsComputationalCreateForm;
 import com.epam.dlab.backendapi.resources.dto.gcp.GcpComputationalCreateForm;
 import com.epam.dlab.cloud.CloudProvider;
-import com.epam.dlab.dto.*;
+import com.epam.dlab.dto.LibListComputationalDTO;
+import com.epam.dlab.dto.ResourceBaseDTO;
+import com.epam.dlab.dto.ResourceSysBaseDTO;
+import com.epam.dlab.dto.UserInstanceDTO;
 import com.epam.dlab.dto.aws.AwsCloudSettings;
 import com.epam.dlab.dto.aws.computational.AwsComputationalTerminateDTO;
 import com.epam.dlab.dto.aws.computational.ClusterConfig;
 import com.epam.dlab.dto.aws.computational.ComputationalCreateAws;
 import com.epam.dlab.dto.aws.computational.SparkComputationalCreateAws;
-import com.epam.dlab.dto.aws.edge.EdgeCreateAws;
 import com.epam.dlab.dto.aws.exploratory.ExploratoryCreateAws;
-import com.epam.dlab.dto.aws.keyload.UploadFileAws;
 import com.epam.dlab.dto.azure.AzureCloudSettings;
 import com.epam.dlab.dto.azure.computational.SparkComputationalCreateAzure;
-import com.epam.dlab.dto.azure.edge.EdgeCreateAzure;
 import com.epam.dlab.dto.azure.exploratory.ExploratoryActionStartAzure;
 import com.epam.dlab.dto.azure.exploratory.ExploratoryActionStopAzure;
 import com.epam.dlab.dto.azure.exploratory.ExploratoryCreateAzure;
-import com.epam.dlab.dto.azure.keyload.UploadFileAzure;
 import com.epam.dlab.dto.backup.EnvBackupDTO;
 import com.epam.dlab.dto.base.CloudSettings;
 import com.epam.dlab.dto.base.DataEngineType;
 import com.epam.dlab.dto.base.computational.ComputationalBase;
-import com.epam.dlab.dto.base.keyload.UploadFile;
 import com.epam.dlab.dto.computational.*;
 import com.epam.dlab.dto.exploratory.*;
 import com.epam.dlab.dto.gcp.GcpCloudSettings;
 import com.epam.dlab.dto.gcp.computational.ComputationalCreateGcp;
 import com.epam.dlab.dto.gcp.computational.GcpComputationalTerminateDTO;
 import com.epam.dlab.dto.gcp.computational.SparkComputationalCreateGcp;
-import com.epam.dlab.dto.gcp.edge.EdgeCreateGcp;
 import com.epam.dlab.dto.gcp.exploratory.ExploratoryCreateGcp;
-import com.epam.dlab.dto.gcp.keyload.UploadFileGcp;
 import com.epam.dlab.dto.project.ProjectActionDTO;
 import com.epam.dlab.dto.project.ProjectCreateDTO;
-import com.epam.dlab.dto.reuploadkey.ReuploadKeyDTO;
 import com.epam.dlab.exceptions.DlabException;
-import com.epam.dlab.model.ResourceData;
 import com.epam.dlab.model.exploratory.Exploratory;
 import com.epam.dlab.util.UsernameUtils;
 import com.google.inject.Inject;
@@ -86,8 +81,8 @@ public class RequestBuilder {
 	@Inject
 	private SettingsDAO settingsDAO;
 
-	private CloudSettings cloudSettings(UserInfo userInfo) {
-		switch (cloudProvider()) {
+	private CloudSettings cloudSettings(UserInfo userInfo, CloudProvider cloudProvider) {
+		switch (cloudProvider) {
 			case AWS:
 				return AwsCloudSettings.builder()
 						.awsIamUser(userInfo.getName())
@@ -99,32 +94,33 @@ public class RequestBuilder {
 				return GcpCloudSettings.builder()
 						.gcpIamUser(userInfo.getName()).build();
 			default:
-				throw new IllegalArgumentException(UNSUPPORTED_CLOUD_PROVIDER_MESSAGE + cloudProvider());
+				throw new IllegalArgumentException(UNSUPPORTED_CLOUD_PROVIDER_MESSAGE + cloudProvider);
 		}
 	}
 
 	@SuppressWarnings("unchecked")
-	private <T extends ResourceBaseDTO<?>> T newResourceBaseDTO(UserInfo userInfo, Class<T> resourceClass) {
+	private <T extends ResourceBaseDTO<?>> T newResourceBaseDTO(UserInfo userInfo, CloudProvider cloudProvider,
+																Class<T> resourceClass) {
 		try {
 			return (T) resourceClass.newInstance()
-					.withEdgeUserName(getEdgeUserName(userInfo))
-					.withCloudSettings(cloudSettings(userInfo));
+					.withEdgeUserName(getEdgeUserName(userInfo, cloudProvider))
+					.withCloudSettings(cloudSettings(userInfo, cloudProvider));
 		} catch (Exception e) {
 			throw new DlabException("Cannot create instance of resource class " + resourceClass.getName() + ". " +
 					e.getLocalizedMessage(), e);
 		}
 	}
 
-	private String getEdgeUserName(UserInfo userInfo) {
+	private String getEdgeUserName(UserInfo userInfo, CloudProvider cloudProvider) {
 		String edgeUser = UsernameUtils.replaceWhitespaces(userInfo.getSimpleName());
-		switch (cloudProvider()) {
+		switch (cloudProvider) {
 			case GCP:
 				return adjustUserName(configuration.getMaxUserNameLength(), edgeUser);
 			case AWS:
 			case AZURE:
 				return edgeUser;
 			default:
-				throw new DlabException(UNSUPPORTED_CLOUD_PROVIDER_MESSAGE + cloudProvider());
+				throw new DlabException(UNSUPPORTED_CLOUD_PROVIDER_MESSAGE + cloudProvider);
 		}
 	}
 
@@ -134,72 +130,26 @@ public class RequestBuilder {
 	}
 
 	@SuppressWarnings("unchecked")
-	private <T extends ResourceSysBaseDTO<?>> T newResourceSysBaseDTO(UserInfo userInfo, Class<T> resourceClass) {
-		return newResourceBaseDTO(userInfo, resourceClass);
+	private <T extends ResourceSysBaseDTO<?>> T newResourceSysBaseDTO(UserInfo userInfo, CloudProvider cloudProvider,
+																	  Class<T> resourceClass) {
+		return newResourceBaseDTO(userInfo, cloudProvider, resourceClass);
 	}
 
 	@SuppressWarnings("unchecked")
-	public UploadFile newEdgeKeyUpload(UserInfo userInfo, String content) {
-
-		switch (cloudProvider()) {
-			case AWS:
-				EdgeCreateAws edgeCreateAws = newResourceSysBaseDTO(userInfo, EdgeCreateAws.class);
-				UploadFileAws uploadFileAws = new UploadFileAws();
-				uploadFileAws.setEdge(edgeCreateAws);
-				uploadFileAws.setContent(content);
-
-				return uploadFileAws;
-
-			case AZURE:
-				EdgeCreateAzure edgeCreateAzure = newResourceSysBaseDTO(userInfo, EdgeCreateAzure.class)
-						.withAzureDataLakeEnable(Boolean.toString(settingsDAO.isAzureDataLakeEnabled()));
-
-				UploadFileAzure uploadFileAzure = new UploadFileAzure();
-				uploadFileAzure.setEdge(edgeCreateAzure);
-				uploadFileAzure.setContent(content);
-
-				return uploadFileAzure;
-
-			case GCP:
-				return new UploadFileGcp(newResourceSysBaseDTO(userInfo, EdgeCreateGcp.class), content);
-			default:
-				throw new IllegalArgumentException(UNSUPPORTED_CLOUD_PROVIDER_MESSAGE + cloudProvider());
-		}
-	}
-
-	public ReuploadKeyDTO newKeyReupload(UserInfo userInfo, String id, String content, List<ResourceData> resources) {
-		return newResourceSysBaseDTO(userInfo, ReuploadKeyDTO.class)
-				.withId(id)
-				.withContent(content)
-				.withResources(resources);
-	}
-
-	@SuppressWarnings("unchecked")
-	public <T extends ResourceSysBaseDTO<?>> T newEdgeAction(UserInfo userInfo) {
-		checkInappropriateCloudProviderOrElseThrowException();
-		return (T) newResourceSysBaseDTO(userInfo, ResourceSysBaseDTO.class);
-	}
-
-	public UserEnvironmentResources newUserEnvironmentStatus(UserInfo userInfo) {
-		checkInappropriateCloudProviderOrElseThrowException();
-		return newResourceSysBaseDTO(userInfo, UserEnvironmentResources.class);
-	}
-
-	@SuppressWarnings("unchecked")
-	public <T extends ExploratoryCreateDTO<T>> T newExploratoryCreate(ProjectDTO projectDTO, Exploratory exploratory,
+	public <T extends ExploratoryCreateDTO<T>> T newExploratoryCreate(ProjectDTO projectDTO, EndpointDTO endpointDTO, Exploratory exploratory,
 																	  UserInfo userInfo,
 																	  ExploratoryGitCredsDTO exploratoryGitCredsDTO,
 																	  Map<String, String> tags) {
 
 		T exploratoryCreate;
-
-		switch (cloudProvider()) {
+		CloudProvider cloudProvider = endpointDTO.getCloudProvider();
+		switch (cloudProvider) {
 			case AWS:
-				exploratoryCreate = (T) newResourceSysBaseDTO(userInfo, ExploratoryCreateAws.class)
+				exploratoryCreate = (T) newResourceSysBaseDTO(userInfo, cloudProvider, ExploratoryCreateAws.class)
 						.withNotebookInstanceType(exploratory.getShape());
 				break;
 			case AZURE:
-				exploratoryCreate = (T) newResourceSysBaseDTO(userInfo, ExploratoryCreateAzure.class)
+				exploratoryCreate = (T) newResourceSysBaseDTO(userInfo, cloudProvider, ExploratoryCreateAzure.class)
 						.withNotebookInstanceSize(exploratory.getShape());
 				if (settingsDAO.isAzureDataLakeEnabled()) {
 					((ExploratoryCreateAzure) exploratoryCreate)
@@ -210,11 +160,11 @@ public class RequestBuilder {
 						.withAzureDataLakeEnabled(Boolean.toString(settingsDAO.isAzureDataLakeEnabled()));
 				break;
 			case GCP:
-				exploratoryCreate = (T) newResourceSysBaseDTO(userInfo, ExploratoryCreateGcp.class)
+				exploratoryCreate = (T) newResourceSysBaseDTO(userInfo, cloudProvider, ExploratoryCreateGcp.class)
 						.withNotebookInstanceType(exploratory.getShape());
 				break;
 			default:
-				throw new IllegalArgumentException(UNSUPPORTED_CLOUD_PROVIDER_MESSAGE + cloudProvider());
+				throw new IllegalArgumentException(UNSUPPORTED_CLOUD_PROVIDER_MESSAGE + cloudProvider);
 		}
 
 		return exploratoryCreate.withExploratoryName(exploratory.getName())
@@ -232,13 +182,14 @@ public class RequestBuilder {
 	@SuppressWarnings("unchecked")
 	public <T extends ExploratoryGitCredsUpdateDTO> T newExploratoryStart(UserInfo userInfo,
 																		  UserInstanceDTO userInstance,
+																		  EndpointDTO endpointDTO,
 																		  ExploratoryGitCredsDTO
 																				  exploratoryGitCredsDTO) {
-
-		switch (cloudProvider()) {
+		CloudProvider cloudProvider = endpointDTO.getCloudProvider();
+		switch (cloudProvider) {
 			case AWS:
 			case GCP:
-				return (T) newResourceSysBaseDTO(userInfo, ExploratoryGitCredsUpdateDTO.class)
+				return (T) newResourceSysBaseDTO(userInfo, cloudProvider, ExploratoryGitCredsUpdateDTO.class)
 						.withNotebookInstanceName(userInstance.getExploratoryId())
 						.withGitCreds(exploratoryGitCredsDTO.getGitCreds())
 						.withNotebookImage(userInstance.getImageName())
@@ -247,7 +198,7 @@ public class RequestBuilder {
 						.withProject(userInstance.getProject())
 						.withEndpoint(userInstance.getEndpoint());
 			case AZURE:
-				T exploratoryStart = (T) newResourceSysBaseDTO(userInfo, ExploratoryActionStartAzure.class)
+				T exploratoryStart = (T) newResourceSysBaseDTO(userInfo, cloudProvider, ExploratoryActionStartAzure.class)
 						.withNotebookInstanceName(userInstance.getExploratoryId())
 						.withGitCreds(exploratoryGitCredsDTO.getGitCreds())
 						.withNotebookImage(userInstance.getImageName())
@@ -266,25 +217,26 @@ public class RequestBuilder {
 
 				return exploratoryStart;
 			default:
-				throw new IllegalArgumentException(UNSUPPORTED_CLOUD_PROVIDER_MESSAGE + cloudProvider());
+				throw new IllegalArgumentException(UNSUPPORTED_CLOUD_PROVIDER_MESSAGE + cloudProvider);
 		}
 	}
 
 	@SuppressWarnings("unchecked")
-	public <T extends ExploratoryActionDTO<T>> T newExploratoryStop(UserInfo userInfo, UserInstanceDTO userInstance) {
+	public <T extends ExploratoryActionDTO<T>> T newExploratoryStop(UserInfo userInfo, UserInstanceDTO userInstance, EndpointDTO endpointDTO) {
 
 		T exploratoryStop;
+		CloudProvider cloudProvider = endpointDTO.getCloudProvider();
 
-		switch (cloudProvider()) {
+		switch (cloudProvider) {
 			case AWS:
 			case GCP:
-				exploratoryStop = (T) newResourceSysBaseDTO(userInfo, ExploratoryActionDTO.class);
+				exploratoryStop = (T) newResourceSysBaseDTO(userInfo, cloudProvider, ExploratoryActionDTO.class);
 				break;
 			case AZURE:
-				exploratoryStop = (T) newResourceSysBaseDTO(userInfo, ExploratoryActionStopAzure.class);
+				exploratoryStop = (T) newResourceSysBaseDTO(userInfo, cloudProvider, ExploratoryActionStopAzure.class);
 				break;
 			default:
-				throw new IllegalArgumentException(UNSUPPORTED_CLOUD_PROVIDER_MESSAGE + cloudProvider());
+				throw new IllegalArgumentException(UNSUPPORTED_CLOUD_PROVIDER_MESSAGE + cloudProvider);
 		}
 
 		return exploratoryStop
@@ -298,9 +250,10 @@ public class RequestBuilder {
 	}
 
 	public ExploratoryGitCredsUpdateDTO newGitCredentialsUpdate(UserInfo userInfo, UserInstanceDTO instanceDTO,
+																EndpointDTO endpointDTO,
 																ExploratoryGitCredsDTO exploratoryGitCredsDTO) {
-		checkInappropriateCloudProviderOrElseThrowException();
-		return newResourceSysBaseDTO(userInfo, ExploratoryGitCredsUpdateDTO.class)
+		checkInappropriateCloudProviderOrElseThrowException(endpointDTO.getCloudProvider());
+		return newResourceSysBaseDTO(userInfo, endpointDTO.getCloudProvider(), ExploratoryGitCredsUpdateDTO.class)
 				.withNotebookImage(instanceDTO.getImageName())
 				.withApplicationName(getApplicationNameFromImage(instanceDTO.getImageName()))
 				.withProject(instanceDTO.getProject())
@@ -311,22 +264,24 @@ public class RequestBuilder {
 	}
 
 	public LibraryInstallDTO newLibInstall(UserInfo userInfo, UserInstanceDTO userInstance,
-										   List<LibInstallDTO> libs) {
-		checkInappropriateCloudProviderOrElseThrowException();
-		return newResourceSysBaseDTO(userInfo, LibraryInstallDTO.class)
+										   EndpointDTO endpointDTO, List<LibInstallDTO> libs) {
+		checkInappropriateCloudProviderOrElseThrowException(endpointDTO.getCloudProvider());
+		return newResourceSysBaseDTO(userInfo, endpointDTO.getCloudProvider(), LibraryInstallDTO.class)
 				.withNotebookImage(userInstance.getImageName())
 				.withApplicationName(getApplicationNameFromImage(userInstance.getImageName()))
 				.withNotebookInstanceName(userInstance.getExploratoryId())
 				.withExploratoryName(userInstance.getExploratoryName())
 				.withProject(userInstance.getProject())
+				.withEndpoint(endpointDTO.getName())
 				.withLibs(libs);
 	}
 
 	@SuppressWarnings("unchecked")
 	public <T extends ExploratoryActionDTO<T>> T newLibExploratoryList(UserInfo userInfo,
-																	   UserInstanceDTO userInstance) {
-		checkInappropriateCloudProviderOrElseThrowException();
-		return (T) newResourceSysBaseDTO(userInfo, ExploratoryActionDTO.class)
+																	   UserInstanceDTO userInstance,
+																	   EndpointDTO endpointDTO) {
+		checkInappropriateCloudProviderOrElseThrowException(endpointDTO.getCloudProvider());
+		return (T) newResourceSysBaseDTO(userInfo, endpointDTO.getCloudProvider(), ExploratoryActionDTO.class)
 				.withNotebookInstanceName(userInstance.getExploratoryId())
 				.withProject(userInstance.getProject())
 				.withNotebookImage(userInstance.getImageName())
@@ -337,13 +292,14 @@ public class RequestBuilder {
 	@SuppressWarnings("unchecked")
 	public <T extends LibraryInstallDTO> T newLibInstall(UserInfo userInfo, UserInstanceDTO userInstance,
 														 UserComputationalResource computationalResource,
-														 List<LibInstallDTO> libs) {
-		checkInappropriateCloudProviderOrElseThrowException();
-		return (T) newResourceSysBaseDTO(userInfo, LibraryInstallDTO.class)
+														 List<LibInstallDTO> libs, EndpointDTO endpointDTO) {
+		checkInappropriateCloudProviderOrElseThrowException(endpointDTO.getCloudProvider());
+		return (T) newResourceSysBaseDTO(userInfo, endpointDTO.getCloudProvider(), LibraryInstallDTO.class)
 				.withComputationalId(computationalResource.getComputationalId())
 				.withComputationalName(computationalResource.getComputationalName())
 				.withExploratoryName(userInstance.getExploratoryName())
 				.withProject(userInstance.getProject())
+				.withEndpoint(endpointDTO.getName())
 				.withComputationalImage(computationalResource.getImageName())
 				.withApplicationName(getApplicationNameFromImage(userInstance.getImageName()))
 				.withLibs(libs);
@@ -353,10 +309,11 @@ public class RequestBuilder {
 	public <T extends LibListComputationalDTO> T newLibComputationalList(UserInfo userInfo,
 																		 UserInstanceDTO userInstance,
 																		 UserComputationalResource
-																				 computationalResource) {
+																				 computationalResource,
+																		 EndpointDTO endpointDTO) {
 
-		checkInappropriateCloudProviderOrElseThrowException();
-		return (T) newResourceSysBaseDTO(userInfo, LibListComputationalDTO.class)
+		checkInappropriateCloudProviderOrElseThrowException(endpointDTO.getCloudProvider());
+		return (T) newResourceSysBaseDTO(userInfo, endpointDTO.getCloudProvider(), LibListComputationalDTO.class)
 				.withComputationalId(computationalResource.getComputationalId())
 				.withProject(userInstance.getProject())
 				.withComputationalImage(computationalResource.getImageName())
@@ -367,15 +324,16 @@ public class RequestBuilder {
 	@SuppressWarnings("unchecked")
 	public <T extends ComputationalBase<T>> T newComputationalCreate(UserInfo userInfo, ProjectDTO projectDTO,
 																	 UserInstanceDTO userInstance,
-																	 ComputationalCreateFormDTO form) {
+																	 ComputationalCreateFormDTO form,
+																	 EndpointDTO endpointDTO) {
 		T computationalCreate;
-
-		switch (cloudProvider()) {
+		CloudProvider cloudProvider = endpointDTO.getCloudProvider();
+		switch (cloudProvider) {
 			case AZURE:
 				throw new UnsupportedOperationException("Creating dataengine service is not supported yet");
 			case AWS:
 				AwsComputationalCreateForm awsForm = (AwsComputationalCreateForm) form;
-				computationalCreate = (T) newResourceSysBaseDTO(userInfo, ComputationalCreateAws.class)
+				computationalCreate = (T) newResourceSysBaseDTO(userInfo, cloudProvider, ComputationalCreateAws.class)
 						.withInstanceCount(awsForm.getInstanceCount())
 						.withMasterInstanceType(awsForm.getMasterInstanceType())
 						.withSlaveInstanceType(awsForm.getSlaveInstanceType())
@@ -387,7 +345,7 @@ public class RequestBuilder {
 				break;
 			case GCP:
 				GcpComputationalCreateForm gcpForm = (GcpComputationalCreateForm) form;
-				computationalCreate = (T) newResourceSysBaseDTO(userInfo, ComputationalCreateGcp.class)
+				computationalCreate = (T) newResourceSysBaseDTO(userInfo, cloudProvider, ComputationalCreateGcp.class)
 						.withMasterInstanceCount(gcpForm.getMasterInstanceCount())
 						.withSlaveInstanceCount(gcpForm.getSlaveInstanceCount())
 						.withPreemptibleCount(gcpForm.getPreemptibleCount())
@@ -398,7 +356,7 @@ public class RequestBuilder {
 				break;
 
 			default:
-				throw new IllegalArgumentException(UNSUPPORTED_CLOUD_PROVIDER_MESSAGE + cloudProvider());
+				throw new IllegalArgumentException(UNSUPPORTED_CLOUD_PROVIDER_MESSAGE + cloudProvider);
 		}
 
 		return computationalCreate
@@ -415,13 +373,14 @@ public class RequestBuilder {
 	@SuppressWarnings("unchecked")
 	public <T extends ComputationalBase<T>> T newComputationalCreate(UserInfo userInfo, ProjectDTO projectDTO,
 																	 UserInstanceDTO userInstance,
-																	 SparkStandaloneClusterCreateForm form) {
+																	 SparkStandaloneClusterCreateForm form,
+																	 EndpointDTO endpointDTO) {
 
 		T computationalCreate;
-
-		switch (cloudProvider()) {
+		CloudProvider cloudProvider = endpointDTO.getCloudProvider();
+		switch (cloudProvider) {
 			case AWS:
-				computationalCreate = (T) newResourceSysBaseDTO(userInfo, SparkComputationalCreateAws.class)
+				computationalCreate = (T) newResourceSysBaseDTO(userInfo, cloudProvider, SparkComputationalCreateAws.class)
 						.withDataEngineInstanceCount(form.getDataEngineInstanceCount())
 						.withDataEngineMasterShape(form.getDataEngineInstanceShape())
 						.withDataEngineSlaveShape(form.getDataEngineInstanceShape())
@@ -429,7 +388,7 @@ public class RequestBuilder {
 						.withSharedImageEnabled(String.valueOf(projectDTO.isSharedImageEnabled()));
 				break;
 			case AZURE:
-				computationalCreate = (T) newResourceSysBaseDTO(userInfo, SparkComputationalCreateAzure.class)
+				computationalCreate = (T) newResourceSysBaseDTO(userInfo, cloudProvider, SparkComputationalCreateAzure.class)
 						.withDataEngineInstanceCount(form.getDataEngineInstanceCount())
 						.withDataEngineMasterSize(form.getDataEngineInstanceShape())
 						.withDataEngineSlaveSize(form.getDataEngineInstanceShape())
@@ -445,7 +404,7 @@ public class RequestBuilder {
 
 				break;
 			case GCP:
-				computationalCreate = (T) newResourceSysBaseDTO(userInfo, SparkComputationalCreateGcp.class)
+				computationalCreate = (T) newResourceSysBaseDTO(userInfo, cloudProvider, SparkComputationalCreateGcp.class)
 						.withDataEngineInstanceCount(form.getDataEngineInstanceCount())
 						.withDataEngineMasterSize(form.getDataEngineInstanceShape())
 						.withDataEngineSlaveSize(form.getDataEngineInstanceShape())
@@ -453,7 +412,7 @@ public class RequestBuilder {
 						.withSharedImageEnabled(String.valueOf(projectDTO.isSharedImageEnabled()));
 				break;
 			default:
-				throw new IllegalArgumentException(UNSUPPORTED_CLOUD_PROVIDER_MESSAGE + cloudProvider());
+				throw new IllegalArgumentException(UNSUPPORTED_CLOUD_PROVIDER_MESSAGE + cloudProvider);
 		}
 
 		return computationalCreate
@@ -470,12 +429,13 @@ public class RequestBuilder {
 	@SuppressWarnings("unchecked")
 	public <T extends ComputationalBase<T>> T newComputationalTerminate(UserInfo userInfo,
 																		UserInstanceDTO userInstanceDTO,
-																		UserComputationalResource computationalResource) {
+																		UserComputationalResource computationalResource,
+																		EndpointDTO endpointDTO) {
 		T computationalTerminate;
-
-		switch (cloudProvider()) {
+		CloudProvider cloudProvider = endpointDTO.getCloudProvider();
+		switch (cloudProvider) {
 			case AWS:
-				AwsComputationalTerminateDTO terminateDTO = newResourceSysBaseDTO(userInfo,
+				AwsComputationalTerminateDTO terminateDTO = newResourceSysBaseDTO(userInfo, cloudProvider,
 						AwsComputationalTerminateDTO.class);
 				if (computationalResource.getDataEngineType() == DataEngineType.CLOUD_SERVICE) {
 					terminateDTO.setClusterName(computationalResource.getComputationalId());
@@ -483,10 +443,10 @@ public class RequestBuilder {
 				computationalTerminate = (T) terminateDTO;
 				break;
 			case AZURE:
-				computationalTerminate = (T) newResourceSysBaseDTO(userInfo, ComputationalTerminateDTO.class);
+				computationalTerminate = (T) newResourceSysBaseDTO(userInfo, cloudProvider, ComputationalTerminateDTO.class);
 				break;
 			case GCP:
-				GcpComputationalTerminateDTO gcpTerminateDTO = newResourceSysBaseDTO(userInfo,
+				GcpComputationalTerminateDTO gcpTerminateDTO = newResourceSysBaseDTO(userInfo, cloudProvider,
 						GcpComputationalTerminateDTO.class);
 				if (computationalResource.getDataEngineType() == DataEngineType.CLOUD_SERVICE) {
 					gcpTerminateDTO.setClusterName(computationalResource.getComputationalId());
@@ -495,7 +455,7 @@ public class RequestBuilder {
 				break;
 
 			default:
-				throw new IllegalArgumentException(UNSUPPORTED_CLOUD_PROVIDER_MESSAGE + cloudProvider());
+				throw new IllegalArgumentException(UNSUPPORTED_CLOUD_PROVIDER_MESSAGE + cloudProvider);
 		}
 
 		return computationalTerminate
@@ -507,10 +467,9 @@ public class RequestBuilder {
 	}
 
 	@SuppressWarnings("unchecked")
-	public <T extends ComputationalBase<T>> T newComputationalStop(UserInfo userInfo,
-																   UserInstanceDTO exploratory,
-																   String computationalName) {
-		return (T) newResourceSysBaseDTO(userInfo, ComputationalStopDTO.class)
+	public <T extends ComputationalBase<T>> T newComputationalStop(UserInfo userInfo, UserInstanceDTO exploratory,
+																   String computationalName, EndpointDTO endpointDTO) {
+		return (T) newResourceSysBaseDTO(userInfo, endpointDTO.getCloudProvider(), ComputationalStopDTO.class)
 				.withExploratoryName(exploratory.getExploratoryName())
 				.withComputationalName(computationalName)
 				.withNotebookInstanceName(exploratory.getExploratoryId())
@@ -520,8 +479,8 @@ public class RequestBuilder {
 
 	@SuppressWarnings("unchecked")
 	public <T extends ComputationalBase<T>> T newComputationalStart(UserInfo userInfo, UserInstanceDTO exploratory,
-																	String computationalName) {
-		return (T) newResourceSysBaseDTO(userInfo, ComputationalStartDTO.class)
+																	String computationalName, EndpointDTO endpointDTO) {
+		return (T) newResourceSysBaseDTO(userInfo, endpointDTO.getCloudProvider(), ComputationalStartDTO.class)
 				.withExploratoryName(exploratory.getExploratoryName())
 				.withComputationalName(computationalName)
 				.withNotebookInstanceName(exploratory.getExploratoryId())
@@ -531,9 +490,9 @@ public class RequestBuilder {
 
 	@SuppressWarnings("unchecked")
 	public <T extends ExploratoryImageDTO> T newExploratoryImageCreate(UserInfo userInfo, UserInstanceDTO userInstance,
-																	   String imageName) {
-		checkInappropriateCloudProviderOrElseThrowException();
-		return (T) newResourceSysBaseDTO(userInfo, ExploratoryImageDTO.class)
+																	   String imageName, EndpointDTO endpointDTO) {
+		checkInappropriateCloudProviderOrElseThrowException(endpointDTO.getCloudProvider());
+		return (T) newResourceSysBaseDTO(userInfo, endpointDTO.getCloudProvider(), ExploratoryImageDTO.class)
 				.withProject(userInstance.getProject())
 				.withNotebookInstanceName(userInstance.getExploratoryId())
 				.withExploratoryName(userInstance.getExploratoryName())
@@ -547,8 +506,8 @@ public class RequestBuilder {
 	@SuppressWarnings("unchecked")
 	public <T extends ComputationalBase<T>> T newComputationalCheckInactivity(UserInfo userInfo,
 																			  UserInstanceDTO exploratory,
-																			  UserComputationalResource cr) {
-		return (T) newResourceSysBaseDTO(userInfo, ComputationalCheckInactivityDTO.class)
+																			  UserComputationalResource cr, EndpointDTO endpointDTO) {
+		return (T) newResourceSysBaseDTO(userInfo, endpointDTO.getCloudProvider(), ComputationalCheckInactivityDTO.class)
 				.withExploratoryName(exploratory.getExploratoryName())
 				.withComputationalName(cr.getComputationalName())
 				.withNotebookInstanceName(exploratory.getExploratoryId())
@@ -576,8 +535,9 @@ public class RequestBuilder {
 
 	public ComputationalClusterConfigDTO newClusterConfigUpdate(UserInfo userInfo, UserInstanceDTO userInstanceDTO,
 																UserComputationalResource compRes,
-																List<ClusterConfig> config) {
-		final ComputationalClusterConfigDTO clusterConfigDTO = newResourceSysBaseDTO(userInfo,
+																List<ClusterConfig> config, EndpointDTO endpointDTO) {
+		CloudProvider cloudProvider = endpointDTO.getCloudProvider();
+		final ComputationalClusterConfigDTO clusterConfigDTO = newResourceSysBaseDTO(userInfo, cloudProvider,
 				ComputationalClusterConfigDTO.class)
 				.withExploratoryName(userInstanceDTO.getExploratoryName())
 				.withNotebookInstanceName(userInstanceDTO.getExploratoryId())
@@ -587,7 +547,7 @@ public class RequestBuilder {
 				.withEndpoint(userInstanceDTO.getEndpoint());
 		clusterConfigDTO.setCopmutationalId(compRes.getComputationalId());
 		clusterConfigDTO.setConfig(config);
-		if (cloudProvider() == AZURE && settingsDAO.isAzureDataLakeEnabled()) {
+		if (cloudProvider == AZURE && settingsDAO.isAzureDataLakeEnabled()) {
 			clusterConfigDTO.setAzureUserRefreshToken(userInfo.getKeys().get(AZURE_REFRESH_TOKEN_KEY));
 		}
 
@@ -596,10 +556,12 @@ public class RequestBuilder {
 
 	public ExploratoryReconfigureSparkClusterActionDTO newClusterConfigUpdate(UserInfo userInfo,
 																			  UserInstanceDTO userInstance,
-																			  List<ClusterConfig> config) {
+																			  List<ClusterConfig> config,
+																			  EndpointDTO endpointDTO) {
 
+		CloudProvider cloudProvider = endpointDTO.getCloudProvider();
 		final ExploratoryReconfigureSparkClusterActionDTO dto =
-				newResourceSysBaseDTO(userInfo, ExploratoryReconfigureSparkClusterActionDTO.class)
+				newResourceSysBaseDTO(userInfo, cloudProvider, ExploratoryReconfigureSparkClusterActionDTO.class)
 						.withNotebookInstanceName(userInstance.getExploratoryId())
 						.withExploratoryName(userInstance.getExploratoryName())
 						.withApplicationName(getApplicationNameFromImage(userInstance.getImageName()))
@@ -607,7 +569,7 @@ public class RequestBuilder {
 						.withConfig(config)
 						.withProject(userInstance.getProject())
 						.withEndpoint(userInstance.getEndpoint());
-		if (cloudProvider() == AZURE && settingsDAO.isAzureDataLakeEnabled()) {
+		if (cloudProvider == AZURE && settingsDAO.isAzureDataLakeEnabled()) {
 			dto.withAzureUserRefreshToken(userInfo.getKeys().get(AZURE_REFRESH_TOKEN_KEY));
 		}
 
@@ -615,8 +577,9 @@ public class RequestBuilder {
 	}
 
 	public ExploratoryCheckInactivityAction newExploratoryCheckInactivityAction(UserInfo userInfo,
-																				UserInstanceDTO userInstance) {
-		final ExploratoryCheckInactivityAction dto = newResourceSysBaseDTO(userInfo,
+																				UserInstanceDTO userInstance,
+																				EndpointDTO endpointDTO) {
+		final ExploratoryCheckInactivityAction dto = newResourceSysBaseDTO(userInfo, endpointDTO.getCloudProvider(),
 				ExploratoryCheckInactivityAction.class);
 		dto.withNotebookInstanceName(userInstance.getExploratoryId())
 				.withNotebookImage(userInstance.getImageName())
@@ -626,23 +589,19 @@ public class RequestBuilder {
 		return dto;
 	}
 
-	public ProjectCreateDTO newProjectCreate(UserInfo userInfo, ProjectDTO projectDTO, String endpoint) {
+	public ProjectCreateDTO newProjectCreate(UserInfo userInfo, ProjectDTO projectDTO, EndpointDTO endpointDTO) {
 		return ProjectCreateDTO.builder()
 				.key(projectDTO.getKey().replace("\n", ""))
 				.name(projectDTO.getName())
 				.tag(projectDTO.getTag())
-				.endpoint(endpoint)
+				.endpoint(endpointDTO.getName())
 				.build()
-				.withCloudSettings(cloudSettings(userInfo));
-	}
-
-	public ProjectActionDTO newProjectAction(UserInfo userInfo, String project, String endpoint) {
-		return new ProjectActionDTO(project, endpoint)
-				.withCloudSettings(cloudSettings(userInfo));
+				.withCloudSettings(cloudSettings(userInfo, endpointDTO.getCloudProvider()));
 	}
 
-	private CloudProvider cloudProvider() {
-		return configuration.getCloudProvider();
+	public ProjectActionDTO newProjectAction(UserInfo userInfo, String project, EndpointDTO endpointDTO) {
+		return new ProjectActionDTO(project, endpointDTO.getName())
+				.withCloudSettings(cloudSettings(userInfo, endpointDTO.getCloudProvider()));
 	}
 
 	/**
@@ -661,8 +620,7 @@ public class RequestBuilder {
 		return "";
 	}
 
-	private void checkInappropriateCloudProviderOrElseThrowException() {
-		CloudProvider provider = cloudProvider();
+	private void checkInappropriateCloudProviderOrElseThrowException(CloudProvider provider) {
 		if (provider != AWS && provider != AZURE && provider != GCP) {
 			throw new IllegalArgumentException(UNSUPPORTED_CLOUD_PROVIDER_MESSAGE + provider);
 		}
diff --git a/services/self-service/src/main/java/com/epam/dlab/backendapi/validation/SelfServiceCloudConfigurationSequenceProvider.java b/services/self-service/src/main/java/com/epam/dlab/backendapi/validation/SelfServiceCloudConfigurationSequenceProvider.java
deleted file mode 100644
index 1fd1748..0000000
--- a/services/self-service/src/main/java/com/epam/dlab/backendapi/validation/SelfServiceCloudConfigurationSequenceProvider.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * 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.validation;
-
-import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
-import com.epam.dlab.validation.CloudConfigurationSequenceProvider;
-
-public class SelfServiceCloudConfigurationSequenceProvider
-        extends CloudConfigurationSequenceProvider<SelfServiceApplicationConfiguration> {
-
-}
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/project/project-form/project-form.component.html b/services/self-service/src/main/resources/webapp/src/app/administration/project/project-form/project-form.component.html
index e278dce..8c18309 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/project/project-form/project-form.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/project/project-form/project-form.component.html
@@ -77,7 +77,7 @@
                   Project name can only contain letters and numbers
                 </span>
                 <span class="error" *ngIf="projectForm?.controls.name.hasError('limit')">
-                  Project name cannot be longer than {{ DICTIONARY.max_project_name_length}} characters
+                  Project name cannot be longer than {{ maxProjectNameLength }} characters
                 </span>
               </div>
             </div>
diff --git a/services/self-service/src/main/resources/webapp/src/app/administration/project/project-form/project-form.component.ts b/services/self-service/src/main/resources/webapp/src/app/administration/project/project-form/project-form.component.ts
index 7ae4aa6..683e7d7 100644
--- a/services/self-service/src/main/resources/webapp/src/app/administration/project/project-form/project-form.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/administration/project/project-form/project-form.component.ts
@@ -46,6 +46,7 @@ export class ProjectFormComponent implements OnInit {
   public projectList: Project[] = [];
   public accessKeyValid: boolean;
   public keyLabel: string = '';
+  public maxProjectNameLength: number = 10;
 
   @Input() item: any;
   @Output() update: EventEmitter<{}> = new EventEmitter();
@@ -204,6 +205,6 @@ export class ProjectFormComponent implements OnInit {
   }
 
   private providerMaxLength(control) {
-    return control.value.length <= DICTIONARY.max_project_name_length ? null : { limit: true };
+    return control.value.length <= this.maxProjectNameLength ? null : { limit: true };
   }
 }
diff --git a/services/self-service/src/main/resources/webapp/src/app/core/services/applicationServiceFacade.service.ts b/services/self-service/src/main/resources/webapp/src/app/core/services/applicationServiceFacade.service.ts
index e37293b..6e2aab3 100644
--- a/services/self-service/src/main/resources/webapp/src/app/core/services/applicationServiceFacade.service.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/core/services/applicationServiceFacade.service.ts
@@ -201,35 +201,35 @@ export class ApplicationServiceFacade {
       data, { responseType: 'text', observe: 'response' });
   }
 
-  public buildCreateComputationalResources_DataengineServiceRequest(data): Observable<any> {
+  public buildCreateComputationalResources_DataengineServiceRequest(data, provider): Observable<any> {
     return this.buildRequest(HTTPMethod.PUT,
-      this.requestRegistry.Item(ApplicationServiceFacade.COMPUTATIONAL_RESOURCES_DATAENGINESERVICE),
+      '/api/' + provider + this.requestRegistry.Item(ApplicationServiceFacade.COMPUTATIONAL_RESOURCES_DATAENGINESERVICE),
       data,
       { observe: 'response' });
   }
 
-  public buildCreateComputationalResources_DataengineRequest(data): Observable<any> {
+  public buildCreateComputationalResources_DataengineRequest(data, provider): Observable<any> {
     return this.buildRequest(HTTPMethod.PUT,
-      this.requestRegistry.Item(ApplicationServiceFacade.COMPUTATIONAL_RESOURCES_DATAENGINE),
+      '/api/' + provider + this.requestRegistry.Item(ApplicationServiceFacade.COMPUTATIONAL_RESOURCES_DATAENGINE),
       data,
       { observe: 'response' });
   }
 
-  public buildDeleteComputationalResourcesRequest(data): Observable<any> {
+  public buildDeleteComputationalResourcesRequest(data, provider): Observable<any> {
     return this.buildRequest(HTTPMethod.DELETE,
-      this.requestRegistry.Item(ApplicationServiceFacade.COMPUTATIONAL_RESOURCES),
+      '/api/' + provider + this.requestRegistry.Item(ApplicationServiceFacade.COMPUTATIONAL_RESOURCES),
       data);
   }
 
-  public buildStopSparkClusterAction(data): Observable<any> {
+  public buildStopSparkClusterAction(data, provider): Observable<any> {
     return this.buildRequest(HTTPMethod.DELETE,
-      this.requestRegistry.Item(ApplicationServiceFacade.COMPUTATIONAL_RESOURCES),
+      '/api/' + provider + this.requestRegistry.Item(ApplicationServiceFacade.COMPUTATIONAL_RESOURCES),
       data);
   }
 
-  public buildStartSparkClusterAction(params): Observable<any> {
+  public buildStartSparkClusterAction(params, provider): Observable<any> {
     return this.buildRequest(HTTPMethod.PUT,
-      this.requestRegistry.Item(ApplicationServiceFacade.COMPUTATIONAL_RESOURCES) + params,
+      '/api/' + provider + this.requestRegistry.Item(ApplicationServiceFacade.COMPUTATIONAL_RESOURCES) + params,
       null);
   }
 
@@ -497,15 +497,15 @@ export class ApplicationServiceFacade {
       data);
   }
 
-  public buildGetClusterConfiguration(param): Observable<any> {
+  public buildGetClusterConfiguration(param, provider): Observable<any> {
     return this.buildRequest(HTTPMethod.GET,
-      this.requestRegistry.Item(ApplicationServiceFacade.COMPUTATIONAL_RESOURCES) + param,
+      '/api/' + provider + this.requestRegistry.Item(ApplicationServiceFacade.COMPUTATIONAL_RESOURCES) + param,
       null);
   }
 
-  public buildEditClusterConfiguration(param, data): Observable<any> {
+  public buildEditClusterConfiguration(param, data, provider): Observable<any> {
     return this.buildRequest(HTTPMethod.PUT,
-      this.requestRegistry.Item(ApplicationServiceFacade.COMPUTATIONAL_RESOURCES) + param,
+      '/api/' + provider + this.requestRegistry.Item(ApplicationServiceFacade.COMPUTATIONAL_RESOURCES) + param,
       data);
   }
 
@@ -631,11 +631,11 @@ export class ApplicationServiceFacade {
 
     // Computational Resources
     this.requestRegistry.Add(ApplicationServiceFacade.COMPUTATIONAL_RESOURCES,
-      '/api/infrastructure_provision/computational_resources');
+      '/infrastructure_provision/computational_resources');
     this.requestRegistry.Add(ApplicationServiceFacade.COMPUTATIONAL_RESOURCES_DATAENGINESERVICE,
-      '/api/infrastructure_provision/computational_resources/dataengine-service'); // emr(aws)
+      '/infrastructure_provision/computational_resources/dataengine-service'); // emr(aws)
     this.requestRegistry.Add(ApplicationServiceFacade.COMPUTATIONAL_RESOURCES_DATAENGINE,
-      '/api/infrastructure_provision/computational_resources/dataengine'); // spark (azure|aws)
+      '/infrastructure_provision/computational_resources/dataengine'); // spark (azure|aws)
 
     this.requestRegistry.Add(ApplicationServiceFacade.COMPUTATIONAL_RESOURCES_TEMLATES,
       '/api/infrastructure_templates/computational_templates');
diff --git a/services/self-service/src/main/resources/webapp/src/app/core/services/dataengineConfiguration.service.ts b/services/self-service/src/main/resources/webapp/src/app/core/services/dataengineConfiguration.service.ts
index 5dcef3e..fe61c75 100644
--- a/services/self-service/src/main/resources/webapp/src/app/core/services/dataengineConfiguration.service.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/core/services/dataengineConfiguration.service.ts
@@ -28,19 +28,19 @@ import { ErrorUtils } from '../util';
 export class DataengineConfigurationService {
   constructor(private applicationServiceFacade: ApplicationServiceFacade) {}
 
-  public getClusterConfiguration(exploratory, cluster): Observable<{}> {
+  public getClusterConfiguration(exploratory, cluster, provider): Observable<{}> {
     const url = `/${exploratory}/${cluster}/config`;
     return this.applicationServiceFacade
-      .buildGetClusterConfiguration(url)
+      .buildGetClusterConfiguration(url, provider)
       .pipe(
         map(response => response),
         catchError(ErrorUtils.handleServiceError));
   }
 
-  public editClusterConfiguration(data, exploratory, cluster): Observable<{}> {
+  public editClusterConfiguration(data, exploratory, cluster, provider): Observable<{}> {
     const url = `/dataengine/${exploratory}/${cluster}/config`;
     return this.applicationServiceFacade
-      .buildEditClusterConfiguration(url, data)
+      .buildEditClusterConfiguration(url, data, provider)
       .pipe(
         map(response => response),
         catchError(ErrorUtils.handleServiceError));
diff --git a/services/self-service/src/main/resources/webapp/src/app/core/services/userResource.service.ts b/services/self-service/src/main/resources/webapp/src/app/core/services/userResource.service.ts
index 496ad28..04acbb8 100644
--- a/services/self-service/src/main/resources/webapp/src/app/core/services/userResource.service.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/core/services/userResource.service.ts
@@ -82,44 +82,44 @@ export class UserResourceService {
         catchError(ErrorUtils.handleServiceError));
   }
 
-  public createComputationalResource_DataengineService(data): Observable<{}> {
+  public createComputationalResource_DataengineService(data, provider): Observable<{}> {
     const body = JSON.stringify(data);
     return this.applicationServiceFacade
-      .buildCreateComputationalResources_DataengineServiceRequest(body)
+      .buildCreateComputationalResources_DataengineServiceRequest(body, provider)
       .pipe(
         map(response => response),
         catchError(ErrorUtils.handleServiceError));
   }
 
-  public createComputationalResource_Dataengine(data): Observable<{}> {
+  public createComputationalResource_Dataengine(data, provider): Observable<{}> {
     const body = JSON.stringify(data);
     return this.applicationServiceFacade
-      .buildCreateComputationalResources_DataengineRequest(body)
+      .buildCreateComputationalResources_DataengineRequest(body, provider)
       .pipe(
         map(response => response),
         catchError(ErrorUtils.handleServiceError));
   }
 
-  public suspendComputationalResource(notebookName: string, computationalResourceName: string): Observable<{}> {
+  public suspendComputationalResource(notebookName: string, computationalResourceName: string, provider: string): Observable<{}> {
     const body = JSON.stringify('/' + notebookName + '/' + computationalResourceName + '/terminate');
     return this.applicationServiceFacade
-      .buildDeleteComputationalResourcesRequest(body)
+      .buildDeleteComputationalResourcesRequest(body, provider)
       .pipe(
         map(response => response),
         catchError(ErrorUtils.handleServiceError));
   }
 
-  public toggleStopStartAction(project: string, notebook: string, resource: string, action): Observable<{}> {
+  public toggleStopStartAction(project: string, notebook: string, resource: string, action, provider: string): Observable<{}> {
     const url = `/${project}/${notebook}/${resource}/${action}`;
     if (action === 'stop') {
       return this.applicationServiceFacade
-        .buildStopSparkClusterAction(JSON.stringify(url))
+        .buildStopSparkClusterAction(JSON.stringify(url), provider)
         .pipe(
           map(response => response),
           catchError(ErrorUtils.handleServiceError));
     } else if (action === 'start') {
       return this.applicationServiceFacade
-        .buildStartSparkClusterAction(url)
+        .buildStartSparkClusterAction(url, provider)
         .pipe(
           map(response => response),
           catchError(ErrorUtils.handleServiceError));
diff --git a/services/self-service/src/main/resources/webapp/src/app/login/login.component.html b/services/self-service/src/main/resources/webapp/src/app/login/login.component.html
index 2266df3..d87e1d1 100644
--- a/services/self-service/src/main/resources/webapp/src/app/login/login.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/login/login.component.html
@@ -23,7 +23,7 @@
       <img src="assets/img/logo.png" alt="">
     </a>
     <form name="form" class="form-wrap" #f="ngForm" novalidate>
-      <!-- 
+      <!--
       <div class="input-icon-group">
         <span class="input-icon"><span class="login-icon icon-username"></span></span>
         <input type="text" class="input-with-icon" name="username" [(ngModel)]="model.username" [pattern]="userPattern" #username="ngModel" placeholder="Username" required />
@@ -34,8 +34,8 @@
         <input type="password" class="input-with-icon" placeholder="Password" name="password" [(ngModel)]="model.password" #password="ngModel" required />
       </div>
 
-      
-      <div class="form-group" [ngClass]="{'flex': DICTIONARY.cloud_provider === 'azure'}">
+
+      <div class="form-group" [ngClass]="{'flex': DICTIONARY['aws'].cloud_provider === 'azure'}">
         <button mat-raised-button [disabled]="loading || !username.valid || !password.valid"
                 (click)="login_btnClick();"
                 class="butt butt-login"
@@ -50,7 +50,7 @@
               </span>
             </span>
         </button>
-        <button *ngIf="DICTIONARY.cloud_provider === 'azure' && !DICTIONARY.use_ldap"
+        <button *ngIf="DICTIONARY['aws'].cloud_provider === 'azure' && !DICTIONARY['aws'].use_ldap"
                 class="butt butt-azure"
                 mat-raised-button (click)="loginWithAzure_btnClick();">
           Login with Azure
diff --git a/services/self-service/src/main/resources/webapp/src/app/login/login.component.ts b/services/self-service/src/main/resources/webapp/src/app/login/login.component.ts
index 64314c6..bc50072 100644
--- a/services/self-service/src/main/resources/webapp/src/app/login/login.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/login/login.component.ts
@@ -22,7 +22,6 @@ import { Subscription } from 'rxjs';
 
 import { LoginModel } from './login.model';
 import { AppRoutingService, HealthStatusService, ApplicationSecurityService } from '../core/services';
-import { HTTP_STATUS_CODES } from '../core/util';
 import { DICTIONARY } from '../../dictionary/global.dictionary';
 
 @Component({
@@ -69,12 +68,8 @@ export class LoginComponent implements OnInit, OnDestroy {
 
         return false;
       }, error => {
-        if (DICTIONARY.cloud_provider === 'azure' && error && error.status === HTTP_STATUS_CODES.FORBIDDEN) {
-          window.location.href = error.headers.get('Location');
-        } else {
           this.error = error.message;
           this.loading = false;
-        }
       });
 
     return false;
diff --git a/services/self-service/src/main/resources/webapp/src/app/reporting/reporting-grid/reporting-grid.component.html b/services/self-service/src/main/resources/webapp/src/app/reporting/reporting-grid/reporting-grid.component.html
index f9bf7cf..07b423b 100644
--- a/services/self-service/src/main/resources/webapp/src/app/reporting/reporting-grid/reporting-grid.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/reporting/reporting-grid/reporting-grid.component.html
@@ -30,7 +30,7 @@
           </i>
         </button>
       </th>
-      <td mat-cell *matCellDef="let element"> {{element[DICTIONARY.billing.dlabId]}} </td>
+      <td mat-cell *matCellDef="let element"> {{element[DICTIONARY['aws'].billing.dlabId]}} </td>
       <td mat-footer-cell *matFooterCellDef> Total </td>
     </ng-container>
 
@@ -72,7 +72,7 @@
           </i>
         </button>
       </th>
-      <td mat-cell *matCellDef="let element"> {{element[DICTIONARY.billing.resourceType]}} </td>
+      <td mat-cell *matCellDef="let element"> {{element[DICTIONARY['aws'].billing.resourceType]}} </td>
       <td mat-footer-cell *matFooterCellDef></td>
     </ng-container>
 
@@ -96,34 +96,34 @@
 
     <ng-container matColumnDef="shape">
       <th mat-header-cell *matHeaderCellDef class="th_shape">
-        <span class="label"> {{ DICTIONARY.instance_size}} </span>
+        <span class="label"> Instance size</span>
         <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()">
           <i class="material-icons">
             <span
-              *ngIf="filteredReportData[DICTIONARY.billing.instance_size].length > 0; else shape_filtered">filter_list</span>
+              *ngIf="filteredReportData['shape'].length > 0; else shape_filtered">filter_list</span>
             <ng-template #shape_filtered>more_vert</ng-template>
           </i>
         </button>
       </th>
       <td mat-cell *matCellDef="let element">
-        <span [outerHTML]="element[DICTIONARY.billing.instance_size] | lineBreak"></span>
+        <span [outerHTML]="element['shape'] | lineBreak"></span>
       </td>
       <td mat-footer-cell *matFooterCellDef></td>
     </ng-container>
 
     <ng-container matColumnDef="service">
       <th mat-header-cell *matHeaderCellDef class="service">
-        <span class="label"> {{ DICTIONARY.service}} </span>
+        <span class="label"> Service </span>
         <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()">
           <i class="material-icons">
             <span
-              *ngIf="filteredReportData[DICTIONARY.billing.instance_size].length > 0; else service_filtered">filter_list</span>
+              *ngIf="filteredReportData['shape'].length > 0; else service_filtered">filter_list</span>
             <ng-template #service_filtered>more_vert</ng-template>
           </i>
         </button>
       </th>
       <td mat-cell *matCellDef="let element">
-        {{ element[DICTIONARY.billing.service] }}
+        {{ element['service'] }}
         <span *ngIf="element.resource_type">({{ element.resource_type }})</span>
       </td>
       <td mat-footer-cell *matFooterCellDef></td>
@@ -135,11 +135,11 @@
       </th>
 
       <td mat-cell *matCellDef="let element">
-        {{ element[DICTIONARY.billing.cost] }} {{ element[DICTIONARY.billing.currencyCode] }}
+        {{ element[DICTIONARY['aws'].billing.cost] }} {{ element[DICTIONARY['aws'].billing.currencyCode] }}
       </td>
       <td mat-footer-cell *matFooterCellDef>
-        <span *ngIf="reportData?.length">{{ fullReport[DICTIONARY.billing.costTotal] }}
-          {{ fullReport[DICTIONARY.billing.currencyCode] }}</span>
+        <span *ngIf="reportData?.length">{{ fullReport['cost_total'] }}
+          {{ fullReport[DICTIONARY['aws'].billing.currencyCode] }}</span>
       </td>
     </ng-container>
 
@@ -178,16 +178,16 @@
     <ng-container matColumnDef="shape-filter">
       <th mat-header-cell *matHeaderCellDef>
         <multi-select-dropdown *ngIf="filterConfiguration" (selectionChange)="onUpdate($event)"
-          [type]="[DICTIONARY.billing.instance_size]" [items]="filterConfiguration[DICTIONARY.billing.instance_size]"
-          [model]="filteredReportData[DICTIONARY.billing.instance_size]"></multi-select-dropdown>
+          [type]="[DICTIONARY['aws'].billing.instance_size]" [items]="filterConfiguration[DICTIONARY['aws'].billing.instance_size]"
+          [model]="filteredReportData[DICTIONARY['aws'].billing.instance_size]"></multi-select-dropdown>
       </th>
     </ng-container>
     <ng-container matColumnDef="service-filter">
       <th mat-header-cell *matHeaderCellDef>
         <multi-select-dropdown *ngIf="filterConfiguration" (selectionChange)="onUpdate($event)"
-          [type]="[DICTIONARY.billing.service_filter_key]"
-          [items]="filterConfiguration[DICTIONARY.billing.service_filter_key]"
-          [model]="filteredReportData[DICTIONARY.billing.service_filter_key]"></multi-select-dropdown>
+          [type]="['service']"
+          [items]="filterConfiguration['service']"
+          [model]="filteredReportData['service']"></multi-select-dropdown>
       </th>
     </ng-container>
     <ng-container matColumnDef="actions" stickyEnd>
diff --git a/services/self-service/src/main/resources/webapp/src/app/reporting/reporting.component.ts b/services/self-service/src/main/resources/webapp/src/app/reporting/reporting.component.ts
index 63257d5..033724b 100644
--- a/services/self-service/src/main/resources/webapp/src/app/reporting/reporting.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/reporting/reporting.component.ts
@@ -95,8 +95,8 @@ export class ReportingComponent implements OnInit, OnDestroy {
         this.reportingToolbar.reportData = this.data;
         if (!localStorage.getItem('report_period')) {
           localStorage.setItem('report_period', JSON.stringify({
-            start_date: this.data[DICTIONARY.billing.dateFrom],
-            end_date: this.data[DICTIONARY.billing.dateTo]
+            start_date: this.data['from'],
+            end_date: this.data['to']
           }));
           this.reportingToolbar.setDateRange();
         }
@@ -140,30 +140,30 @@ export class ReportingComponent implements OnInit, OnDestroy {
       if (item.project && projects.indexOf(item.project) === -1)
         projects.push(item.project);
 
-      if (item[DICTIONARY.billing.resourceType] && types.indexOf(item[DICTIONARY.billing.resourceType]) === -1)
-        types.push(item[DICTIONARY.billing.resourceType]);
+      if (item[DICTIONARY['aws'].billing.resourceType] && types.indexOf(item[DICTIONARY['aws'].billing.resourceType]) === -1)
+        types.push(item[DICTIONARY['aws'].billing.resourceType]);
 
-      if (item[DICTIONARY.billing.instance_size]) {
-        if (item[DICTIONARY.billing.instance_size].indexOf('Master') > -1) {
-          for (let shape of item[DICTIONARY.billing.instance_size].split('\n')) {
+      if (item[DICTIONARY['aws'].billing.instance_size]) {
+        if (item[DICTIONARY['aws'].billing.instance_size].indexOf('Master') > -1) {
+          for (let shape of item[DICTIONARY['aws'].billing.instance_size].split('\n')) {
             shape = shape.replace('Master: ', '');
             shape = shape.replace(/Slave:\s+\d+ x /, '');
             shape = shape.replace(/\s+/g, '');
 
             shapes.indexOf(shape) === -1 && shapes.push(shape);
           }
-        } else if (item[DICTIONARY.billing.instance_size].match(/\d x \S+/)) {
-          const parsedShape = item[DICTIONARY.billing.instance_size].match(/\d x \S+/)[0].split(' x ')[1];
+        } else if (item[DICTIONARY['aws'].billing.instance_size].match(/\d x \S+/)) {
+          const parsedShape = item[DICTIONARY['aws'].billing.instance_size].match(/\d x \S+/)[0].split(' x ')[1];
           if (shapes.indexOf(parsedShape) === -1) {
             shapes.push(parsedShape);
           }
         } else {
-          shapes.indexOf(item[DICTIONARY.billing.instance_size]) === -1 && shapes.push(item[DICTIONARY.billing.instance_size]);
+          shapes.indexOf(item[DICTIONARY['aws'].billing.instance_size]) === -1 && shapes.push(item[DICTIONARY['aws'].billing.instance_size]);
         }
       }
 
-      if (item[DICTIONARY.billing.service] && services.indexOf(item[DICTIONARY.billing.service]) === -1)
-        services.push(item[DICTIONARY.billing.service]);
+      if (item[DICTIONARY['aws'].billing.service] && services.indexOf(item[DICTIONARY['aws'].billing.service]) === -1)
+        services.push(item[DICTIONARY['aws'].billing.service]);
     });
 
     if (!this.reportingGrid.filterConfiguration || !localStorage.getItem('report_config')) {
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/computational/cluster-details/cluster-details.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/computational/cluster-details/cluster-details.component.html
index 41c145e..04ea086 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/computational/cluster-details/cluster-details.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/computational/cluster-details/cluster-details.component.html
@@ -35,7 +35,7 @@
               {{resource.status}}
             </span>
           </td>
-          <td>{{ resource[DICTIONARY[resource.image].master_node_shape] }}</td>
+          <td>{{ resource[DICTIONARY[PROVIDER][resource.image].master_node_shape] }}</td>
         </tr>
       </table>
       <div class="detail-info content-box" *ngIf="!resource.error_message">
@@ -49,7 +49,7 @@
           <div class="col">
             <p>Cluster version:</p>
           </div>
-          <div class="col"><span>{{ resource[DICTIONARY.cluster_version] }}</span></div>
+          <div class="col"><span>{{ resource[DICTIONARY[PROVIDER].cluster_version] }}</span></div>
         </div>
         <div class="row-wrap">
           <div class="col">
@@ -63,34 +63,34 @@
         </div>
         <div class="row-wrap">
           <div class="col"
-            *ngIf="DICTIONARY.cloud_provider === 'gcp' && resource.image === 'docker.dlab-dataengine-service'; else inst">
-            <p>{{ DICTIONARY[resource.image].master_instance_number }}:</p>
+            *ngIf="DICTIONARY[PROVIDER].cloud_provider === 'gcp' && resource.image === 'docker.dlab-dataengine-service'; else inst">
+            <p>Master instance number:</p>
           </div>
           <ng-template #inst>
             <div class="col">
-              <p>{{ DICTIONARY[resource.image].instance_number }}:</p>
+              <p>Total instance number:</p>
             </div>
           </ng-template>
-          <div class="col"><span>{{ resource[DICTIONARY[resource.image].total_instance_number] }}</span></div>
+          <div class="col"><span>{{ resource[DICTIONARY[PROVIDER][resource.image].total_instance_number] }}</span></div>
         </div>
         <div class="row-wrap"
-          *ngIf="DICTIONARY.cloud_provider === 'gcp' && resource.image === 'docker.dlab-dataengine-service'">
+          *ngIf="DICTIONARY[PROVIDER].cloud_provider === 'gcp' && resource.image === 'docker.dlab-dataengine-service'">
           <div class="col">
-            <p>{{ DICTIONARY[resource.image].slave_instance_number }}:</p>
+            <p>Slave instance number:</p>
           </div>
-          <div class="col"><span>{{ resource[DICTIONARY[resource.image].total_slave_instance_number] }}</span></div>
+          <div class="col"><span>{{ resource[DICTIONARY[PROVIDER][resource.image].total_slave_instance_number] }}</span></div>
         </div>
         <div class="row-wrap">
           <div class="col">
-            <p>{{ DICTIONARY[resource.image].data_engine_master_instance_size }}:</p>
+            <p>Master instance size:</p>
           </div>
-          <div class="col"><span>{{ resource[DICTIONARY[resource.image].master_node_shape] }}</span></div>
+          <div class="col"><span>{{ resource[DICTIONARY[PROVIDER][resource.image].master_node_shape] }}</span></div>
         </div>
         <div class="row-wrap" *ngIf="resource.image === 'docker.dlab-dataengine-service'">
           <div class="col">
-            <p>{{ DICTIONARY[resource.image].data_engine_slave_instance_size }}:</p>
+            <p>Slave instance size:</p>
           </div>
-          <div class="col"><span>{{ resource[DICTIONARY[resource.image].slave_node_shape] }}</span></div>
+          <div class="col"><span>{{ resource[DICTIONARY[PROVIDER][resource.image].slave_node_shape] }}</span></div>
         </div>
 
         <div *ngIf="resource.status === 'running'">
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/computational/cluster-details/cluster-details.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/computational/cluster-details/cluster-details.component.ts
index cc0211b..75ea01e 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/computational/cluster-details/cluster-details.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/computational/cluster-details/cluster-details.component.ts
@@ -35,6 +35,7 @@ import { CLUSTER_CONFIGURATION } from '../computational-resource-create-dialog/c
 
 export class DetailComputationalResourcesComponent implements OnInit {
   readonly DICTIONARY = DICTIONARY;
+  readonly PROVIDER = this.data.environment.cloud_provider;
 
   resource: any;
   environment: any;
@@ -55,7 +56,9 @@ export class DetailComputationalResourcesComponent implements OnInit {
   ) { }
 
   ngOnInit() {
-    this.open(this.data.environment, this.data.resource)
+    this.open(this.data.environment, this.data.resource);
+
+    console.log(this.PROVIDER);
   }
 
   public open(environment, resource): void {
@@ -63,6 +66,7 @@ export class DetailComputationalResourcesComponent implements OnInit {
     this.resource = resource;
     this.environment = environment;
 
+
     this.upTimeInHours = (this.resource.up_time) ? DateUtils.diffBetweenDatesInHours(this.resource.up_time) : 0;
     this.upTimeSince = (this.resource.up_time) ? new Date(this.resource.up_time).toString() : '';
     this.initFormModel();
@@ -87,14 +91,14 @@ export class DetailComputationalResourcesComponent implements OnInit {
 
   public getClusterConfiguration(): void {
     this.dataengineConfigurationService
-      .getClusterConfiguration(this.environment.name, this.resource.computational_name)
+      .getClusterConfiguration(this.environment.name, this.resource.computational_name, this.PROVIDER)
       .subscribe((result: any) => this.config = result,
         error => this.toastr.error(error.message || 'Configuration loading failed!', 'Oops!'));
   }
 
   public editClusterConfiguration(data): void {
     this.dataengineConfigurationService
-      .editClusterConfiguration(data.configuration_parameters, this.environment.name, this.resource.computational_name)
+      .editClusterConfiguration(data.configuration_parameters, this.environment.name, this.resource.computational_name, this.PROVIDER)
       .subscribe(result => {
         this.dialogRef.close();
       },
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resource-create-dialog/computational-resource-create-dialog.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resource-create-dialog/computational-resource-create-dialog.component.html
index 0bbc0e8..3cae0dc 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resource-create-dialog/computational-resource-create-dialog.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resource-create-dialog/computational-resource-create-dialog.component.html
@@ -78,7 +78,7 @@
                 <span class="error" *ngIf="!resourceForm?.controls.cluster_alias_name.valid
                                             && resourceForm?.controls['cluster_alias_name'].dirty
                                             && !resourceForm?.controls['cluster_alias_name'].hasError('duplication')">
-                  Cluster name cannot be longer than {{DICTIONARY.max_cluster_name_length}} characters
+                  Cluster name cannot be longer than {{DICTIONARY[PROVIDER].max_cluster_name_length}} characters
                   and can only contain letters, numbers, hyphens and '_' but can not end with special
                   characters
                 </span>
@@ -88,7 +88,7 @@
 
           <div class="col">
             <div class="control-group" *ngIf="selectedImage?.image">
-              <label class="label">{{ DICTIONARY[selectedImage.image].instance_number }}</label>
+              <label class="label">Total instance number</label>
               <div class="control">
                 <input type="number" class="form-control" min="{{minInstanceNumber}}" max="{{maxInstanceNumber}}"
                   formControlName="instance_number" (keypress)="CheckUtils.isNumberKey($event)" />
@@ -100,10 +100,11 @@
             </div>
 
             <div class="control-group" *ngIf="selectedImage?.image">
-              <label class="label">{{ DICTIONARY[selectedImage.image].data_engine_master_instance_size }}</label>
+              <label class="label">Master instance size</label>
               <div class="control selector-wrapper">
                 <mat-form-field>
-                  <mat-select formControlName="shape_master" disableOptionCentering placeholder="Select {{ DICTIONARY.notebook_instance_size }}">
+                  <mat-label>Select instance size</mat-label>
+                  <mat-select formControlName="shape_master" disableOptionCentering>
                     <mat-optgroup *ngFor="let item of (selectedImage.computation_resources_shapes | keys)"
                       [label]="item.key | underscoreless">
                       <mat-option *ngFor="let list_item of item.value" [value]="list_item.Type">
@@ -120,7 +121,7 @@
 
             <div class="control-group" *ngIf="selectedImage?.image"
               [hidden]="selectedImage?.image === 'docker.dlab-dataengine'">
-              <label class="label">{{ DICTIONARY[selectedImage.image].data_engine_slave_instance_size }}</label>
+              <label class="label">Slave instance size</label>
               <div class="control selector-wrapper">
                 <mat-form-field>
                   <mat-label>Select cluster type</mat-label>
@@ -193,7 +194,7 @@
           </label>
           <div class="config-link" *ngIf="(configuration?.nativeElement['checked'] || false)
             && selectedImage?.image === 'docker.dlab-dataengine-service'
-            && DICTIONARY.cloud_provider === 'aws'">
+            && PROVIDER === 'aws'">
             To view example JSON of configurations refer for <a
               href="https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-configure-apps.html" target="_blank">AWS
               official documentation</a>
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resource-create-dialog/computational-resource-create-dialog.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resource-create-dialog/computational-resource-create-dialog.component.ts
index ee748d6..52731b2 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resource-create-dialog/computational-resource-create-dialog.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resource-create-dialog/computational-resource-create-dialog.component.ts
@@ -36,7 +36,7 @@ import { CLUSTER_CONFIGURATION } from './cluster-configuration-templates';
 })
 
 export class ComputationalResourceCreateDialogComponent implements OnInit {
-  readonly PROVIDER = DICTIONARY.cloud_provider;
+  readonly PROVIDER = this.data.notebook.cloud_provider;
   readonly DICTIONARY = DICTIONARY;
   readonly CLUSTER_CONFIGURATION = CLUSTER_CONFIGURATION;
   readonly CheckUtils = CheckUtils;
@@ -123,14 +123,14 @@ export class ComputationalResourceCreateDialogComponent implements OnInit {
   }
 
   public isAvailableSpots(): boolean {
-    if (DICTIONARY.cloud_provider === 'aws' && this.selectedImage.image === 'docker.dlab-dataengine-service')
+    if (this.PROVIDER === 'aws' && this.selectedImage.image === 'docker.dlab-dataengine-service')
       return !!Object.keys(this.filterAvailableSpots()).length;
 
     return false;
   }
 
   public createComputationalResource(data) {
-    this.model.createComputationalResource(data, this.selectedImage, this.notebook_instance, this.spotInstance)
+    this.model.createComputationalResource(data, this.selectedImage, this.notebook_instance, this.spotInstance, this.PROVIDER.toLowerCase())
       .subscribe((response: any) => {
         if (response.status === HTTP_STATUS_CODES.OK) this.dialogRef.close();
       }, error => this.toastr.error(error.message, 'Oops!'));
@@ -142,10 +142,12 @@ export class ComputationalResourceCreateDialogComponent implements OnInit {
       version: [''],
       shape_master: ['', Validators.required],
       shape_slave: ['', Validators.required],
-      cluster_alias_name: ['', [Validators.required, Validators.pattern(PATTERNS.namePattern), Validators.maxLength(DICTIONARY.max_cluster_name_length),
+      cluster_alias_name: ['', [Validators.required, Validators.pattern(PATTERNS.namePattern), Validators.maxLength(DICTIONARY[this.PROVIDER].max_cluster_name_length),
       this.checkDuplication.bind(this)]],
       instance_number: ['', [Validators.required, Validators.pattern(PATTERNS.nodeCountPattern), this.validInstanceNumberRange.bind(this)]],
-      preemptible_instance_number: [0, Validators.compose([Validators.pattern(PATTERNS.integerRegex), this.validPreemptibleRange.bind(this)])],
+      preemptible_instance_number: [0,
+        Validators.compose([Validators.pattern(PATTERNS.integerRegex),
+        this.validPreemptibleRange.bind(this)])],
       instance_price: [0, [this.validInstanceSpotRange.bind(this)]],
       configuration_parameters: ['', [this.validConfiguration.bind(this)]],
       custom_tag: [this.notebook_instance.tags.custom_tag]
@@ -169,17 +171,17 @@ export class ComputationalResourceCreateDialogComponent implements OnInit {
 
   private getComputationalResourceLimits(): void {
     if (this.selectedImage && this.selectedImage.image) {
-      const activeImage = DICTIONARY[this.selectedImage.image];
+      const activeImage = DICTIONARY[this.PROVIDER][this.selectedImage.image];
 
       this.minInstanceNumber = this.selectedImage.limits[activeImage.total_instance_number_min];
       this.maxInstanceNumber = this.selectedImage.limits[activeImage.total_instance_number_max];
 
-      if (DICTIONARY.cloud_provider === 'gcp' && this.selectedImage.image === 'docker.dlab-dataengine-service') {
+      if (this.PROVIDER === 'gcp' && this.selectedImage.image === 'docker.dlab-dataengine-service') {
         this.maxInstanceNumber = this.selectedImage.limits[activeImage.total_instance_number_max] - 1;
         this.minPreemptibleInstanceNumber = this.selectedImage.limits.min_dataproc_preemptible_instance_count;
       }
 
-      if (DICTIONARY.cloud_provider === 'aws' && this.selectedImage.image === 'docker.dlab-dataengine-service') {
+      if (this.PROVIDER === 'aws' && this.selectedImage.image === 'docker.dlab-dataengine-service') {
         this.minSpotPrice = this.selectedImage.limits.min_emr_spot_instance_bid_pct;
         this.maxSpotPrice = this.selectedImage.limits.max_emr_spot_instance_bid_pct;
 
@@ -195,7 +197,7 @@ export class ComputationalResourceCreateDialogComponent implements OnInit {
   //  Validation
   private validInstanceNumberRange(control) {
     if (control && control.value)
-      if (DICTIONARY.cloud_provider === 'gcp' && this.selectedImage.image === 'docker.dlab-dataengine-service') {
+      if (this.PROVIDER === 'gcp' && this.selectedImage.image === 'docker.dlab-dataengine-service') {
         this.validPreemptibleNumberRange();
         return control.value >= this.minInstanceNumber && control.value <= this.maxInstanceNumber ? null : { valid: false };
       } else {
@@ -274,7 +276,7 @@ export class ComputationalResourceCreateDialogComponent implements OnInit {
           return obj;
         }, {});
 
-      if (DICTIONARY.cloud_provider !== 'azure') {
+      if (this.PROVIDER !== 'azure') {
         const images = this.clusterTypes.filter(image => image.image === 'docker.dlab-dataengine');
         this.clusterTypes = images;
         this.selectedImage = this.clusterTypes[0];
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resource-create-dialog/computational-resource-create.model.ts b/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resource-create-dialog/computational-resource-create.model.ts
index b5a1a32..a64857d 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resource-create-dialog/computational-resource-create.model.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resource-create-dialog/computational-resource-create.model.ts
@@ -22,17 +22,16 @@ import { Injectable } from '@angular/core';
 import { Observable } from 'rxjs';
 
 import { UserResourceService } from '../../../core/services';
-import { DICTIONARY } from '../../../../dictionary/global.dictionary';
 
 @Injectable()
 export class ComputationalResourceModel {
 
   constructor(private userResourceService: UserResourceService) { }
 
-  public createComputationalResource(parameters, image, env, spot): Observable<{}> {
+  public createComputationalResource(parameters, image, env, spot, provider): Observable<{}> {
     const config = parameters.configuration_parameters ? JSON.parse(parameters.configuration_parameters) : null;
 
-    if (DICTIONARY.cloud_provider === 'aws' && image.image === 'docker.dlab-dataengine-service') {
+    if (provider === 'aws' && image.image === 'docker.dlab-dataengine-service') {
       return this.userResourceService.createComputationalResource_DataengineService({
         name: parameters.cluster_alias_name,
         emr_instance_count: parameters.instance_number,
@@ -47,8 +46,8 @@ export class ComputationalResourceModel {
         config: config,
         project: env.project,
         custom_tag: parameters.custom_tag
-      });
-    } else if (DICTIONARY.cloud_provider === 'gcp' && image.image === 'docker.dlab-dataengine-service') {
+      }, provider);
+    } else if (provider=== 'gcp' && image.image === 'docker.dlab-dataengine-service') {
       return this.userResourceService.createComputationalResource_DataengineService({
         template_name: image.template_name,
         image: image.image,
@@ -63,7 +62,7 @@ export class ComputationalResourceModel {
         config: config,
         project: env.project,
         custom_tag: parameters.custom_tag
-      });
+      }, provider);
     } else {
       return this.userResourceService.createComputationalResource_Dataengine({
         name: parameters.cluster_alias_name,
@@ -75,7 +74,7 @@ export class ComputationalResourceModel {
         config: config,
         project: env.project,
         custom_tag: parameters.custom_tag
-      });
+      }, provider);
     }
   }
 }
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resources-list/computational-resources-list.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resources-list/computational-resources-list.component.ts
index bd175a6..f7bfa1d 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resources-list/computational-resources-list.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/computational/computational-resources-list/computational-resources-list.component.ts
@@ -54,13 +54,13 @@ export class ComputationalResourcesListComponent {
       dialogRef.afterClosed().subscribe(result => {
         if (result && action === 'stop') {
           this.userResourceService
-            .toggleStopStartAction(this.environment.project, this.environment.name, resource.computational_name, action)
+            .toggleStopStartAction(this.environment.project, this.environment.name, resource.computational_name, action, this.environment.cloud_provider)
             .subscribe(() => {
               this.rebuildGrid();
             });
         } else if (result && action === 'terminate') {
           this.userResourceService
-            .suspendComputationalResource(this.environment.name, resource.computational_name)
+            .suspendComputationalResource(this.environment.name, resource.computational_name, this.environment.cloud_provider)
             .subscribe(() => {
               this.rebuildGrid();
             });
@@ -68,7 +68,7 @@ export class ComputationalResourcesListComponent {
       });
     } else if (action === 'start') {
       this.userResourceService
-        .toggleStopStartAction(this.environment.project, this.environment.name, resource.computational_name, 'start')
+        .toggleStopStartAction(this.environment.project, this.environment.name, resource.computational_name, 'start', this.environment.cloud_provider)
         .subscribe(
           () => this.rebuildGrid(),
           error => this.toastr.error(error.message || 'Computational resource starting failed!', 'Oops!'));
@@ -76,12 +76,14 @@ export class ComputationalResourcesListComponent {
   }
 
   public detailComputationalResources(environment, resource): void {
-    this.dialog.open(DetailComputationalResourcesComponent, { data: { environment, resource }, panelClass: 'modal-sm' })
+    this.dialog.open(DetailComputationalResourcesComponent, { data:
+        { environment, resource }, panelClass: 'modal-sm' })
       .afterClosed().subscribe(() => this.rebuildGrid());
-  };
+  }
 
   public openScheduleDialog(resource) {
-    this.dialog.open(SchedulerComponent, { data: { notebook: this.environment, type: 'СOMPUTATIONAL', resource }, panelClass: 'modal-xl-s' })
+    this.dialog.open(SchedulerComponent, { data:
+        { notebook: this.environment, type: 'СOMPUTATIONAL', resource }, panelClass: 'modal-xl-s' })
       .afterClosed().subscribe(() => this.rebuildGrid());
   }
 }
@@ -100,9 +102,9 @@ export class ComputationalResourcesListComponent {
           <span class="strong" matTooltip="{{ data.resource.computational_name }}"
                   [matTooltipShowDelay]="2000"
                   matTooltipPosition="left"
-          > 
+          >
                 {{ data.resource.computational_name }}
-            </span> will be 
+            </span> will be
       <span *ngIf="data.action === 'terminate'"> decommissioned.</span>
       <span *ngIf="data.action === 'stop'">stopped.</span>
     </div>
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/ami-create-dialog/ami-create-dialog.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/ami-create-dialog/ami-create-dialog.component.html
index b3510c4..1e7c25c 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/ami-create-dialog/ami-create-dialog.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/ami-create-dialog/ami-create-dialog.component.html
@@ -19,7 +19,7 @@
 
 <div class="ami-dialog" id="dialog-box">
   <header class="dialog-header">
-    <h4 class="modal-title">Create {{ DICTIONARY.image }}</h4>
+    <h4 class="modal-title">Create image</h4>
     <button type="button" class="close" (click)="dialogRef.close()">&times;</button>
   </header>
   <div class="dialog-content">
@@ -28,13 +28,13 @@
         <div class="control-group">
           <label class="label">Name</label>
           <div class="control">
-            <input type="text" formControlName="name" placeholder="Enter {{ DICTIONARY.image }} name">
+            <input type="text" formControlName="name" placeholder="Enter image name">
             <span class="error" *ngIf="createAMIForm.controls['name'].hasError('duplication')">This
-              {{ DICTIONARY.image }} name already exists in project.</span>
+              image name already exists in project.</span>
             <span class="error"
               *ngIf="!createAMIForm.valid && createAMIForm.controls['name'].dirty && !createAMIForm.controls['name'].hasError('duplication')">
-              {{ DICTIONARY.image }} name
-              <span *ngIf="DICTIONARY.cloud_provider === 'azure'"> cannot be longer than 10 characters and</span>
+              image name
+              <span *ngIf="provider === 'azure'"> cannot be longer than 10 characters and</span>
               can only contain letters, numbers, hyphens and '_'</span>
           </div>
         </div>
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/ami-create-dialog/ami-create-dialog.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/ami-create-dialog/ami-create-dialog.component.ts
index 430f6cb..ff17382 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/ami-create-dialog/ami-create-dialog.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/ami-create-dialog/ami-create-dialog.component.ts
@@ -35,7 +35,7 @@ export class AmiCreateDialogComponent implements OnInit {
   readonly DICTIONARY = DICTIONARY;
   public notebook: any;
   public createAMIForm: FormGroup;
-
+  public provider: string;
   namePattern = '[-_a-zA-Z0-9]+';
   delimitersRegex = /[-_]?/g;
   imagesList: any;
@@ -50,6 +50,7 @@ export class AmiCreateDialogComponent implements OnInit {
 
   ngOnInit() {
     this.notebook = this.data;
+    this.provider = this.data.cloud_provider;
 
     this.initFormModel();
     this._userResource.getImagesList(this.data.project).subscribe(res => this.imagesList = res);
@@ -58,7 +59,7 @@ export class AmiCreateDialogComponent implements OnInit {
   public assignChanges(data) {
     this._userResource.createAMI(data).subscribe(
       response => response.status === HTTP_STATUS_CODES.ACCEPTED && this.dialogRef.close(),
-      error => this.toastr.error(error.message || `${DICTIONARY.image.toLocaleUpperCase()} creation failed!`, 'Oops!'));
+      error => this.toastr.error(error.message || `Image creation failed!`, 'Oops!'));
   }
 
   private initFormModel(): void {
@@ -70,7 +71,7 @@ export class AmiCreateDialogComponent implements OnInit {
   }
 
   private providerMaxLength(control) {
-    if (DICTIONARY.cloud_provider !== 'aws')
+    if (control && control.value)
       return control.value.length <= 10 ? null : { valid: false };
   }
 
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/cost-details-dialog/cost-details-dialog.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/cost-details-dialog/cost-details-dialog.component.html
index 700cc54..95ae591 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/cost-details-dialog/cost-details-dialog.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/cost-details-dialog/cost-details-dialog.component.html
@@ -34,25 +34,25 @@
       <div class="billing-detail content-box">
         <mat-list>
             <mat-list-item class="list-header">
-              <div class="resource-name ellipsis" [ngClass]="{ 'wide-name-field' : DICTIONARY.cloud_provider === 'azure' }">Name</div>
-              <div class="service">{{ DICTIONARY.service }}</div>
-              <div class="resource-type" *ngIf="DICTIONARY.cloud_provider === 'aws'">{{ DICTIONARY.type }}</div>
+              <div class="resource-name ellipsis" [ngClass]="{ 'wide-name-field' : provider === 'azure' }">Name</div>
+              <div class="service">{{ DICTIONARY[provider].service }}</div>
+              <div class="resource-type" *ngIf="provider === 'aws'">Type</div>
               <div class="cost-currency">Cost</div>
               <div class="usage-date-start">Start</div>
               <div class="usage-date-end">End</div>
             </mat-list-item>
             <div class="scrolling-content" id="scrolling">
               <mat-list-item *ngFor="let item of notebook.billing">
-                <div class="resource-name" [ngClass]="{ 'wide-name-field' : DICTIONARY.cloud_provider === 'azure' }"
-                     matTooltip="{{ item[DICTIONARY.billing.resourceName] }}"
+                <div class="resource-name" [ngClass]="{ 'wide-name-field' : provider === 'azure' }"
+                     matTooltip="{{ item[DICTIONARY[provider].billing.resourceName] }}"
                      matTooltipPosition="above">
-                     {{ item[DICTIONARY.billing.resourceName] }}
+                     {{ item[DICTIONARY[provider].billing.resourceName] }}
                 </div>
-                <div class="service">{{ item[DICTIONARY.billing.service] }}</div>
-                <div class="resource-type" *ngIf="DICTIONARY.cloud_provider === 'aws'">{{ item[DICTIONARY.billing.type] }}</div>
-                <div class="cost-currency">{{ item[DICTIONARY.billing.cost] }} {{ item[DICTIONARY.billing.currencyCode] }}</div>
-                <div class="usage-date-start">{{ item[DICTIONARY.billing.dateFrom] | date }}</div>
-                <div class="usage-date-end">{{ item[DICTIONARY.billing.dateTo] | date }}</div>
+                <div class="service">{{ item[DICTIONARY[provider].billing.service] }}</div>
+                <div class="resource-type" *ngIf="provider === 'aws'">{{ item[DICTIONARY[provider].billing.type] }}</div>
+                <div class="cost-currency">{{ item[DICTIONARY[provider].billing.cost] }} {{ item[DICTIONARY[provider].billing.currencyCode] }}</div>
+                <div class="usage-date-start">{{ item[DICTIONARY[provider].billing.dateFrom] | date }}</div>
+                <div class="usage-date-end">{{ item[DICTIONARY[provider].billing.dateTo] | date }}</div>
               </mat-list-item>
             </div>
         </mat-list>
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/cost-details-dialog/cost-details-dialog.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/cost-details-dialog/cost-details-dialog.component.ts
index 3243b77..e115cad 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/cost-details-dialog/cost-details-dialog.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/cost-details-dialog/cost-details-dialog.component.ts
@@ -29,6 +29,7 @@ import { DICTIONARY } from '../../../../dictionary/global.dictionary';
 export class CostDetailsDialogComponent implements OnInit {
   readonly DICTIONARY = DICTIONARY;
   public notebook: any;
+  public provider: string;
 
   constructor(
     @Inject(MAT_DIALOG_DATA) public data: any,
@@ -37,5 +38,6 @@ export class CostDetailsDialogComponent implements OnInit {
 
   ngOnInit() {
     this.notebook = this.data;
+    this.provider = this.notebook.cloud_provider;
   }
 }
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/create-environment/create-environment.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/create-environment/create-environment.component.html
index 45bc68d..a598cec 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/create-environment/create-environment.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/create-environment/create-environment.component.html
@@ -82,10 +82,11 @@
         </div>
 
         <div class="control-group" *ngIf="images && images.length > 0">
-          <label class="label">Select {{ DICTIONARY.image }}</label>
+          <label class="label">Select image</label>
           <div class="control selector-wrapper">
             <mat-form-field>
-              <mat-select formControlName="notebook_image_name" disableOptionCentering placeholder="Select image">
+              <mat-label>Select image</mat-label>
+              <mat-select formControlName="notebook_image_name" disableOptionCentering>
                 <mat-option [value]="null">None</mat-option>
                 <mat-option *ngFor="let image of images" [value]="image.name">{{ image.name }}</mat-option>
                 <mat-option *ngIf="!images.length" class="multiple-select ml-10" disabled>Images list is empty
@@ -110,16 +111,17 @@
             <span class="error" *ngIf="!createExploratoryForm?.controls.name.valid
                                         && createExploratoryForm?.controls['name'].dirty
                                         && !createExploratoryForm?.controls['name'].hasError('duplication')">Name
-              <span *ngIf="DICTIONARY.cloud_provider !== 'aws'">cannot be longer than 10 characters and</span> can only
+             cannot be longer than 10 characters and can only
               contain letters, numbers, hyphens and '_' but can not end with special characters
             </span>
           </div>
         </div>
 
         <div class="control-group">
-          <label class="label">{{ DICTIONARY.notebook_instance_size }}</label>
+          <label class="label">Instance size</label>
           <div class="control selector-wrapper" [ngClass]="{ 'not-active': !currentTemplate }">
             <mat-form-field>
+              <mat-label>Select instance size</mat-label>
               <mat-select formControlName="shape" disableOptionCentering [disabled]="!currentTemplate"
                 panelClass="create-resources-shapes" placeholder="Instance size">
                 <mat-optgroup *ngFor="let item of (shapes | keys)" [label]="item.key | underscoreless">
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/create-environment/create-environment.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/create-environment/create-environment.component.ts
index 5b907f4..eb32cec 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/create-environment/create-environment.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/create-environment/create-environment.component.ts
@@ -152,7 +152,7 @@ export class ExploratoryEnvironmentCreateComponent implements OnInit {
   }
 
   private providerMaxLength(control) {
-    if (DICTIONARY.cloud_provider !== 'aws')
+    if (control && control.value)
       return control.value.length <= 10 ? null : { valid: false };
   }
 
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/detail-dialog/detail-dialog.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/detail-dialog/detail-dialog.component.html
index 22802ae..4977b22 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/detail-dialog/detail-dialog.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/detail-dialog/detail-dialog.component.html
@@ -59,23 +59,23 @@
             <p class="flex" *ngIf="notebook.password">Password: &nbsp;<span
                 class="strong">{{ notebook.password }}</span></p>
 
-            <p class="m-top-30">{{ DICTIONARY.personal_storage }}: &nbsp;</p>
+            <p class="m-top-30">{{ DICTIONARY[PROVIDER].personal_storage }}: &nbsp;</p>
             <div class="links_block">
-              <p *ngIf="DICTIONARY.cloud_provider === 'azure' && notebook.account_name">{{ DICTIONARY.account }}
+              <p *ngIf="DICTIONARY[PROVIDER].cloud_provider === 'azure' && notebook.account_name">{{ DICTIONARY[PROVIDER].account }}
                 <span class="bucket-info">{{ notebook.account_name}}</span></p>
-              <p *ngIf="notebook.bucket_name">{{ DICTIONARY.container }} <span
+              <p *ngIf="notebook.bucket_name">{{ DICTIONARY[PROVIDER].container }} <span
                   class="bucket-info">{{ notebook.bucket_name }}</span></p>
             </div>
-            <p>{{ DICTIONARY.collaboration_storage }}: &nbsp;</p>
+            <p>Shared endpoint bucket: &nbsp;</p>
             <div class="links_block">
-              <p *ngIf="DICTIONARY.cloud_provider === 'azure' && notebook.shared_account_name">{{ DICTIONARY.account }}
+              <p *ngIf="DICTIONARY[PROVIDER].cloud_provider === 'azure' && notebook.shared_account_name">{{ DICTIONARY[PROVIDER].account }}
                 <span class="bucket-info">{{ notebook.shared_account_name}}</span></p>
-              <p *ngIf="notebook.shared_bucket_name">{{ DICTIONARY.container }}
+              <p *ngIf="notebook.shared_bucket_name">{{ DICTIONARY[PROVIDER].container }}
                 <span class="bucket-info">{{ notebook.shared_bucket_name }}</span></p>
             </div>
             <br />
 
-            <div *ngIf="DICTIONARY.cloud_provider === 'azure' && notebook.datalake_name">
+            <div *ngIf="DICTIONARY[PROVIDER].cloud_provider === 'azure' && notebook.datalake_name">
               <p>Data Lake Store: &nbsp;</p>
               <div class="links_block">
                 <p>Data Lake Store Account: &nbsp;<span class="bucket-info">{{ notebook.datalake_name }}</span></p>
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/detail-dialog/detail-dialog.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/detail-dialog/detail-dialog.component.ts
index fa05b52..1fa43ca 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/detail-dialog/detail-dialog.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/exploratory/detail-dialog/detail-dialog.component.ts
@@ -35,6 +35,7 @@ import { CLUSTER_CONFIGURATION } from '../../computational/computational-resourc
 
 export class DetailDialogComponent implements OnInit {
   readonly DICTIONARY = DICTIONARY;
+  readonly PROVIDER = this.data.cloud_provider;
   notebook: any;
   upTimeInHours: number;
   upTimeSince: string = '';
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.html b/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.html
index eedd10c..6f05128 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.html
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.html
@@ -62,7 +62,7 @@
     </ng-container>
     <ng-container matColumnDef="shapes">
       <th mat-header-cell *matHeaderCellDef class="shape-col">
-        <span class="label"> {{ DICTIONARY.instance_size }} </span>
+        <span class="label"> Size </span>
         <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()">
           <i class="material-icons">
             <span *ngIf="filtering && filterForm.shapes.length > 0 && !collapseFilterRow">filter_list</span>
@@ -78,7 +78,7 @@
     </ng-container>
     <ng-container matColumnDef="resources">
       <th mat-header-cell *matHeaderCellDef class="resources-col">
-        <span class="label"> {{ DICTIONARY.computational_resource }} </span>
+        <span class="label"> Computational resources </span>
         <button mat-icon-button aria-label="More" class="ar" (click)="toggleFilterRow()">
           <i class="material-icons">
             <span *ngIf="filtering && filterForm.resources.length > 0 && !collapseFilterRow">filter_list</span>
@@ -195,9 +195,9 @@
                   </li>
                 </div>
                 <li (click)="exploratoryAction(element, 'ami')"
-                  *ngIf="element.status === 'running' && DICTIONARY.cloud_provider !== 'gcp' && element.image !== 'docker.dlab-superset' && element.image !== 'docker.dlab-jupyterlab'">
+                  *ngIf="element.status === 'running' && element.cloud_provider !== 'gcp' && element.image !== 'docker.dlab-superset' && element.image !== 'docker.dlab-jupyterlab'">
                   <i class="material-icons">view_module</i>
-                  <span>Create {{ DICTIONARY.image }}</span>
+                  <span>Create {{ DICTIONARY[element.cloud_provider].image }}</span>
                 </li>
                 <li (click)="exploratoryAction(element, 'install')"
                   *ngIf="element.image !== 'docker.dlab-superset' && element.image !== 'docker.dlab-jupyterlab'">
@@ -234,7 +234,7 @@
     <ng-container matColumnDef="shape-filter">
       <th mat-header-cell *matHeaderCellDef class="shape-col">
         <multi-select-dropdown (selectionChange)="onUpdate($event)"
-          [type]="DICTIONARY.cloud_provider === 'aws' ? 'shapes': 'sizes'" [items]="filterConfiguration.shapes"
+          [type]="'sizes'" [items]="filterConfiguration.shapes"
           [model]="filterForm.shapes"></multi-select-dropdown>
       </th>
     </ng-container>
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.ts b/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.ts
index 347483b..78bb38a 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.component.ts
@@ -72,9 +72,9 @@ export class ResourcesGridComponent implements OnInit {
   public filteringColumns: Array<any> = [
     { title: 'Environment name', name: 'name', class: 'name-col', filter_class: 'name-filter', filtering: true },
     { title: 'Status', name: 'statuses', class: 'status-col', filter_class: 'status-filter', filtering: true },
-    { title: DICTIONARY.instance_size, name: 'shapes', class: 'shape-col', filter_class: 'shape-filter', filtering: true },
+    { title: 'Instance size', name: 'shapes', class: 'shape-col', filter_class: 'shape-filter', filtering: true },
     { title: 'Tags', name: 'tag', class: 'tag-col', filter_class: 'tag-filter', filtering: false },
-    { title: DICTIONARY.computational_resource, name: 'resources', class: 'resources-col', filter_class: 'resource-filter', filtering: true },
+    { title: 'Computational resource', name: 'resources', class: 'resources-col', filter_class: 'resource-filter', filtering: true },
     { title: 'Cost', name: 'cost', class: 'cost-col', filter_class: 'cost-filter', filtering: false },
     { title: '', name: 'actions', class: 'actions-col', filter_class: 'action-filter', filtering: false }
   ];
@@ -91,7 +91,6 @@ export class ResourcesGridComponent implements OnInit {
   ) { }
 
   ngOnInit(): void {
-
     this.buildGrid();
   }
 
@@ -127,10 +126,11 @@ export class ResourcesGridComponent implements OnInit {
   }
 
   public containsNotebook(notebook_name: string): boolean {
-    if (notebook_name && this.environments.length)
+    if (notebook_name && this.environments && this.environments.length ) {
       return this.environments
         .filter(project => project.exploratory
           .some(item => CheckUtils.delimitersFiltering(notebook_name) === CheckUtils.delimitersFiltering(item.name))).length > 0;
+    }
   }
 
   public isResourcesInProgress(notebook) {
@@ -194,6 +194,7 @@ export class ResourcesGridComponent implements OnInit {
         .afterClosed().subscribe(() => this.buildGrid());
     } else if (action === 'ami') {
       this.dialog.open(AmiCreateDialogComponent, { data: data, panelClass: 'modal-sm' })
+
         .afterClosed().subscribe(() => this.buildGrid());
     }
   }
diff --git a/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.model.ts b/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.model.ts
index d9e4089..063c7fc 100644
--- a/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.model.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/resources/resources-grid/resources-grid.model.ts
@@ -49,11 +49,13 @@ export class ExploratoryModel {
     public project: string,
     public endpoint: string,
     public tags: any,
+    public cloud_provider: string
   ) { }
 
   public static loadEnvironments(data: Array<any>) {
     if (data) {
       return data.map((value) => {
+        const provider = value.endpoints[0].cloudProvider.toLowerCase();
         return {
           project: value.project,
           exploratory: value.exploratory.map(el => new ExploratoryModel(el.exploratory_name,
@@ -68,23 +70,24 @@ export class ExploratoryModel {
             el.private_ip,
             el.exploratory_user,
             el.exploratory_pass,
-            value.shared[el.endpoint][DICTIONARY.bucket_name],
-            value.shared[el.endpoint][DICTIONARY.shared_bucket_name],
+            value.shared[el.endpoint][DICTIONARY[provider].bucket_name],
+            value.shared[el.endpoint][DICTIONARY[provider].shared_bucket_name],
             el.error_message,
-            el[DICTIONARY.billing.cost],
-            el[DICTIONARY.billing.currencyCode],
+            el[DICTIONARY[provider].billing.cost],
+            el[DICTIONARY[provider].billing.currencyCode],
             el.billing,
             el.libs,
-            value.shared[el.endpoint][DICTIONARY.user_storage_account_name],
-            value.shared[el.endpoint][DICTIONARY.shared_storage_account_name],
-            value.shared[el.endpoint][DICTIONARY.datalake_name],
-            value.shared[el.endpoint][DICTIONARY.datalake_user_directory_name],
-            value.shared[el.endpoint][DICTIONARY.datalake_shared_directory_name],
+            value.shared[el.endpoint][DICTIONARY[provider].user_storage_account_name],
+            value.shared[el.endpoint][DICTIONARY[provider].shared_storage_account_name],
+            value.shared[el.endpoint][DICTIONARY[provider].datalake_name],
+            value.shared[el.endpoint][DICTIONARY[provider].datalake_user_directory_name],
+            value.shared[el.endpoint][DICTIONARY[provider].datalake_shared_directory_name],
             el.project,
             el.endpoint,
-            el.tags
+            el.tags,
+            provider,
           ))
-        }
+        };
       });
     }
   }
@@ -92,5 +95,5 @@ export class ExploratoryModel {
 
 export interface Exploratory {
   project: string;
-  exploratory: ExploratoryModel[]
+  exploratory: ExploratoryModel[];
 }
diff --git a/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.ts b/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.ts
index 37ae148..78ddd3c 100644
--- a/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.ts
+++ b/services/self-service/src/main/resources/webapp/src/app/shared/navbar/navbar.component.ts
@@ -75,7 +75,6 @@ import {ProgressBarService} from "../../core/services/progress-bar.service";
   encapsulation: ViewEncapsulation.None
 })
 export class NavbarComponent implements OnInit, OnDestroy {
-  readonly PROVIDER = DICTIONARY.cloud_provider;
 
   private readonly CHECK_ACTIVE_SCHEDULE_TIMEOUT: number = 55000;
   private readonly CHECK_ACTIVE_SCHEDULE_PERIOD: number = 15;
diff --git a/services/self-service/src/main/resources/webapp/src/dictionary/aws.dictionary.ts b/services/self-service/src/main/resources/webapp/src/dictionary/aws.dictionary.ts
index a37445f..f989415 100644
--- a/services/self-service/src/main/resources/webapp/src/dictionary/aws.dictionary.ts
+++ b/services/self-service/src/main/resources/webapp/src/dictionary/aws.dictionary.ts
@@ -17,15 +17,11 @@
  * under the License.
  */
 
-export const NAMING_CONVENTION = {
+export const NAMING_CONVENTION_AWS = {
     'cloud_provider': 'aws',
-    'use_ldap': true,
-    'notebook_instance_size': 'Instance shape',
     'personal_storage': 'Project bucket',
-    'collaboration_storage': 'Shared endpoint bucket',
     'account': '',
     'container': '',
-    'data_engine': 'Deploy Spark Server / Deploy EMR',
     'image': 'AMI',
     'data_engine_master_instance_size': 'Master instance shape',
     'data_engine_slave_instance_size': 'Slave instance shape',
@@ -52,7 +48,6 @@ export const NAMING_CONVENTION = {
     'service': 'Service',
     'type': 'Type',
     'instance_size': 'Shape',
-    'computational_resource': 'Computational resources',
     'user_storage_account_name': '',
     'shared_storage_account_name': '',
     'bucket_name': 'user_own_bicket_name',
@@ -65,9 +60,6 @@ export const NAMING_CONVENTION = {
         'total_instance_number_max': 'max_emr_instance_count',
         'min_emr_spot_instance_bid_pct': 'min_emr_spot_instance_bid_pct',
         'max_emr_spot_instance_bid_pct': 'max_emr_spot_instance_bid_pct',
-        'data_engine_master_instance_size': 'Master instance shape',
-        'data_engine_slave_instance_size': 'Slave instance shape',
-        'instance_number': 'Total instance number',
         'master_node_shape': 'master_node_shape',
         'slave_node_shape': 'slave_node_shape',
         'total_instance_number': 'total_instance_number',
@@ -76,40 +68,9 @@ export const NAMING_CONVENTION = {
         'total_instance_number_min': 'min_spark_instance_count',
         'total_instance_number_max': 'max_spark_instance_count',
         'data_engine_master_instance_size': 'Node shape',
-        'instance_number': 'Total node number',
         'master_node_shape': 'dataengine_instance_shape',
         'total_instance_number': 'dataengine_instance_count',
     },
-    'max_project_name_length': 40
 };
 
-export class ReportingConfigModel {
 
-    static getDefault(): ReportingConfigModel {
-        return new ReportingConfigModel([], [], [], [], [], '', '', '', []);
-    }
-
-    constructor(
-        public user: Array<string>,
-        public product: Array<string>,
-        public resource_type: Array<string>,
-        public status: Array<string>,
-        public shape: Array<string>,
-        public date_start: string,
-        public date_end: string,
-        public dlab_id: string,
-        public project?: Array<string>
-    ) { }
-
-    defaultConfigurations(): void {
-        this.user = [];
-        this.product = [];
-        this.resource_type = [];
-        this.status = [];
-        this.shape = [];
-        this.date_start = '';
-        this.date_end = '';
-        this.dlab_id = '';
-        this.project = [];
-    }
-}
diff --git a/services/self-service/src/main/resources/webapp/src/dictionary/azure.dictionary.ts b/services/self-service/src/main/resources/webapp/src/dictionary/azure.dictionary.ts
index 819c181..67ac627 100644
--- a/services/self-service/src/main/resources/webapp/src/dictionary/azure.dictionary.ts
+++ b/services/self-service/src/main/resources/webapp/src/dictionary/azure.dictionary.ts
@@ -17,22 +17,18 @@
  * under the License.
  */
 
-export const NAMING_CONVENTION = {
+export const NAMING_CONVENTION_AZURE = {
     'cloud_provider': 'azure',
-    'use_ldap': true,
-    'notebook_instance_size': 'Virtual machine size',
     'personal_storage': 'Project bucket',
     'collaboration_storage': 'Shared endpoint bucket',
     'account': 'Account:',
     'container': 'Container:',
-    'data_engine': 'Deploy Spark Server / Deploy HDInsight',
     'image': 'image',
     'data_engine_master_instance_size': 'Head node size',
     'data_engine_slave_instance_size': 'Worker node size',
     'master_node_shape': 'azure_dataengine_master_size',
     'slave_node_shape': 'azure_dataengine_slave_size',
     'total_instance_number': 'dataengine_instance_count',
-
     'spot_instance': 'Low-priority virtual machines',
     'cluster_version': '',
     'max_cluster_name_length': 10,
@@ -53,7 +49,6 @@ export const NAMING_CONVENTION = {
     'service': 'Category',
     'type': '',
     'instance_size': 'Size',
-    'computational_resource': 'Computational resources',
     'user_storage_account_name': 'user_storage_account_name',
     'shared_storage_account_name': 'shared_storage_account_name',
     'bucket_name': 'user_container_name',
@@ -66,9 +61,6 @@ export const NAMING_CONVENTION = {
         'total_instance_number_max': 'max_emr_instance_count',
         'min_emr_spot_instance_bid_pct': 'min_emr_spot_instance_bid_pct',
         'max_emr_spot_instance_bid_pct': 'max_emr_spot_instance_bid_pct',
-        'data_engine_master_instance_size': 'Master instance shape',
-        'data_engine_slave_instance_size': 'Slave instance shape',
-        'instance_number': 'Total instance number',
         'master_node_shape': 'master_node_shape',
         'slave_node_shape': 'slave_node_shape',
         'total_instance_number': 'total_instance_number',
@@ -77,40 +69,8 @@ export const NAMING_CONVENTION = {
         'total_instance_number_min': 'min_spark_instance_count',
         'total_instance_number_max': 'max_spark_instance_count',
         'data_engine_master_instance_size': 'Node size',
-        'instance_number': 'Total node number',
         'master_node_shape': 'dataengine_instance_shape',
         'total_instance_number': 'dataengine_instance_count'
     },
-    'max_project_name_length': 30
 };
 
-export class ReportingConfigModel {
-
-    static getDefault(): ReportingConfigModel {
-        return new ReportingConfigModel([], [], [], [], [], '', '', '', []);
-    }
-
-    constructor(
-        public user: Array<string>,
-        public category: Array<string>,
-        public resource_type: Array<string>,
-        public status: Array<string>,
-        public size: Array<string>,
-        public date_start: string,
-        public date_end: string,
-        public dlab_id: string,
-        public project?: Array<string>
-    ) { }
-
-    defaultConfigurations(): void {
-        this.user = [];
-        this.category = [];
-        this.resource_type = [];
-        this.status = [];
-        this.size = [];
-        this.date_start = '';
-        this.date_end = '';
-        this.dlab_id = '';
-        this.project = [];
-    }
-}
diff --git a/services/self-service/src/main/resources/webapp/src/dictionary/gcp.dictionary.ts b/services/self-service/src/main/resources/webapp/src/dictionary/gcp.dictionary.ts
index 10d7cf2..0d02f63 100644
--- a/services/self-service/src/main/resources/webapp/src/dictionary/gcp.dictionary.ts
+++ b/services/self-service/src/main/resources/webapp/src/dictionary/gcp.dictionary.ts
@@ -17,23 +17,17 @@
  * under the License.
  */
 
-export const NAMING_CONVENTION = {
+export const NAMING_CONVENTION_GCP = {
     'cloud_provider': 'gcp',
-    'use_ldap': true,
-    'notebook_instance_size': 'Instance type',
     'personal_storage': 'Project bucket',
-    'collaboration_storage': 'Shared endpoint bucket',
     'account': '',
     'container': '',
-    'data_engine': 'Deploy Spark Server / Deploy Dataproc',
     'image': 'Not available',
     'data_engine_master_instance_size': 'Master machine type',
     'data_engine_slave_instance_size': 'Slave machine type',
-
     'master_node_shape': 'master_node_shape',
     'slave_node_shape': 'slave_node_shape',
     'total_instance_number': 'total_instance_number',
-
     'spot_instance': 'Preemptible worker nodes',
     'cluster_version': 'dataproc_version',
     'max_cluster_name_length': 7,
@@ -54,7 +48,6 @@ export const NAMING_CONVENTION = {
     'service': 'Product',
     'type': 'Resource',
     'instance_size': 'Type',
-    'computational_resource': 'Computational resources',
     'user_storage_account_name': '',
     'shared_storage_account_name': '',
     'bucket_name': 'user_own_bucket_name',
@@ -67,9 +60,6 @@ export const NAMING_CONVENTION = {
         'total_instance_number_max': 'max_instance_count',
         'min_emr_spot_instance_bid_pct': 'min_emr_spot_instance_bid_pct',
         'max_emr_spot_instance_bid_pct': 'max_emr_spot_instance_bid_pct',
-        'data_engine_master_instance_size': 'Master machine type',
-        'data_engine_slave_instance_size': 'Slave machine type',
-        'instance_number': 'Total machine count',
         'master_instance_number': 'Master node count',
         'slave_instance_number': 'Worker node count',
         'master_node_shape': 'master_node_shape',
@@ -81,41 +71,10 @@ export const NAMING_CONVENTION = {
         'total_instance_number_min': 'min_spark_instance_count',
         'total_instance_number_max': 'max_spark_instance_count',
         'data_engine_master_instance_size': 'Machine type',
-        'instance_number': 'Total machine number',
         'master_instance_number': 'Master machine number',
         'master_node_shape': 'dataengine_instance_shape',
         'total_instance_number': 'dataengine_instance_count',
     },
-    'max_project_name_length': 10
 };
 
-export class ReportingConfigModel {
-
-    static getDefault(): ReportingConfigModel {
-        return new ReportingConfigModel([], [], [], [], [], '', '', '', []);
-    }
-
-    constructor(
-        public user: Array<string>,
-        public product: Array<string>,
-        public resource_type: Array<string>,
-        public status: Array<string>,
-        public shape: Array<string>,
-        public date_start: string,
-        public date_end: string,
-        public dlab_id: string,
-        public project?: Array<string>
-    ) { }
 
-    defaultConfigurations(): void {
-        this.user = [];
-        this.product = [];
-        this.resource_type = [];
-        this.status = [];
-        this.shape = [];
-        this.date_start = '';
-        this.date_end = '';
-        this.dlab_id = '';
-        this.project = [];
-    }
-}
diff --git a/services/self-service/src/main/resources/webapp/src/dictionary/global.dictionary.ts b/services/self-service/src/main/resources/webapp/src/dictionary/global.dictionary.ts
index 6d0d8ea..dfb97b0 100644
--- a/services/self-service/src/main/resources/webapp/src/dictionary/global.dictionary.ts
+++ b/services/self-service/src/main/resources/webapp/src/dictionary/global.dictionary.ts
@@ -19,8 +19,45 @@
 
 // from './{{ aws | gcp | azure }}.dictionary';
 
-import { NAMING_CONVENTION } from './CLOUD_PROVIDER.dictionary';
+import { NAMING_CONVENTION_AWS } from './aws.dictionary';
+import { NAMING_CONVENTION_GCP } from './gcp.dictionary';
+import { NAMING_CONVENTION_AZURE } from './azure.dictionary';
+
+export const DICTIONARY = Object.freeze({
+  aws: NAMING_CONVENTION_AWS,
+  gcp: NAMING_CONVENTION_GCP,
+  azure: NAMING_CONVENTION_AZURE
+});
+
+export class ReportingConfigModel {
+
+  static getDefault(): ReportingConfigModel {
+    return new ReportingConfigModel([], [], [], [], [], '', '', '', []);
+  }
+
+  constructor(
+    public user: Array<string>,
+    public service: Array<string>,
+    public resource_type: Array<string>,
+    public status: Array<string>,
+    public shape: Array<string>,
+    public date_start: string,
+    public date_end: string,
+    public dlab_id: string,
+    public project?: Array<string>
+  ) { }
+
+  defaultConfigurations(): void {
+    this.user = [];
+    this.service = [];
+    this.resource_type = [];
+    this.status = [];
+    this.shape = [];
+    this.date_start = '';
+    this.date_end = '';
+    this.dlab_id = '';
+    this.project = [];
+  }
+}
 
-export * from './CLOUD_PROVIDER.dictionary';
 
-export const DICTIONARY = Object.freeze(NAMING_CONVENTION);
diff --git a/services/self-service/src/test/java/com/epam/dlab/backendapi/resources/EdgeResourceTest.java b/services/self-service/src/test/java/com/epam/dlab/backendapi/resources/EdgeResourceTest.java
deleted file mode 100644
index 075502e..0000000
--- a/services/self-service/src/test/java/com/epam/dlab/backendapi/resources/EdgeResourceTest.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.resources;
-
-import com.epam.dlab.auth.UserInfo;
-import com.epam.dlab.backendapi.service.EdgeService;
-import com.epam.dlab.exceptions.DlabException;
-import io.dropwizard.auth.AuthenticationException;
-import io.dropwizard.testing.junit.ResourceTestRule;
-import org.apache.http.HttpStatus;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.*;
-
-public class EdgeResourceTest extends TestBase {
-
-	private EdgeService edgeService = mock(EdgeService.class);
-
-	@Rule
-	public final ResourceTestRule resources = getResourceTestRuleInstance(new EdgeResource(edgeService));
-
-	@Before
-	public void setup() throws AuthenticationException {
-		authSetup();
-	}
-
-	@Test
-	public void start() {
-		when(edgeService.start(any(UserInfo.class))).thenReturn("someUuid");
-		final Response response = resources.getJerseyTest()
-				.target("/infrastructure/edge/start")
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.json(getUserInfo()));
-
-		assertEquals(HttpStatus.SC_OK, response.getStatus());
-		assertEquals("someUuid", response.readEntity(String.class));
-		assertEquals(MediaType.APPLICATION_JSON, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(edgeService).start(getUserInfo());
-		verifyNoMoreInteractions(edgeService);
-	}
-
-	@Test
-	public void startWithFailedAuth() throws AuthenticationException {
-		authFailSetup();
-		when(edgeService.start(any(UserInfo.class))).thenReturn("someUuid");
-		final Response response = resources.getJerseyTest()
-				.target("/infrastructure/edge/start")
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.json(getUserInfo()));
-
-		assertEquals(HttpStatus.SC_OK, response.getStatus());
-		assertEquals("someUuid", response.readEntity(String.class));
-		assertEquals(MediaType.APPLICATION_JSON, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(edgeService).start(getUserInfo());
-		verifyNoMoreInteractions(edgeService);
-	}
-
-	@Test
-	public void startWithException() {
-		when(edgeService.start(any(UserInfo.class))).thenThrow(new DlabException("Could not start edge node"));
-		final Response response = resources.getJerseyTest()
-				.target("/infrastructure/edge/start")
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.json(getUserInfo()));
-
-		assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, response.getStatus());
-		String expectedJson = "\"code\":500,\"message\":\"There was an error processing your request. " +
-				"It has been logged";
-		String actualJson = response.readEntity(String.class);
-		assertTrue(actualJson.contains(expectedJson));
-		assertEquals(MediaType.APPLICATION_JSON, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(edgeService).start(getUserInfo());
-		verifyNoMoreInteractions(edgeService);
-	}
-
-	@Test
-	public void stop() {
-		when(edgeService.stop(any(UserInfo.class))).thenReturn("someUuid");
-		final Response response = resources.getJerseyTest()
-				.target("/infrastructure/edge/stop")
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.json(getUserInfo()));
-
-		assertEquals(HttpStatus.SC_OK, response.getStatus());
-		assertEquals("someUuid", response.readEntity(String.class));
-		assertEquals(MediaType.APPLICATION_JSON, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(edgeService).stop(getUserInfo());
-		verifyNoMoreInteractions(edgeService);
-	}
-
-	@Test
-	public void stopWithFailedAuth() throws AuthenticationException {
-		authFailSetup();
-		when(edgeService.stop(any(UserInfo.class))).thenReturn("someUuid");
-		final Response response = resources.getJerseyTest()
-				.target("/infrastructure/edge/stop")
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.json(getUserInfo()));
-
-		assertEquals(HttpStatus.SC_OK, response.getStatus());
-		assertEquals("someUuid", response.readEntity(String.class));
-		assertEquals(MediaType.APPLICATION_JSON, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(edgeService).stop(getUserInfo());
-		verifyNoMoreInteractions(edgeService);
-	}
-
-	@Test
-	public void stopWithException() {
-		when(edgeService.stop(any(UserInfo.class))).thenThrow(new DlabException("Could not stop edge node"));
-		final Response response = resources.getJerseyTest()
-				.target("/infrastructure/edge/stop")
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.json(getUserInfo()));
-
-		assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, response.getStatus());
-		String expectedJson = "\"code\":500,\"message\":\"There was an error processing your request. " +
-				"It has been logged";
-		String actualJson = response.readEntity(String.class);
-		assertTrue(actualJson.contains(expectedJson));
-		assertEquals(MediaType.APPLICATION_JSON, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(edgeService).stop(getUserInfo());
-		verifyNoMoreInteractions(edgeService);
-	}
-
-}
diff --git a/services/self-service/src/test/java/com/epam/dlab/backendapi/resources/EnvironmentResourceTest.java b/services/self-service/src/test/java/com/epam/dlab/backendapi/resources/EnvironmentResourceTest.java
index 2cc49a2..a8b01fa 100644
--- a/services/self-service/src/test/java/com/epam/dlab/backendapi/resources/EnvironmentResourceTest.java
+++ b/services/self-service/src/test/java/com/epam/dlab/backendapi/resources/EnvironmentResourceTest.java
@@ -125,55 +125,6 @@ public class EnvironmentResourceTest extends TestBase {
 	}
 
 	@Test
-	public void terminateEnv() {
-		doNothing().when(environmentService).terminateEnvironment(any(UserInfo.class), anyString());
-		final Response response = resources.getJerseyTest()
-				.target("/environment/terminate")
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.text(USER));
-
-		assertEquals(HttpStatus.SC_OK, response.getStatus());
-		assertNull(response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(environmentService).terminateEnvironment(new UserInfo(USER, TOKEN), USER);
-		verifyNoMoreInteractions(environmentService);
-	}
-
-	@Test
-	public void terminateEnvWithFailedAuth() throws AuthenticationException {
-		authFailSetup();
-		doNothing().when(environmentService).terminateEnvironment(any(UserInfo.class), anyString());
-		final Response response = resources.getJerseyTest()
-				.target("/environment/terminate")
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.text(USER));
-
-		assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatus());
-		assertEquals(MediaType.APPLICATION_JSON, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verifyZeroInteractions(environmentService);
-	}
-
-	@Test
-	public void terminateEnvWithResourceConflictException() {
-		doThrow(new ResourceConflictException("Can not terminate environment because one of the user resources is in" +
-				"status CREATING or STARTING")).when(environmentService).terminateEnvironment(any(UserInfo.class), anyString());
-		final Response response = resources.getJerseyTest()
-				.target("/environment/terminate")
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.text(USER));
-
-		assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, response.getStatus());
-		assertEquals(MediaType.APPLICATION_JSON, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(environmentService).terminateEnvironment(new UserInfo(USER, TOKEN), USER);
-		verifyNoMoreInteractions(environmentService);
-	}
-
-	@Test
 	public void stopEnv() {
 		doNothing().when(environmentService).stopEnvironment(any(UserInfo.class), anyString());
 		final Response response = resources.getJerseyTest()
@@ -223,55 +174,6 @@ public class EnvironmentResourceTest extends TestBase {
 	}
 
 	@Test
-	public void stopEdge() {
-		doNothing().when(environmentService).stopEdge(anyString());
-		final Response response = resources.getJerseyTest()
-				.target("/environment/stop/edge")
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.text(USER));
-
-		assertEquals(HttpStatus.SC_OK, response.getStatus());
-		assertNull(response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(environmentService).stopEdge(USER);
-		verifyNoMoreInteractions(environmentService);
-	}
-
-	@Test
-	public void stopEdgeWithFailedAuth() throws AuthenticationException {
-		authFailSetup();
-		doNothing().when(environmentService).stopEdge(anyString());
-		final Response response = resources.getJerseyTest()
-				.target("/environment/stop/edge")
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.text(USER));
-
-		assertEquals(HttpStatus.SC_FORBIDDEN, response.getStatus());
-		assertEquals(MediaType.APPLICATION_JSON, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verifyZeroInteractions(environmentService);
-	}
-
-	@Test
-	public void stopEdgeWithResourceConflictException() {
-		doThrow(new ResourceConflictException("Can not stop edge because its status is CREATING or STARTING"))
-				.when(environmentService).stopEdge(anyString());
-		final Response response = resources.getJerseyTest()
-				.target("/environment/stop/edge")
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.text(USER));
-
-		assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, response.getStatus());
-		assertEquals(MediaType.APPLICATION_JSON, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(environmentService).stopEdge(USER);
-		verifyNoMoreInteractions(environmentService);
-	}
-
-	@Test
 	public void stopNotebook() {
 		doNothing().when(environmentService).stopExploratory(any(UserInfo.class), anyString(), anyString());
 		final Response response = resources.getJerseyTest()
diff --git a/services/self-service/src/test/java/com/epam/dlab/backendapi/resources/KeyUploaderResourceTest.java b/services/self-service/src/test/java/com/epam/dlab/backendapi/resources/KeyUploaderResourceTest.java
deleted file mode 100644
index 1628cba..0000000
--- a/services/self-service/src/test/java/com/epam/dlab/backendapi/resources/KeyUploaderResourceTest.java
+++ /dev/null
@@ -1,405 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.resources;
-
-import com.epam.dlab.auth.UserInfo;
-import com.epam.dlab.backendapi.service.AccessKeyService;
-import com.epam.dlab.dto.keyload.KeyLoadStatus;
-import com.epam.dlab.exceptions.DlabException;
-import io.dropwizard.auth.AuthenticationException;
-import io.dropwizard.testing.junit.ResourceTestRule;
-import org.apache.http.HttpStatus;
-import org.glassfish.jersey.media.multipart.FormDataMultiPart;
-import org.glassfish.jersey.media.multipart.MultiPartFeature;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.core.HttpHeaders;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.*;
-
-public class KeyUploaderResourceTest extends TestBase {
-
-	private AccessKeyService keyService = mock(AccessKeyService.class);
-
-	@Rule
-	public final ResourceTestRule resources = getResourceTestRuleInstance(new KeyUploaderResource(keyService));
-
-	@Before
-	public void setup() throws AuthenticationException {
-		authSetup();
-	}
-
-	@Test
-	public void checkKey() {
-		when(keyService.getUserKeyStatus(anyString())).thenReturn(KeyLoadStatus.SUCCESS);
-		final Response response = resources.getJerseyTest()
-				.target("/user/access_key")
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.get();
-
-		assertEquals(HttpStatus.SC_OK, response.getStatus());
-		assertNull(response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(keyService).getUserKeyStatus(USER.toLowerCase());
-		verifyNoMoreInteractions(keyService);
-	}
-
-	@Test
-	public void checkKeyWithFailedAuth() throws AuthenticationException {
-		authFailSetup();
-		when(keyService.getUserKeyStatus(anyString())).thenReturn(KeyLoadStatus.SUCCESS);
-		final Response response = resources.getJerseyTest()
-				.target("/user/access_key")
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.get();
-
-		assertEquals(HttpStatus.SC_OK, response.getStatus());
-		assertNull(response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(keyService).getUserKeyStatus(USER.toLowerCase());
-		verifyNoMoreInteractions(keyService);
-	}
-
-	@Test
-	public void checkKeyWithErrorStatus() {
-		when(keyService.getUserKeyStatus(anyString())).thenReturn(KeyLoadStatus.ERROR);
-		final Response response = resources.getJerseyTest()
-				.target("/user/access_key")
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.get();
-
-		assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, response.getStatus());
-		assertEquals(MediaType.APPLICATION_JSON, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(keyService).getUserKeyStatus(USER.toLowerCase());
-		verifyNoMoreInteractions(keyService);
-	}
-
-	@Test
-	public void loadKey() {
-		when(keyService.uploadKey(any(UserInfo.class), anyString(), anyBoolean())).thenReturn("someUuid");
-
-		FormDataMultiPart multiPart = new FormDataMultiPart()
-				.field("file", "ssh-h;glfh;lgfmhgfmmgfkl");
-
-		final Response response = resources.getJerseyTest()
-				.target("/user/access_key")
-				.register(MultiPartFeature.class)
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.entity(multiPart, multiPart.getMediaType()));
-
-		assertEquals(HttpStatus.SC_OK, response.getStatus());
-		assertNull(response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(keyService).uploadKey(getUserInfo(), "ssh-h;glfh;lgfmhgfmmgfkl", true);
-		verifyNoMoreInteractions(keyService);
-	}
-
-	@Test
-	public void loadKeyWithFailedAuth() throws AuthenticationException {
-		authFailSetup();
-		when(keyService.uploadKey(any(UserInfo.class), anyString(), anyBoolean())).thenReturn("someUuid");
-
-		FormDataMultiPart multiPart = new FormDataMultiPart()
-				.field("file", "ssh-h;glfh;lgfmhgfmmgfkl");
-
-		final Response response = resources.getJerseyTest()
-				.target("/user/access_key")
-				.register(MultiPartFeature.class)
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.entity(multiPart, multiPart.getMediaType()));
-
-		assertEquals(HttpStatus.SC_OK, response.getStatus());
-		assertNull(response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(keyService).uploadKey(getUserInfo(), "ssh-h;glfh;lgfmhgfmmgfkl", true);
-		verifyNoMoreInteractions(keyService);
-	}
-
-	@Test
-	public void loadKeyWithWrongKeyFormat() {
-		when(keyService.uploadKey(any(UserInfo.class), anyString(), anyBoolean())).thenReturn("someUuid");
-
-		FormDataMultiPart multiPart = new FormDataMultiPart()
-				.field("file", "glfh;lgfmhgfmmgfkl");
-
-		final Response response = resources.getJerseyTest()
-				.target("/user/access_key")
-				.register(MultiPartFeature.class)
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.entity(multiPart, multiPart.getMediaType()));
-
-		assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, response.getStatus());
-		assertEquals(MediaType.APPLICATION_JSON, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verifyZeroInteractions(keyService);
-	}
-
-	@Test
-	public void loadKeyWithException() {
-		doThrow(new DlabException("Could not upload the key and create EDGE node"))
-				.when(keyService).uploadKey(any(UserInfo.class), anyString(), anyBoolean());
-
-		FormDataMultiPart multiPart = new FormDataMultiPart()
-				.field("file", "ssh-h;glfh;lgfmhgfmmgfkl");
-
-		final Response response = resources.getJerseyTest()
-				.target("/user/access_key")
-				.register(MultiPartFeature.class)
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.entity(multiPart, multiPart.getMediaType()));
-
-		assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, response.getStatus());
-		assertEquals(MediaType.APPLICATION_JSON, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(keyService).uploadKey(getUserInfo(), "ssh-h;glfh;lgfmhgfmmgfkl", true);
-		verifyNoMoreInteractions(keyService);
-	}
-
-	@Test
-	public void reuploadKey() {
-		when(keyService.uploadKey(any(UserInfo.class), anyString(), anyBoolean())).thenReturn("someUuid");
-
-		FormDataMultiPart multiPart = new FormDataMultiPart()
-				.field("file", "ssh-h;glfh;lgfmhgfmmgfkl");
-
-		final Response response = resources.getJerseyTest()
-				.target("/user/access_key")
-				.queryParam("is_primary_uploading", "false")
-				.register(MultiPartFeature.class)
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.entity(multiPart, multiPart.getMediaType()));
-
-		assertEquals(HttpStatus.SC_OK, response.getStatus());
-		assertNull(response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(keyService).uploadKey(getUserInfo(), "ssh-h;glfh;lgfmhgfmmgfkl", false);
-		verifyNoMoreInteractions(keyService);
-	}
-
-	@Test
-	public void reuploadKeyWithFailedAuth() throws AuthenticationException {
-		authFailSetup();
-		when(keyService.uploadKey(any(UserInfo.class), anyString(), anyBoolean())).thenReturn("someUuid");
-
-		FormDataMultiPart multiPart = new FormDataMultiPart()
-				.field("file", "ssh-h;glfh;lgfmhgfmmgfkl");
-
-		final Response response = resources.getJerseyTest()
-				.target("/user/access_key")
-				.queryParam("is_primary_uploading", "false")
-				.register(MultiPartFeature.class)
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.entity(multiPart, multiPart.getMediaType()));
-
-		assertEquals(HttpStatus.SC_OK, response.getStatus());
-		assertNull(response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(keyService).uploadKey(getUserInfo(), "ssh-h;glfh;lgfmhgfmmgfkl", false);
-		verifyNoMoreInteractions(keyService);
-	}
-
-	@Test
-	public void reuploadKeyWithWrongKeyFormat() {
-		when(keyService.uploadKey(any(UserInfo.class), anyString(), anyBoolean())).thenReturn("someUuid");
-
-		FormDataMultiPart multiPart = new FormDataMultiPart()
-				.field("file", "glfh;lgfmhgfmmgfkl");
-
-		final Response response = resources.getJerseyTest()
-				.target("/user/access_key")
-				.queryParam("is_primary_uploading", "false")
-				.register(MultiPartFeature.class)
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.entity(multiPart, multiPart.getMediaType()));
-
-		assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, response.getStatus());
-		assertEquals(MediaType.APPLICATION_JSON, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verifyZeroInteractions(keyService);
-	}
-
-	@Test
-	public void reuploadKeyWithException() {
-		doThrow(new DlabException("Could not reupload the key. Previous key has been deleted"))
-				.when(keyService).uploadKey(any(UserInfo.class), anyString(), anyBoolean());
-
-		FormDataMultiPart multiPart = new FormDataMultiPart()
-				.field("file", "ssh-h;glfh;lgfmhgfmmgfkl");
-
-		final Response response = resources.getJerseyTest()
-				.target("/user/access_key")
-				.queryParam("is_primary_uploading", "false")
-				.register(MultiPartFeature.class)
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.entity(multiPart, multiPart.getMediaType()));
-
-		assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, response.getStatus());
-		assertEquals(MediaType.APPLICATION_JSON, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(keyService).uploadKey(getUserInfo(), "ssh-h;glfh;lgfmhgfmmgfkl", false);
-		verifyNoMoreInteractions(keyService);
-	}
-
-	@Test
-	public void recoverEdge() {
-		when(keyService.recoverEdge(any(UserInfo.class))).thenReturn("someUuid");
-
-		final Response response = resources.getJerseyTest()
-				.target("/user/access_key/recover")
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.json(""));
-
-		assertEquals(HttpStatus.SC_OK, response.getStatus());
-		assertEquals(MediaType.APPLICATION_JSON, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(keyService).recoverEdge(getUserInfo());
-		verifyNoMoreInteractions(keyService);
-	}
-
-	@Test
-	public void recoverEdgeWithFailedAuth() throws AuthenticationException {
-		authFailSetup();
-		when(keyService.recoverEdge(any(UserInfo.class))).thenReturn("someUuid");
-
-		final Response response = resources.getJerseyTest()
-				.target("/user/access_key/recover")
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.json(""));
-
-		assertEquals(HttpStatus.SC_OK, response.getStatus());
-		assertEquals(MediaType.APPLICATION_JSON, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(keyService).recoverEdge(getUserInfo());
-		verifyNoMoreInteractions(keyService);
-	}
-
-	@Test
-	public void recoverEdgeWithException() {
-		doThrow(new DlabException("Could not upload the key and create EDGE node"))
-				.when(keyService).recoverEdge(any(UserInfo.class));
-
-		final Response response = resources.getJerseyTest()
-				.target("/user/access_key/recover")
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.json(""));
-
-		assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, response.getStatus());
-		assertEquals(MediaType.APPLICATION_JSON, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(keyService).recoverEdge(getUserInfo());
-		verifyNoMoreInteractions(keyService);
-	}
-
-	@Test
-	public void generateKey() {
-		when(keyService.generateKey(any(UserInfo.class), anyBoolean())).thenReturn("someUuid");
-
-		final Response response = resources.getJerseyTest()
-				.target("/user/access_key/generate")
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.json(""));
-
-		assertEquals(HttpStatus.SC_OK, response.getStatus());
-		assertEquals(MediaType.APPLICATION_OCTET_STREAM, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(keyService).generateKey(getUserInfo(), true);
-		verifyNoMoreInteractions(keyService);
-	}
-
-	@Test
-	public void generateKeyWithoutEdgeCreation() {
-		when(keyService.generateKey(any(UserInfo.class), anyBoolean())).thenReturn("someUuid");
-
-		final Response response = resources.getJerseyTest()
-				.target("/user/access_key/generate")
-				.queryParam("is_primary_uploading", "false")
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.json(""));
-
-		assertEquals(HttpStatus.SC_OK, response.getStatus());
-		assertEquals(MediaType.APPLICATION_OCTET_STREAM, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(keyService).generateKey(getUserInfo(), false);
-		verifyNoMoreInteractions(keyService);
-	}
-
-	@Test
-	public void generateKeyWithFailedAuth() throws AuthenticationException {
-		authFailSetup();
-		when(keyService.generateKey(any(UserInfo.class), anyBoolean())).thenReturn("someUuid");
-
-		final Response response = resources.getJerseyTest()
-				.target("/user/access_key/generate")
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.json(""));
-
-		assertEquals(HttpStatus.SC_OK, response.getStatus());
-		assertEquals(MediaType.APPLICATION_OCTET_STREAM, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(keyService).generateKey(getUserInfo(), true);
-		verifyNoMoreInteractions(keyService);
-	}
-
-	@Test
-	public void generateKeyWithException() {
-		doThrow(new DlabException("Can not generate private/public key pair due to"))
-				.when(keyService).generateKey(any(UserInfo.class), anyBoolean());
-
-		final Response response = resources.getJerseyTest()
-				.target("/user/access_key/generate")
-				.request()
-				.header("Authorization", "Bearer " + TOKEN)
-				.post(Entity.json(""));
-
-		assertEquals(HttpStatus.SC_INTERNAL_SERVER_ERROR, response.getStatus());
-		assertEquals(MediaType.APPLICATION_JSON, response.getHeaderString(HttpHeaders.CONTENT_TYPE));
-
-		verify(keyService).generateKey(getUserInfo(), true);
-		verifyNoMoreInteractions(keyService);
-	}
-
-}
diff --git a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/aws/AwsBillingServiceTest.java b/services/self-service/src/test/java/com/epam/dlab/backendapi/service/aws/AwsBillingServiceTest.java
index d7d00b5..0c9cf26 100644
--- a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/aws/AwsBillingServiceTest.java
+++ b/services/self-service/src/test/java/com/epam/dlab/backendapi/service/aws/AwsBillingServiceTest.java
@@ -21,7 +21,7 @@ package com.epam.dlab.backendapi.service.aws;
 
 import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.dao.aws.AwsBillingDAO;
-import com.epam.dlab.backendapi.resources.dto.aws.AwsBillingFilter;
+import com.epam.dlab.backendapi.resources.dto.BillingFilter;
 import com.epam.dlab.exceptions.DlabException;
 import org.bson.Document;
 import org.junit.Before;
@@ -38,14 +38,21 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
-import static org.junit.Assert.*;
-import static org.mockito.Mockito.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
 
 @RunWith(MockitoJUnitRunner.class)
 public class AwsBillingServiceTest {
 
 	private UserInfo userInfo;
-	private AwsBillingFilter billingFilter;
+	private BillingFilter billingFilter;
 	private Document basicDocument;
 
 	@Mock
@@ -60,14 +67,14 @@ public class AwsBillingServiceTest {
 	@Before
 	public void setUp() {
 		userInfo = getUserInfo();
-		billingFilter = new AwsBillingFilter();
+		billingFilter = new BillingFilter();
 		basicDocument = getBasicDocument();
 	}
 
 	@Test
 	public void getReportWithTheSameInstanceOfDocument() {
 		Document expectedDocument = new Document();
-		when(billingDAO.getReport(any(UserInfo.class), any(AwsBillingFilter.class))).thenReturn(expectedDocument);
+		when(billingDAO.getReport(any(UserInfo.class), any(BillingFilter.class))).thenReturn(expectedDocument);
 
 		Document actualDocument = awsBillingService.getReport(userInfo, billingFilter);
 		assertEquals(expectedDocument, actualDocument);
@@ -80,7 +87,7 @@ public class AwsBillingServiceTest {
 	public void getReportWithAnotherInstanceOfDocument() {
 		Document expectedDocument = new Document().append("someField", "someValue");
 		Document anotherDocument = new Document().append("someField", "anotherValue");
-		when(billingDAO.getReport(any(UserInfo.class), any(AwsBillingFilter.class))).thenReturn(anotherDocument);
+		when(billingDAO.getReport(any(UserInfo.class), any(BillingFilter.class))).thenReturn(anotherDocument);
 
 		Document actualDocument = awsBillingService.getReport(userInfo, billingFilter);
 		assertNotEquals(expectedDocument, actualDocument);
@@ -91,7 +98,7 @@ public class AwsBillingServiceTest {
 
 	@Test
 	public void getReportWithException() {
-		doThrow(new RuntimeException()).when(billingDAO).getReport(any(UserInfo.class), any(AwsBillingFilter.class));
+		doThrow(new RuntimeException()).when(billingDAO).getReport(any(UserInfo.class), any(BillingFilter.class));
 
 		try {
 			awsBillingService.getReport(userInfo, billingFilter);
@@ -105,7 +112,7 @@ public class AwsBillingServiceTest {
 
 	@Test
 	public void downloadReport() {
-		when(billingDAO.getReport(any(UserInfo.class), any(AwsBillingFilter.class))).thenReturn(basicDocument);
+		when(billingDAO.getReport(any(UserInfo.class), any(BillingFilter.class))).thenReturn(basicDocument);
 
 		byte[] result = awsBillingService.downloadReport(userInfo, billingFilter);
 		assertNotNull(result);
@@ -118,7 +125,7 @@ public class AwsBillingServiceTest {
 	@Test
 	public void downloadReportWithInapproprietaryDateFormatInDocument() {
 		basicDocument.put("from", "someDateStart");
-		when(billingDAO.getReport(any(UserInfo.class), any(AwsBillingFilter.class))).thenReturn(basicDocument);
+		when(billingDAO.getReport(any(UserInfo.class), any(BillingFilter.class))).thenReturn(basicDocument);
 
 		try {
 			awsBillingService.downloadReport(userInfo, billingFilter);
@@ -133,7 +140,7 @@ public class AwsBillingServiceTest {
 	@Test
 	public void downloadReportWhenDocumentHasNotAllRequiredFields() {
 		basicDocument.remove("lines");
-		when(billingDAO.getReport(any(UserInfo.class), any(AwsBillingFilter.class))).thenReturn(basicDocument);
+		when(billingDAO.getReport(any(UserInfo.class), any(BillingFilter.class))).thenReturn(basicDocument);
 
 		expectedException.expect(NullPointerException.class);
 
diff --git a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/aws/AwsInfrastructureInfoServiceTest.java b/services/self-service/src/test/java/com/epam/dlab/backendapi/service/aws/AwsInfrastructureInfoServiceTest.java
deleted file mode 100644
index 50aeb39..0000000
--- a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/aws/AwsInfrastructureInfoServiceTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.service.aws;
-
-import com.epam.dlab.dto.aws.edge.EdgeInfoAws;
-import org.junit.Test;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-
-public class AwsInfrastructureInfoServiceTest {
-
-	@Test
-	public void getSharedInfo() {
-		EdgeInfoAws edgeInfoAws = new EdgeInfoAws();
-		edgeInfoAws.setPublicIp("ip");
-		edgeInfoAws.setUserOwnBucketName("userOwnBucketName");
-		edgeInfoAws.setSharedBucketName("sharedBucketName");
-
-		Map<String, String> expectedMap = new HashMap<>();
-		expectedMap.put("edge_node_ip", "ip");
-		expectedMap.put("user_own_bicket_name", "userOwnBucketName");
-		expectedMap.put("shared_bucket_name", "sharedBucketName");
-
-		Map<String, String> actualMap = new AwsInfrastructureInfoService().getSharedInfo(edgeInfoAws);
-		assertEquals(expectedMap, actualMap);
-	}
-}
diff --git a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/aws/AwsInfrastructureTemplateServiceTest.java b/services/self-service/src/test/java/com/epam/dlab/backendapi/service/aws/AwsInfrastructureTemplateServiceTest.java
deleted file mode 100644
index 118e7e8..0000000
--- a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/aws/AwsInfrastructureTemplateServiceTest.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.service.aws;
-
-import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
-import com.epam.dlab.backendapi.resources.dto.aws.AwsEmrConfiguration;
-import com.epam.dlab.dto.base.computational.FullComputationalTemplate;
-import com.epam.dlab.dto.imagemetadata.ComputationalMetadataDTO;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
-
-import java.lang.reflect.Field;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Mockito.*;
-
-@RunWith(MockitoJUnitRunner.class)
-public class AwsInfrastructureTemplateServiceTest {
-
-	@Mock
-	private SelfServiceApplicationConfiguration configuration;
-
-	@InjectMocks
-	private AwsInfrastructureTemplateService awsInfrastructureTemplateService;
-
-	@Test
-	public void getCloudFullComputationalTemplate() throws NoSuchFieldException, IllegalAccessException {
-		when(configuration.getMinEmrInstanceCount()).thenReturn(2);
-		when(configuration.getMaxEmrInstanceCount()).thenReturn(1000);
-		when(configuration.getMaxEmrSpotInstanceBidPct()).thenReturn(95);
-		when(configuration.getMinEmrSpotInstanceBidPct()).thenReturn(10);
-
-		AwsEmrConfiguration expectedAwsEmrConfiguration = AwsEmrConfiguration.builder()
-				.minEmrInstanceCount(2)
-				.maxEmrInstanceCount(1000)
-				.maxEmrSpotInstanceBidPct(95)
-				.minEmrSpotInstanceBidPct(10)
-				.build();
-
-		ComputationalMetadataDTO expectedComputationalMetadataDTO =
-				new ComputationalMetadataDTO("someImageName");
-
-		FullComputationalTemplate fullComputationalTemplate =
-				awsInfrastructureTemplateService.getCloudFullComputationalTemplate(expectedComputationalMetadataDTO);
-		assertNotNull(fullComputationalTemplate);
-
-		Field actualAwsEmrConfiguration =
-				fullComputationalTemplate.getClass().getDeclaredField("awsEmrConfiguration");
-		actualAwsEmrConfiguration.setAccessible(true);
-		assertEquals(expectedAwsEmrConfiguration, actualAwsEmrConfiguration.get(fullComputationalTemplate));
-
-		Field actualComputationalMetadataDTO = fullComputationalTemplate.getClass().getSuperclass()
-				.getDeclaredField("computationalMetadataDTO");
-		actualComputationalMetadataDTO.setAccessible(true);
-		assertEquals(expectedComputationalMetadataDTO, actualComputationalMetadataDTO.get(fullComputationalTemplate));
-
-		verify(configuration).getMinEmrInstanceCount();
-		verify(configuration).getMaxEmrInstanceCount();
-		verify(configuration).getMaxEmrSpotInstanceBidPct();
-		verify(configuration).getMinEmrSpotInstanceBidPct();
-		verifyNoMoreInteractions(configuration);
-	}
-}
diff --git a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/azure/AzureBillingServiceTest.java b/services/self-service/src/test/java/com/epam/dlab/backendapi/service/azure/AzureBillingServiceTest.java
index cc96d0a..ebd4b83 100644
--- a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/azure/AzureBillingServiceTest.java
+++ b/services/self-service/src/test/java/com/epam/dlab/backendapi/service/azure/AzureBillingServiceTest.java
@@ -21,7 +21,7 @@ package com.epam.dlab.backendapi.service.azure;
 
 import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.dao.BillingDAO;
-import com.epam.dlab.backendapi.resources.dto.azure.AzureBillingFilter;
+import com.epam.dlab.backendapi.resources.dto.BillingFilter;
 import com.epam.dlab.exceptions.DlabException;
 import org.bson.Document;
 import org.junit.Before;
@@ -38,18 +38,24 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
-import static org.junit.Assert.*;
-import static org.mockito.Mockito.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
 
 @RunWith(MockitoJUnitRunner.class)
 public class AzureBillingServiceTest {
 
 	private UserInfo userInfo;
-	private AzureBillingFilter billingFilter;
+	private BillingFilter billingFilter;
 	private Document basicDocument;
 
 	@Mock
-	private BillingDAO<AzureBillingFilter> billingDAO;
+	private BillingDAO billingDAO;
 
 	@InjectMocks
 	private AzureBillingService azureBillingService;
@@ -60,13 +66,13 @@ public class AzureBillingServiceTest {
 	@Before
 	public void setUp() {
 		userInfo = getUserInfo();
-		billingFilter = new AzureBillingFilter();
+		billingFilter = new BillingFilter();
 		basicDocument = getBasicDocument();
 	}
 
 	@Test
 	public void getReportWithTheSameInstanceOfDocument() {
-		when(billingDAO.getReport(any(UserInfo.class), any(AzureBillingFilter.class))).thenReturn(new Document());
+		when(billingDAO.getReport(any(UserInfo.class), any(BillingFilter.class))).thenReturn(new Document());
 
 		Document actualDocument = azureBillingService.getReport(userInfo, billingFilter);
 		assertEquals(new Document(), actualDocument);
@@ -77,7 +83,7 @@ public class AzureBillingServiceTest {
 
 	@Test
 	public void getReportWithException() {
-		doThrow(new RuntimeException()).when(billingDAO).getReport(any(UserInfo.class), any(AzureBillingFilter.class));
+		doThrow(new RuntimeException()).when(billingDAO).getReport(any(UserInfo.class), any(BillingFilter.class));
 
 		try {
 			azureBillingService.getReport(userInfo, billingFilter);
@@ -91,7 +97,7 @@ public class AzureBillingServiceTest {
 
 	@Test
 	public void downloadReport() {
-		when(billingDAO.getReport(any(UserInfo.class), any(AzureBillingFilter.class))).thenReturn(basicDocument);
+		when(billingDAO.getReport(any(UserInfo.class), any(BillingFilter.class))).thenReturn(basicDocument);
 
 		byte[] result = azureBillingService.downloadReport(userInfo, billingFilter);
 		assertNotNull(result);
@@ -104,7 +110,7 @@ public class AzureBillingServiceTest {
 	@Test
 	public void downloadReportWithInapproprietaryDateFormatInDocument() {
 		basicDocument.put("from", "someDateStart");
-		when(billingDAO.getReport(any(UserInfo.class), any(AzureBillingFilter.class))).thenReturn(basicDocument);
+		when(billingDAO.getReport(any(UserInfo.class), any(BillingFilter.class))).thenReturn(basicDocument);
 
 		try {
 			azureBillingService.downloadReport(userInfo, billingFilter);
@@ -119,7 +125,7 @@ public class AzureBillingServiceTest {
 	@Test
 	public void downloadReportWhenDocumentHasNotAllRequiredFields() {
 		basicDocument.remove("lines");
-		when(billingDAO.getReport(any(UserInfo.class), any(AzureBillingFilter.class))).thenReturn(basicDocument);
+		when(billingDAO.getReport(any(UserInfo.class), any(BillingFilter.class))).thenReturn(basicDocument);
 
 		expectedException.expect(NullPointerException.class);
 
diff --git a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/azure/AzureInfrastructureInfoServiceTest.java b/services/self-service/src/test/java/com/epam/dlab/backendapi/service/azure/AzureInfrastructureInfoServiceTest.java
deleted file mode 100644
index 37f5e46..0000000
--- a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/azure/AzureInfrastructureInfoServiceTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.service.azure;
-
-import com.epam.dlab.dto.azure.edge.EdgeInfoAzure;
-import org.junit.Test;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-
-public class AzureInfrastructureInfoServiceTest {
-
-	@Test
-	public void getSharedInfo() {
-		EdgeInfoAzure edgeInfoAzure = new EdgeInfoAzure();
-		edgeInfoAzure.setPublicIp("ip");
-		edgeInfoAzure.setUserContainerName("userContainerName");
-		edgeInfoAzure.setSharedContainerName("sharedContainerName");
-		edgeInfoAzure.setUserStorageAccountName("userStorageAccountName");
-		edgeInfoAzure.setSharedStorageAccountName("sharedStorageAccountName");
-		edgeInfoAzure.setDataLakeName("datalakeName");
-		edgeInfoAzure.setDataLakeDirectoryName("datalakeUserDirectoryName");
-		edgeInfoAzure.setDataLakeSharedDirectoryName("datalakeSharedDirectoryName");
-
-		Map<String, String> expectedMap = new HashMap<>();
-		expectedMap.put("edge_node_ip", "ip");
-		expectedMap.put("user_container_name", "userContainerName");
-		expectedMap.put("shared_container_name", "sharedContainerName");
-		expectedMap.put("user_storage_account_name", "userStorageAccountName");
-		expectedMap.put("shared_storage_account_name", "sharedStorageAccountName");
-		expectedMap.put("datalake_name", "datalakeName");
-		expectedMap.put("datalake_user_directory_name", "datalakeUserDirectoryName");
-		expectedMap.put("datalake_shared_directory_name", "datalakeSharedDirectoryName");
-
-		Map<String, String> actualMap = new AzureInfrastructureInfoService().getSharedInfo(edgeInfoAzure);
-		assertEquals(expectedMap, actualMap);
-	}
-}
diff --git a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/azure/AzureInfrastructureTemplateServiceTest.java b/services/self-service/src/test/java/com/epam/dlab/backendapi/service/azure/AzureInfrastructureTemplateServiceTest.java
deleted file mode 100644
index 0da7503..0000000
--- a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/azure/AzureInfrastructureTemplateServiceTest.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.service.azure;
-
-import com.epam.dlab.dto.imagemetadata.ComputationalMetadataDTO;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-public class AzureInfrastructureTemplateServiceTest {
-
-	@Rule
-	public ExpectedException expectedException = ExpectedException.none();
-
-	@Test
-	public void getCloudFullComputationalTemplate() {
-		expectedException.expect(UnsupportedOperationException.class);
-		expectedException.expectMessage("Operation is not supported currently");
-		new AzureInfrastructureTemplateService().getCloudFullComputationalTemplate(new ComputationalMetadataDTO());
-	}
-}
diff --git a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/gcp/GcpInfrastructureInfoServiceTest.java b/services/self-service/src/test/java/com/epam/dlab/backendapi/service/gcp/GcpInfrastructureInfoServiceTest.java
deleted file mode 100644
index b57daf3..0000000
--- a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/gcp/GcpInfrastructureInfoServiceTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.service.gcp;
-
-import com.epam.dlab.dto.gcp.edge.EdgeInfoGcp;
-import org.junit.Test;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.junit.Assert.assertEquals;
-
-public class GcpInfrastructureInfoServiceTest {
-
-	@Test
-	public void getSharedInfo() {
-		EdgeInfoGcp edgeInfoGcp = new EdgeInfoGcp();
-		edgeInfoGcp.setPublicIp("ip");
-		edgeInfoGcp.setUserOwnBucketName("userOwnBucketName");
-		edgeInfoGcp.setSharedBucketName("sharedBucketName");
-
-		Map<String, String> expectedMap = new HashMap<>();
-		expectedMap.put("edge_node_ip", "ip");
-		expectedMap.put("user_own_bucket_name", "userOwnBucketName");
-		expectedMap.put("shared_bucket_name", "sharedBucketName");
-
-		Map<String, String> actualMap = new GcpInfrastructureInfoService().getSharedInfo(edgeInfoGcp);
-		assertEquals(expectedMap, actualMap);
-	}
-}
diff --git a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/gcp/GcpInfrastructureTemplateServiceTest.java b/services/self-service/src/test/java/com/epam/dlab/backendapi/service/gcp/GcpInfrastructureTemplateServiceTest.java
deleted file mode 100644
index 2010b76..0000000
--- a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/gcp/GcpInfrastructureTemplateServiceTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.service.gcp;
-
-import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
-import com.epam.dlab.backendapi.resources.dto.gcp.GcpDataprocConfiguration;
-import com.epam.dlab.dto.base.computational.FullComputationalTemplate;
-import com.epam.dlab.dto.imagemetadata.ComputationalMetadataDTO;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
-
-import java.lang.reflect.Field;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Mockito.*;
-
-@RunWith(MockitoJUnitRunner.class)
-public class GcpInfrastructureTemplateServiceTest {
-
-	@Mock
-	private SelfServiceApplicationConfiguration configuration;
-
-	@InjectMocks
-	private GcpInfrastructureTemplateService gcpInfrastructureTemplateService;
-
-	@Test
-	public void getCloudFullComputationalTemplate() throws NoSuchFieldException, IllegalAccessException {
-		when(configuration.getMinInstanceCount()).thenReturn(2);
-		when(configuration.getMaxInstanceCount()).thenReturn(100);
-		when(configuration.getMinDataprocPreemptibleCount()).thenReturn(10);
-
-		GcpDataprocConfiguration expectedGcpDataprocConfiguration = GcpDataprocConfiguration.builder()
-				.minInstanceCount(2)
-				.maxInstanceCount(100)
-				.minDataprocPreemptibleInstanceCount(10)
-				.build();
-
-		ComputationalMetadataDTO expectedComputationalMetadataDTO =
-				new ComputationalMetadataDTO("someImageName");
-
-		FullComputationalTemplate fullComputationalTemplate =
-				gcpInfrastructureTemplateService.getCloudFullComputationalTemplate(expectedComputationalMetadataDTO);
-		assertNotNull(fullComputationalTemplate);
-
-		Field actualGcpDataprocConfiguration =
-				fullComputationalTemplate.getClass().getDeclaredField("gcpDataprocConfiguration");
-		actualGcpDataprocConfiguration.setAccessible(true);
-		assertEquals(expectedGcpDataprocConfiguration, actualGcpDataprocConfiguration.get(fullComputationalTemplate));
-
-		Field actualComputationalMetadataDTO = fullComputationalTemplate.getClass().getSuperclass()
-				.getDeclaredField("computationalMetadataDTO");
-		actualComputationalMetadataDTO.setAccessible(true);
-		assertEquals(expectedComputationalMetadataDTO, actualComputationalMetadataDTO.get(fullComputationalTemplate));
-
-		verify(configuration).getMinInstanceCount();
-		verify(configuration).getMaxInstanceCount();
-		verify(configuration).getMinDataprocPreemptibleCount();
-		verifyNoMoreInteractions(configuration);
-	}
-}
diff --git a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/AccessKeyServiceImplTest.java b/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/AccessKeyServiceImplTest.java
deleted file mode 100644
index c68a3d0..0000000
--- a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/AccessKeyServiceImplTest.java
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.service.impl;
-
-import com.epam.dlab.auth.UserInfo;
-import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
-import com.epam.dlab.backendapi.dao.KeyDAO;
-import com.epam.dlab.backendapi.domain.RequestId;
-import com.epam.dlab.backendapi.service.ExploratoryService;
-import com.epam.dlab.backendapi.service.ReuploadKeyService;
-import com.epam.dlab.backendapi.util.RequestBuilder;
-import com.epam.dlab.dto.UserInstanceStatus;
-import com.epam.dlab.dto.base.edge.EdgeInfo;
-import com.epam.dlab.dto.base.keyload.UploadFile;
-import com.epam.dlab.dto.keyload.KeyLoadStatus;
-import com.epam.dlab.dto.keyload.UserKeyDTO;
-import com.epam.dlab.exceptions.DlabException;
-import com.epam.dlab.rest.client.RESTService;
-import org.apache.commons.lang3.StringUtils;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.runner.RunWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
-
-import static org.junit.Assert.*;
-import static org.mockito.Mockito.*;
-
-@RunWith(MockitoJUnitRunner.class)
-public class AccessKeyServiceImplTest {
-
-	private final String USER = "test";
-	private final String TOKEN = "token";
-
-	private UserInfo userInfo;
-
-	@Mock
-	private KeyDAO keyDAO;
-	@Mock
-	private RESTService provisioningService;
-	@Mock
-	private RequestBuilder requestBuilder;
-	@Mock
-	private RequestId requestId;
-	@Mock
-	private ExploratoryService exploratoryService;
-	@Mock
-	private SelfServiceApplicationConfiguration configuration;
-	@Mock
-	private ReuploadKeyService reuploadKeyService;
-
-	@InjectMocks
-	private AccessKeyServiceImpl accessKeyService;
-
-	@Rule
-	public ExpectedException expectedException = ExpectedException.none();
-
-	@Before
-	public void setUp() {
-		userInfo = getUserInfo();
-	}
-
-	@Test
-	public void getUserKeyStatus() {
-		when(keyDAO.findKeyStatus(anyString())).thenReturn(KeyLoadStatus.SUCCESS);
-
-		KeyLoadStatus keyLoadStatus = accessKeyService.getUserKeyStatus(USER);
-		assertEquals(KeyLoadStatus.SUCCESS, keyLoadStatus);
-
-		verify(keyDAO).findKeyStatus(USER);
-		verifyNoMoreInteractions(keyDAO);
-	}
-
-	@Test
-	public void getUserKeyStatusWithException() {
-		doThrow(new DlabException("Some message")).when(keyDAO).findKeyStatus(anyString());
-
-		KeyLoadStatus keyLoadStatus = accessKeyService.getUserKeyStatus(USER);
-		assertEquals(KeyLoadStatus.ERROR, keyLoadStatus);
-
-		verify(keyDAO).findKeyStatus(USER);
-		verifyNoMoreInteractions(keyDAO);
-	}
-
-	@Test
-	public void uploadKey() {
-		doNothing().when(keyDAO).upsertKey(anyString(), anyString(), anyBoolean());
-		doNothing().when(exploratoryService).updateExploratoriesReuploadKeyFlag(anyString(), anyBoolean(),
-				anyVararg());
-
-		UploadFile uploadFile = mock(UploadFile.class);
-		when(requestBuilder.newEdgeKeyUpload(any(UserInfo.class), anyString())).thenReturn(uploadFile);
-
-		String expectedUuid = "someUuid";
-		when(provisioningService.post(anyString(), anyString(), any(UploadFile.class), any())).
-				thenReturn(expectedUuid);
-		when(requestId.put(anyString(), anyString())).thenReturn(expectedUuid);
-
-		String keyContent = "keyContent";
-		String actualUuid = accessKeyService.uploadKey(userInfo, keyContent, true);
-		assertNotNull(actualUuid);
-		assertEquals(expectedUuid, actualUuid);
-
-		verify(keyDAO).upsertKey(USER, keyContent, true);
-		verifyZeroInteractions(exploratoryService);
-		verify(requestBuilder).newEdgeKeyUpload(userInfo, keyContent);
-		verify(provisioningService).post("infrastructure/edge/create", TOKEN, uploadFile, String.class);
-		verify(requestId).put(USER, expectedUuid);
-		verifyNoMoreInteractions(keyDAO, requestBuilder, provisioningService, requestId);
-	}
-
-
-	@Test
-	public void uploadKeyWithException() {
-		doNothing().when(keyDAO).upsertKey(anyString(), anyString(), anyBoolean());
-		doNothing().when(exploratoryService).updateExploratoriesReuploadKeyFlag(anyString(), anyBoolean(), anyVararg());
-		doThrow(new RuntimeException()).when(requestBuilder).newEdgeKeyUpload(any(UserInfo.class), anyString());
-
-		expectedException.expect(RuntimeException.class);
-
-		doNothing().when(keyDAO).deleteKey(anyString());
-		expectedException.expect(DlabException.class);
-		expectedException.expectMessage("Could not upload the key and create EDGE node: ");
-
-		accessKeyService.uploadKey(userInfo, "someKeyContent", true);
-	}
-
-	@Test
-	public void reUploadKey() {
-		doNothing().when(keyDAO).upsertKey(anyString(), anyString(), anyBoolean());
-		when(reuploadKeyService.reuploadKey(any(UserInfo.class), anyString())).thenReturn("someString");
-
-		String expectedString = "someString";
-		String keyContent = "keyContent";
-		String actualString = accessKeyService.uploadKey(userInfo, keyContent, false);
-		assertNotNull(actualString);
-		assertEquals(expectedString, actualString);
-
-		verify(keyDAO).upsertKey(USER, keyContent, false);
-		verify(reuploadKeyService).reuploadKey(userInfo, keyContent);
-		verifyNoMoreInteractions(keyDAO, reuploadKeyService);
-	}
-
-	@Test
-	public void reUploadKeyWithException() {
-		doNothing().when(keyDAO).upsertKey(anyString(), anyString(), anyBoolean());
-		doThrow(new RuntimeException()).when(reuploadKeyService).reuploadKey(any(UserInfo.class), anyString());
-
-		expectedException.expect(RuntimeException.class);
-
-		expectedException.expect(DlabException.class);
-		expectedException.expectMessage("Could not reupload the key. Previous key has been deleted:");
-
-		accessKeyService.uploadKey(userInfo, "someKeyContent", false);
-	}
-
-	@Test
-	public void recoverEdge() {
-		EdgeInfo edgeInfo = new EdgeInfo();
-		edgeInfo.setId("someId");
-		edgeInfo.setEdgeStatus("failed");
-		when(keyDAO.getEdgeInfo(anyString())).thenReturn(edgeInfo);
-
-		UserKeyDTO userKeyDTO = new UserKeyDTO();
-		userKeyDTO.withStatus("someStatus");
-		userKeyDTO.withContent("someContent");
-		when(keyDAO.fetchKey(anyString(), any(KeyLoadStatus.class))).thenReturn(userKeyDTO);
-
-		edgeInfo.setEdgeStatus("terminated");
-		edgeInfo.setInstanceId(null);
-
-		doNothing().when(keyDAO).updateEdgeInfo(anyString(), any(EdgeInfo.class));
-
-		UploadFile uploadFile = mock(UploadFile.class);
-		when(requestBuilder.newEdgeKeyUpload(any(UserInfo.class), anyString())).thenReturn(uploadFile);
-
-		String expectedUuid = "someUuid";
-		when(provisioningService.post(anyString(), anyString(), any(UploadFile.class), any()))
-				.thenReturn(expectedUuid);
-		when(requestId.put(anyString(), anyString())).thenReturn(expectedUuid);
-
-		String actualUuid = accessKeyService.recoverEdge(userInfo);
-		assertNotNull(actualUuid);
-		assertEquals(expectedUuid, actualUuid);
-
-		verify(keyDAO).getEdgeInfo(USER);
-		verify(keyDAO).fetchKey(USER, KeyLoadStatus.SUCCESS);
-		verify(keyDAO).updateEdgeInfo(USER, edgeInfo);
-
-		verify(requestBuilder).newEdgeKeyUpload(userInfo, userKeyDTO.getContent());
-		verify(provisioningService).post("infrastructure/edge/create", TOKEN, uploadFile, String.class);
-		verify(requestId).put(USER, expectedUuid);
-		verifyNoMoreInteractions(keyDAO, requestBuilder, provisioningService, requestId);
-	}
-
-	@Test
-	public void recoverEdgeWithExceptionInGetEdgeInfoMethod() {
-		EdgeInfo edgeInfo = new EdgeInfo();
-		edgeInfo.setId("someId");
-		edgeInfo.setEdgeStatus("running");
-		when(keyDAO.getEdgeInfo(anyString())).thenReturn(edgeInfo);
-
-		expectedException.expect(DlabException.class);
-		expectedException.expectMessage("Could not create EDGE node because the status of instance is running");
-
-		doNothing().when(keyDAO).updateEdgeStatus(anyString(), anyString());
-
-		expectedException.expect(DlabException.class);
-		expectedException.expectMessage("Could not upload the key and create EDGE node:");
-
-		accessKeyService.recoverEdge(userInfo);
-
-		verify(keyDAO).getEdgeInfo(USER);
-		verify(keyDAO).updateEdgeStatus(USER, UserInstanceStatus.FAILED.toString());
-		verifyNoMoreInteractions(keyDAO);
-		verifyZeroInteractions(requestBuilder, provisioningService, requestId);
-	}
-
-	@Test
-	public void recoverEdgeWithExceptionInFetchKeyMethod() {
-		EdgeInfo edgeInfo = new EdgeInfo();
-		edgeInfo.setId("someId");
-		edgeInfo.setEdgeStatus("failed");
-		when(keyDAO.getEdgeInfo(anyString())).thenReturn(edgeInfo);
-
-		UserKeyDTO userKeyDTO = new UserKeyDTO();
-		userKeyDTO.withStatus("someStatus");
-		userKeyDTO.withContent("someContent");
-		doThrow(new DlabException(String.format("Key of user %s with status %s not found", USER,
-				KeyLoadStatus.SUCCESS))).when(keyDAO).fetchKey(anyString(), eq(KeyLoadStatus.SUCCESS));
-
-		doNothing().when(keyDAO).updateEdgeStatus(anyString(), anyString());
-
-		expectedException.expect(DlabException.class);
-		expectedException.expectMessage("Could not upload the key and create EDGE node: ");
-
-		accessKeyService.recoverEdge(userInfo);
-
-		verify(keyDAO).getEdgeInfo(USER);
-		verify(keyDAO).fetchKey(USER, KeyLoadStatus.SUCCESS);
-		verify(keyDAO).updateEdgeStatus(USER, UserInstanceStatus.FAILED.toString());
-		verifyNoMoreInteractions(keyDAO);
-		verifyZeroInteractions(requestBuilder, provisioningService, requestId);
-	}
-
-	@Test
-	public void generateKey() {
-		doNothing().when(keyDAO).upsertKey(anyString(), anyString(), anyBoolean());
-
-		UploadFile uploadFile = mock(UploadFile.class);
-		when(requestBuilder.newEdgeKeyUpload(any(UserInfo.class), anyString())).thenReturn(uploadFile);
-
-		String someUuid = "someUuid";
-		when(configuration.getPrivateKeySize()).thenReturn(2048);
-		when(provisioningService.post(anyString(), anyString(), any(UploadFile.class), any())).thenReturn(someUuid);
-		when(requestId.put(anyString(), anyString())).thenReturn(someUuid);
-
-		String actualPrivateKey = accessKeyService.generateKey(userInfo, true);
-		assertTrue(StringUtils.isNotEmpty(actualPrivateKey));
-
-		verify(keyDAO).upsertKey(eq(USER), anyString(), eq(true));
-		verify(requestBuilder).newEdgeKeyUpload(refEq(userInfo), anyString());
-		verify(provisioningService).post("infrastructure/edge/create", TOKEN, uploadFile, String.class);
-		verify(requestId).put(USER, someUuid);
-		verifyNoMoreInteractions(keyDAO, requestBuilder, provisioningService, requestId);
-	}
-
-	@Test
-	public void generateKeyWithException() {
-		doNothing().when(keyDAO).upsertKey(anyString(), anyString(), anyBoolean());
-		when(configuration.getPrivateKeySize()).thenReturn(2048);
-		doThrow(new RuntimeException()).when(requestBuilder).newEdgeKeyUpload(any(UserInfo.class), anyString());
-		doNothing().when(keyDAO).deleteKey(anyString());
-
-		try {
-			accessKeyService.generateKey(userInfo, true);
-		} catch (DlabException e) {
-			assertEquals("Could not upload the key and create EDGE node: ", e.getMessage());
-		}
-
-		verify(keyDAO).upsertKey(eq(USER), anyString(), eq(true));
-		verify(requestBuilder).newEdgeKeyUpload(refEq(userInfo), anyString());
-		verify(keyDAO).deleteKey(USER);
-		verifyNoMoreInteractions(keyDAO, requestBuilder);
-	}
-
-	private UserInfo getUserInfo() {
-		return new UserInfo(USER, TOKEN);
-	}
-
-}
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 33821e6..8331235 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
@@ -33,6 +33,7 @@ import com.epam.dlab.backendapi.service.EndpointService;
 import com.epam.dlab.backendapi.service.ProjectService;
 import com.epam.dlab.backendapi.service.TagService;
 import com.epam.dlab.backendapi.util.RequestBuilder;
+import com.epam.dlab.cloud.CloudProvider;
 import com.epam.dlab.dto.SchedulerJobDTO;
 import com.epam.dlab.dto.UserInstanceDTO;
 import com.epam.dlab.dto.UserInstanceStatus;
@@ -140,7 +141,8 @@ public class ComputationalServiceImplTest {
 
 		ComputationalBase compBaseMocked = mock(ComputationalBase.class);
 		when(requestBuilder.newComputationalCreate(any(UserInfo.class), any(ProjectDTO.class),
-				any(UserInstanceDTO.class), any(SparkStandaloneClusterCreateForm.class))).thenReturn(compBaseMocked);
+				any(UserInstanceDTO.class), any(SparkStandaloneClusterCreateForm.class), any(EndpointDTO.class)))
+				.thenReturn(compBaseMocked);
 		when(provisioningService.post(anyString(), anyString(), any(ComputationalBase.class), any())).thenReturn(UUID);
 		when(requestId.put(anyString(), anyString())).thenReturn(UUID);
 
@@ -155,7 +157,7 @@ public class ComputationalServiceImplTest {
 
 		verify(exploratoryDAO).fetchExploratoryFields(USER, EXPLORATORY_NAME);
 		verify(requestBuilder).newComputationalCreate(
-				refEq(userInfo), refEq(projectDTO), refEq(userInstance), refEq(sparkClusterCreateForm));
+				refEq(userInfo), refEq(projectDTO), refEq(userInstance), refEq(sparkClusterCreateForm), refEq(endpointDTO()));
 
 		verify(provisioningService)
 				.post(endpointDTO().getUrl() + ComputationalAPI.COMPUTATIONAL_CREATE_SPARK, TOKEN, compBaseMocked,
@@ -207,6 +209,7 @@ public class ComputationalServiceImplTest {
 	@Test
 	public void createSparkClusterWhenMethodNewComputationalCreateThrowsException() {
 		ProjectDTO projectDTO = getProjectDTO();
+		when(endpointService.get(anyString())).thenReturn(endpointDTO());
 		when(projectService.get(anyString())).thenReturn(projectDTO);
 		when(computationalDAO.addComputational(anyString(), anyString(),
 				any(SparkStandaloneClusterResource.class))).thenReturn(true);
@@ -214,7 +217,7 @@ public class ComputationalServiceImplTest {
 
 		doThrow(new DlabException("Cannot create instance of resource class "))
 				.when(requestBuilder).newComputationalCreate(any(UserInfo.class), any(ProjectDTO.class),
-				any(UserInstanceDTO.class), any(SparkStandaloneClusterCreateForm.class));
+				any(UserInstanceDTO.class), any(SparkStandaloneClusterCreateForm.class), any(EndpointDTO.class));
 
 		when(computationalDAO.updateComputationalStatus(any(ComputationalStatusDTO.class)))
 				.thenReturn(mock(UpdateResult.class));
@@ -229,7 +232,7 @@ public class ComputationalServiceImplTest {
 		verify(computationalDAO).addComputational(USER, EXPLORATORY_NAME, sparkClusterResource);
 		verify(computationalDAO).updateComputationalStatus(refEq(computationalStatusDTOWithStatusFailed, "self"));
 		verify(exploratoryDAO).fetchExploratoryFields(USER, EXPLORATORY_NAME);
-		verify(requestBuilder).newComputationalCreate(userInfo, projectDTO, userInstance, sparkClusterCreateForm);
+		verify(requestBuilder).newComputationalCreate(userInfo, projectDTO, userInstance, sparkClusterCreateForm, endpointDTO());
 		verifyNoMoreInteractions(projectService, configuration, computationalDAO, exploratoryDAO, requestBuilder);
 	}
 
@@ -252,7 +255,7 @@ public class ComputationalServiceImplTest {
 		ctDto.setComputationalName(COMP_NAME);
 		ctDto.setExploratoryName(EXPLORATORY_NAME);
 		when(requestBuilder.newComputationalTerminate(any(UserInfo.class), any(UserInstanceDTO.class),
-				any(UserComputationalResource.class))).thenReturn(ctDto);
+				any(UserComputationalResource.class), any(EndpointDTO.class))).thenReturn(ctDto);
 
 		when(provisioningService.post(anyString(), anyString(), any(ComputationalTerminateDTO.class), any()))
 				.thenReturn(UUID);
@@ -263,7 +266,7 @@ public class ComputationalServiceImplTest {
 		verify(computationalDAO).updateComputationalStatus(refEq(computationalStatusDTOWithStatusTerminating, "self"));
 		verify(computationalDAO).fetchComputationalFields(USER, EXPLORATORY_NAME, COMP_NAME);
 
-		verify(requestBuilder).newComputationalTerminate(userInfo, userInstance,ucResource);
+		verify(requestBuilder).newComputationalTerminate(userInfo, userInstance, ucResource, endpointDTO());
 
 		verify(provisioningService).post(endpointDTO().getUrl() + ComputationalAPI.COMPUTATIONAL_TERMINATE_CLOUD_SPECIFIC, TOKEN, ctDto,
 				String.class);
@@ -320,9 +323,9 @@ public class ComputationalServiceImplTest {
 
 	@Test
 	public void terminateComputationalEnvironmentWhenMethodNewComputationalTerminateThrowsException() {
+		when(endpointService.get(anyString())).thenReturn(endpointDTO());
 		when(computationalDAO.updateComputationalStatus(any(ComputationalStatusDTO.class)))
 				.thenReturn(mock(UpdateResult.class));
-		String explId = "explId";
 		when(exploratoryDAO.fetchExploratoryFields(anyString(), anyString())).thenReturn(userInstance);
 
 		String compId = "compId";
@@ -334,7 +337,7 @@ public class ComputationalServiceImplTest {
 
 		doThrow(new DlabException("Cannot create instance of resource class "))
 				.when(requestBuilder).newComputationalTerminate(any(UserInfo.class), any(UserInstanceDTO.class),
-				any(UserComputationalResource.class));
+				any(UserComputationalResource.class), any(EndpointDTO.class));
 
 		when(computationalDAO.updateComputationalStatus(any(ComputationalStatusDTO.class)))
 				.thenReturn(mock(UpdateResult.class));
@@ -350,7 +353,7 @@ public class ComputationalServiceImplTest {
 
 		verify(exploratoryDAO).fetchExploratoryFields(USER, EXPLORATORY_NAME);
 
-		verify(requestBuilder).newComputationalTerminate(userInfo, userInstance, ucResource);
+		verify(requestBuilder).newComputationalTerminate(userInfo, userInstance, ucResource, endpointDTO());
 		verify(computationalDAO).updateComputationalStatus(refEq(computationalStatusDTOWithStatusFailed, "self"));
 		verifyNoMoreInteractions(computationalDAO, exploratoryDAO, requestBuilder);
 	}
@@ -366,7 +369,8 @@ public class ComputationalServiceImplTest {
 
 		ComputationalBase compBaseMocked = mock(ComputationalBase.class);
 		when(requestBuilder.newComputationalCreate(any(UserInfo.class), any(ProjectDTO.class),
-				any(UserInstanceDTO.class), any(ComputationalCreateFormDTO.class))).thenReturn(compBaseMocked);
+				any(UserInstanceDTO.class), any(ComputationalCreateFormDTO.class), any(EndpointDTO.class)))
+				.thenReturn(compBaseMocked);
 
 		when(provisioningService.post(anyString(), anyString(), any(ComputationalBase.class), any())).thenReturn(UUID);
 		when(requestId.put(anyString(), anyString())).thenReturn(UUID);
@@ -382,7 +386,7 @@ public class ComputationalServiceImplTest {
 		verify(exploratoryDAO).fetchExploratoryFields(USER, EXPLORATORY_NAME);
 
 		verify(requestBuilder).newComputationalCreate(
-				refEq(userInfo), refEq(projectDTO), refEq(userInstance), any(ComputationalCreateFormDTO.class));
+				refEq(userInfo), refEq(projectDTO), refEq(userInstance), any(ComputationalCreateFormDTO.class), refEq(endpointDTO()));
 
 		verify(provisioningService)
 				.post(endpointDTO().getUrl() + ComputationalAPI.COMPUTATIONAL_CREATE_CLOUD_SPECIFIC, TOKEN,
@@ -443,7 +447,7 @@ public class ComputationalServiceImplTest {
 
 		doThrow(new DlabException("Cannot create instance of resource class "))
 				.when(requestBuilder).newComputationalCreate(any(UserInfo.class), any(ProjectDTO.class),
-				any(UserInstanceDTO.class), any(ComputationalCreateFormDTO.class));
+				any(UserInstanceDTO.class), any(ComputationalCreateFormDTO.class), any(EndpointDTO.class));
 
 		when(computationalDAO.updateComputationalStatus(any(ComputationalStatusDTO.class)))
 				.thenReturn(mock(UpdateResult.class));
@@ -460,7 +464,7 @@ public class ComputationalServiceImplTest {
 		verify(computationalDAO).addComputational(eq(USER), eq(EXPLORATORY_NAME), refEq(ucResource));
 		verify(exploratoryDAO).fetchExploratoryFields(USER, EXPLORATORY_NAME);
 		verify(requestBuilder).newComputationalCreate(
-				refEq(userInfo), refEq(projectDTO), refEq(userInstance), refEq(computationalCreateFormDTO));
+				refEq(userInfo), refEq(projectDTO), refEq(userInstance), refEq(computationalCreateFormDTO), refEq(endpointDTO()));
 		verify(computationalDAO).updateComputationalStatus(refEq(computationalStatusDTOWithStatusFailed, "self"));
 
 		verifyNoMoreInteractions(projectService, computationalDAO, exploratoryDAO, requestBuilder);
@@ -476,8 +480,8 @@ public class ComputationalServiceImplTest {
 				.thenReturn(mock(UpdateResult.class));
 
 		ComputationalStopDTO computationalStopDTO = new ComputationalStopDTO();
-		when(requestBuilder.newComputationalStop(any(UserInfo.class), any(UserInstanceDTO.class), anyString()))
-				.thenReturn(computationalStopDTO);
+		when(requestBuilder.newComputationalStop(any(UserInfo.class), any(UserInstanceDTO.class), anyString(),
+				any(EndpointDTO.class))).thenReturn(computationalStopDTO);
 		when(provisioningService.post(anyString(), anyString(), any(ComputationalBase.class), any()))
 				.thenReturn("someUuid");
 		when(requestId.put(anyString(), anyString())).thenReturn("someUuid");
@@ -486,7 +490,7 @@ public class ComputationalServiceImplTest {
 
 		verify(computationalDAO).updateComputationalStatus(refEq(computationalStatusDTOWithStatusStopping, "self"));
 		verify(exploratoryDAO).fetchExploratoryFields(USER, EXPLORATORY_NAME, true);
-		verify(requestBuilder).newComputationalStop(refEq(userInfo), refEq(exploratory), eq(COMP_NAME));
+		verify(requestBuilder).newComputationalStop(refEq(userInfo), refEq(exploratory), eq(COMP_NAME), refEq(endpointDTO()));
 		verify(provisioningService)
 				.post(eq(endpointDTO().getUrl() + "computational/stop/spark"), eq(TOKEN), refEq(computationalStopDTO),
 						eq(String.class));
@@ -516,8 +520,8 @@ public class ComputationalServiceImplTest {
 				.thenReturn(mock(UpdateResult.class));
 
 		ComputationalStartDTO computationalStartDTO = new ComputationalStartDTO();
-		when(requestBuilder.newComputationalStart(any(UserInfo.class), any(UserInstanceDTO.class), anyString()))
-				.thenReturn(computationalStartDTO);
+		when(requestBuilder.newComputationalStart(any(UserInfo.class), any(UserInstanceDTO.class), anyString(),
+				any(EndpointDTO.class))).thenReturn(computationalStartDTO);
 		when(provisioningService.post(anyString(), anyString(), any(ComputationalBase.class), any()))
 				.thenReturn("someUuid");
 		when(requestId.put(anyString(), anyString())).thenReturn("someUuid");
@@ -526,7 +530,7 @@ public class ComputationalServiceImplTest {
 
 		verify(computationalDAO).updateComputationalStatus(refEq(computationalStatusDTOWithStatusStarting, "self"));
 		verify(exploratoryDAO).fetchExploratoryFields(USER, EXPLORATORY_NAME, true);
-		verify(requestBuilder).newComputationalStart(refEq(userInfo), refEq(exploratory), eq(COMP_NAME));
+		verify(requestBuilder).newComputationalStart(refEq(userInfo), refEq(exploratory), eq(COMP_NAME), refEq(endpointDTO()));
 		verify(provisioningService)
 				.post(eq(endpointDTO().getUrl() + "computational/start/spark"), eq(TOKEN),
 						refEq(computationalStartDTO),
@@ -600,7 +604,8 @@ public class ComputationalServiceImplTest {
 		userInstanceDto.setResources(Collections.singletonList(getUserComputationalResource(RUNNING, COMP_NAME)));
 		when(exploratoryDAO.fetchExploratoryFields(anyString(), anyString(), anyBoolean())).thenReturn(userInstanceDto);
 		when(requestBuilder.newClusterConfigUpdate(any(UserInfo.class), any(UserInstanceDTO.class),
-				any(UserComputationalResource.class), anyListOf(ClusterConfig.class))).thenReturn(clusterConfigDTO);
+				any(UserComputationalResource.class), anyListOf(ClusterConfig.class), any(EndpointDTO.class)))
+				.thenReturn(clusterConfigDTO);
 		when(provisioningService.post(anyString(), anyString(), any(ComputationalClusterConfigDTO.class), any()))
 				.thenReturn("someUuid");
 		computationalService.updateSparkClusterConfig(getUserInfo(), EXPLORATORY_NAME, COMP_NAME,
@@ -609,7 +614,7 @@ public class ComputationalServiceImplTest {
 		verify(exploratoryDAO).fetchExploratoryFields(USER, EXPLORATORY_NAME, true);
 		verify(requestBuilder).newClusterConfigUpdate(refEq(getUserInfo()), refEq(userInstanceDto),
 				refEq(getUserComputationalResource(RUNNING, COMP_NAME)),
-				eq(Collections.singletonList(new ClusterConfig())));
+				eq(Collections.singletonList(new ClusterConfig())), eq(endpointDTO()));
 		verify(requestId).put(USER, "someUuid");
 		verify(computationalDAO).updateComputationalFields(refEq(new ComputationalStatusDTO()
 				.withConfig(config)
@@ -736,7 +741,7 @@ public class ComputationalServiceImplTest {
 	}
 
 	private EndpointDTO endpointDTO() {
-		return new EndpointDTO("test", "url", "", null, EndpointDTO.EndpointStatus.ACTIVE);
+		return new EndpointDTO("test", "url", "", null, EndpointDTO.EndpointStatus.ACTIVE, CloudProvider.AWS);
 	}
 
 
diff --git a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/EdgeServiceImplTest.java b/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/EdgeServiceImplTest.java
deleted file mode 100644
index 09784eb..0000000
--- a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/EdgeServiceImplTest.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package com.epam.dlab.backendapi.service.impl;
-
-import com.epam.dlab.auth.UserInfo;
-import com.epam.dlab.backendapi.dao.KeyDAO;
-import com.epam.dlab.backendapi.domain.RequestId;
-import com.epam.dlab.backendapi.util.RequestBuilder;
-import com.epam.dlab.dto.ResourceSysBaseDTO;
-import com.epam.dlab.dto.UserInstanceStatus;
-import com.epam.dlab.exceptions.DlabException;
-import com.epam.dlab.rest.client.RESTService;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.runner.RunWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.runners.MockitoJUnitRunner;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.mockito.Mockito.*;
-
-@RunWith(MockitoJUnitRunner.class)
-public class EdgeServiceImplTest {
-
-	private final String USER = "test";
-	private final String TOKEN = "token";
-	private final String UUID = "1234-56789765-4321";
-	private final String STATUS_STOPPED = "stopped";
-	private final String STATUS_RUNNING = "running";
-	private UserInfo userInfo;
-
-	@Mock
-	private KeyDAO keyDAO;
-	@Mock
-	private RESTService provisioningService;
-	@Mock
-	private RequestBuilder requestBuilder;
-	@Mock
-	private RequestId requestId;
-
-	@InjectMocks
-	private EdgeServiceImpl edgeService;
-
-	@Rule
-	public ExpectedException expectedException = ExpectedException.none();
-
-	@Before
-	public void setUp() {
-		userInfo = getUserInfo();
-	}
-
-	@Test
-	public void start() {
-		when(keyDAO.getEdgeStatus(anyString())).thenReturn(STATUS_STOPPED);
-		doNothing().when(keyDAO).updateEdgeStatus(anyString(), anyString());
-		ResourceSysBaseDTO rsbDto = new ResourceSysBaseDTO();
-		when(requestBuilder.newEdgeAction(any(UserInfo.class))).thenReturn(rsbDto);
-		String edgeStart = "infrastructure/edge/start";
-		when(provisioningService.post(anyString(), anyString(), any(ResourceSysBaseDTO.class), any()))
-				.thenReturn(UUID);
-		when(requestId.put(anyString(), anyString())).thenReturn(UUID);
-
-		String uuid = edgeService.start(userInfo);
-		assertNotNull(uuid);
-		assertEquals(UUID, uuid);
-
-		verify(keyDAO).getEdgeStatus(USER);
-		verify(keyDAO).updateEdgeStatus(USER, "starting");
-		verify(requestBuilder).newEdgeAction(userInfo);
-		verify(provisioningService).post(edgeStart, TOKEN, rsbDto, String.class);
-		verify(requestId).put(USER, UUID);
-		verifyNoMoreInteractions(keyDAO, requestBuilder, provisioningService, requestId);
-	}
-
-	@Test
-	public void startWithInappropriateEdgeStatus() {
-		when(keyDAO.getEdgeStatus(anyString())).thenReturn(STATUS_RUNNING);
-		expectedException.expect(DlabException.class);
-		expectedException.expectMessage("Could not start EDGE node because the status of instance is running");
-
-		edgeService.start(userInfo);
-	}
-
-	@Test
-	public void startWhenMethodNewEdgeActionThrowsException() {
-		when(keyDAO.getEdgeStatus(anyString())).thenReturn(STATUS_STOPPED);
-		doNothing().when(keyDAO).updateEdgeStatus(anyString(), anyString());
-
-		doThrow(new DlabException("Cannot create instance of resource class "))
-				.when(requestBuilder).newEdgeAction(any(UserInfo.class));
-		try {
-			edgeService.start(userInfo);
-		} catch (DlabException e) {
-			assertEquals("Could not start EDGE node: Could not infrastructure/edge/start EDGE node : " +
-					"Cannot create instance of resource class ", e.getMessage());
-		}
-		verify(keyDAO).getEdgeStatus(USER);
-		verify(keyDAO).updateEdgeStatus(USER, "starting");
-		verify(keyDAO).updateEdgeStatus(USER, "failed");
-		verify(requestBuilder).newEdgeAction(userInfo);
-		verifyNoMoreInteractions(keyDAO, requestBuilder);
-	}
-
-	@Test
-	public void stop() {
-		when(keyDAO.getEdgeStatus(anyString())).thenReturn(STATUS_RUNNING);
-		doNothing().when(keyDAO).updateEdgeStatus(anyString(), anyString());
-		ResourceSysBaseDTO rsbDto = new ResourceSysBaseDTO();
-		when(requestBuilder.newEdgeAction(any(UserInfo.class))).thenReturn(rsbDto);
-		String edgeStop = "infrastructure/edge/stop";
-		when(provisioningService.post(anyString(), anyString(), any(ResourceSysBaseDTO.class), any())).thenReturn
-				(UUID);
-		when(requestId.put(anyString(), anyString())).thenReturn(UUID);
-
-		String uuid = edgeService.stop(userInfo);
-		assertNotNull(uuid);
-		assertEquals(UUID, uuid);
-
-		verify(keyDAO).getEdgeStatus(USER);
-		verify(keyDAO).updateEdgeStatus(USER, "stopping");
-		verify(requestBuilder).newEdgeAction(userInfo);
-		verify(provisioningService).post(edgeStop, TOKEN, rsbDto, String.class);
-		verify(requestId).put(USER, UUID);
-		verifyNoMoreInteractions(keyDAO, requestBuilder, provisioningService, requestId);
-	}
-
-	@Test
-	public void stopWithInappropriateEdgeStatus() {
-		when(keyDAO.getEdgeStatus(anyString())).thenReturn(STATUS_STOPPED);
-		expectedException.expect(DlabException.class);
-		expectedException.expectMessage("Could not stop EDGE node because the status of instance is stopped");
-
-		edgeService.stop(userInfo);
-	}
-
-	@Test
-	public void stopWhenMethodNewEdgeActionThrowsException() {
-		when(keyDAO.getEdgeStatus(anyString())).thenReturn(STATUS_RUNNING);
-		doNothing().when(keyDAO).updateEdgeStatus(anyString(), anyString());
-
-		doThrow(new DlabException("Cannot create instance of resource class "))
-				.when(requestBuilder).newEdgeAction(any(UserInfo.class));
-		try {
-			edgeService.stop(userInfo);
-		} catch (DlabException e) {
-			assertEquals("Could not stop EDGE node: Could not infrastructure/edge/stop EDGE node : " +
-					"Cannot create instance of resource class ", e.getMessage());
-		}
-		verify(keyDAO).getEdgeStatus(USER);
-		verify(keyDAO).updateEdgeStatus(USER, "stopping");
-		verify(keyDAO).updateEdgeStatus(USER, "failed");
-		verify(requestBuilder).newEdgeAction(userInfo);
-		verifyNoMoreInteractions(keyDAO, requestBuilder);
-	}
-
-	@Test
-	public void terminate() {
-		when(keyDAO.getEdgeStatus(anyString())).thenReturn(STATUS_RUNNING);
-		doNothing().when(keyDAO).updateEdgeStatus(anyString(), anyString());
-		ResourceSysBaseDTO rsbDto = new ResourceSysBaseDTO();
-		when(requestBuilder.newEdgeAction(any(UserInfo.class))).thenReturn(rsbDto);
-		String edgeTerminate = "infrastructure/edge/terminate";
-		when(provisioningService.post(anyString(), anyString(), any(ResourceSysBaseDTO.class), any()))
-				.thenReturn(UUID);
-		when(requestId.put(anyString(), anyString())).thenReturn(UUID);
-
-		String uuid = edgeService.terminate(userInfo);
-		assertNotNull(uuid);
-		assertEquals(UUID, uuid);
-
-		verify(keyDAO).getEdgeStatus(USER);
-		verify(keyDAO).updateEdgeStatus(USER, "terminating");
-		verify(requestBuilder).newEdgeAction(userInfo);
-		verify(provisioningService).post(edgeTerminate, TOKEN, rsbDto, String.class);
-		verify(requestId).put(USER, UUID);
-		verifyNoMoreInteractions(keyDAO, requestBuilder, provisioningService, requestId);
-	}
-
-	@Test
-	public void terminateWithInappropriateEdgeStatus() {
-		when(keyDAO.getEdgeStatus(anyString())).thenReturn(anyString());
-		expectedException.expect(DlabException.class);
-		expectedException.expectMessage("Could not terminate EDGE node because the status of instance is null");
-
-		edgeService.terminate(userInfo);
-	}
-
-	@Test
-	public void terminateWhenMethodNewEdgeActionThrowsException() {
-		when(keyDAO.getEdgeStatus(anyString())).thenReturn(STATUS_RUNNING);
-		doNothing().when(keyDAO).updateEdgeStatus(anyString(), anyString());
-
-		doThrow(new DlabException("Cannot create instance of resource class "))
-				.when(requestBuilder).newEdgeAction(any(UserInfo.class));
-		try {
-			edgeService.terminate(userInfo);
-		} catch (DlabException e) {
-			assertEquals("Could not terminate EDGE node: Could not infrastructure/edge/terminate EDGE node : " +
-					"Cannot create instance of resource class ", e.getMessage());
-		}
-		verify(keyDAO).getEdgeStatus(USER);
-		verify(keyDAO).updateEdgeStatus(USER, "terminating");
-		verify(keyDAO).updateEdgeStatus(USER, "failed");
-		verify(requestBuilder).newEdgeAction(userInfo);
-		verifyNoMoreInteractions(keyDAO, requestBuilder);
-	}
-
-	@Test
-	public void updateReuploadKeyFlag() {
-		doNothing().when(keyDAO).updateEdgeReuploadKey(anyString(), anyBoolean(), anyVararg());
-		edgeService.updateReuploadKeyFlag(USER, true, UserInstanceStatus.RUNNING);
-
-		verify(keyDAO).updateEdgeReuploadKey(USER, true, UserInstanceStatus.RUNNING);
-		verifyNoMoreInteractions(keyDAO);
-	}
-
-	private UserInfo getUserInfo() {
-		return new UserInfo(USER, TOKEN);
-	}
-}
diff --git a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/EnvironmentServiceImplTest.java b/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/EnvironmentServiceImplTest.java
index bc8db84..5396ca8 100644
--- a/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/EnvironmentServiceImplTest.java
+++ b/services/self-service/src/test/java/com/epam/dlab/backendapi/service/impl/EnvironmentServiceImplTest.java
@@ -22,16 +22,14 @@ package com.epam.dlab.backendapi.service.impl;
 import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.dao.EnvDAO;
 import com.epam.dlab.backendapi.dao.ExploratoryDAO;
-import com.epam.dlab.backendapi.dao.KeyDAO;
 import com.epam.dlab.backendapi.dao.UserSettingsDAO;
 import com.epam.dlab.backendapi.domain.ProjectDTO;
 import com.epam.dlab.backendapi.domain.ProjectEndpointDTO;
 import com.epam.dlab.backendapi.resources.dto.UserDTO;
 import com.epam.dlab.backendapi.service.ComputationalService;
-import com.epam.dlab.backendapi.service.EdgeService;
 import com.epam.dlab.backendapi.service.ExploratoryService;
-import com.epam.dlab.backendapi.service.SecurityService;
 import com.epam.dlab.backendapi.service.ProjectService;
+import com.epam.dlab.backendapi.service.SecurityService;
 import com.epam.dlab.dto.UserInstanceDTO;
 import com.epam.dlab.dto.UserInstanceStatus;
 import com.epam.dlab.dto.base.edge.EdgeInfo;
@@ -76,10 +74,6 @@ public class EnvironmentServiceImplTest {
 	@Mock
 	private ComputationalService computationalService;
 	@Mock
-	private EdgeService edgeService;
-	@Mock
-	private KeyDAO keyDAO;
-	@Mock
 	private UserSettingsDAO userSettingsDAO;
 	@Mock
 	private ProjectService projectService;
@@ -145,24 +139,18 @@ public class EnvironmentServiceImplTest {
 	public void stopEnvironment() {
 		final UserInfo userInfo = getUserInfo();
 		when(exploratoryDAO.fetchRunningExploratoryFields(anyString())).thenReturn(getUserInstances());
-		when(securityService.getUserInfoOffline(anyString())).thenReturn(userInfo);
 		when(exploratoryService.stop(any(UserInfo.class), anyString())).thenReturn(UUID);
-		when(keyDAO.getEdgeStatus(anyString())).thenReturn(RUNNING_STATE);
-		when(edgeService.stop(any(UserInfo.class))).thenReturn(UUID);
 
 		environmentService.stopEnvironment(userInfo, USER);
 
 		verify(exploratoryDAO).fetchRunningExploratoryFields(USER);
-		verify(securityService).getUserInfoOffline(USER);
 		verify(exploratoryService).stop(refEq(userInfo), eq(EXPLORATORY_NAME_1));
 		verify(exploratoryService).stop(refEq(userInfo), eq(EXPLORATORY_NAME_2));
-		verify(keyDAO, times(2)).getEdgeStatus(USER);
-		verify(edgeService).stop(refEq(userInfo));
 		verify(exploratoryDAO).fetchUserExploratoriesWhereStatusIn(USER, Arrays.asList(UserInstanceStatus.CREATING,
 				UserInstanceStatus.STARTING, UserInstanceStatus.CREATING_IMAGE),
 				UserInstanceStatus.CREATING,
 				UserInstanceStatus.STARTING, UserInstanceStatus.CREATING_IMAGE);
-		verifyNoMoreInteractions(keyDAO, exploratoryDAO, edgeService, exploratoryService);
+		verifyNoMoreInteractions(exploratoryDAO, exploratoryService);
 	}
 
 	@Test
@@ -176,32 +164,20 @@ public class EnvironmentServiceImplTest {
 	}
 
 	@Test
-	public void stopEnvironmentWithEdgeStarting() {
-		when(keyDAO.getEdgeStatus(anyString())).thenReturn("starting");
-		expectedException.expect(ResourceConflictException.class);
-
-		environmentService.stopEnvironment(getUserInfo(), USER);
-	}
-
-	@Test
 	public void stopEnvironmentWithoutEdge() {
 		final UserInfo userInfo = getUserInfo();
 		when(exploratoryDAO.fetchRunningExploratoryFields(anyString())).thenReturn(getUserInstances());
 		when(exploratoryService.stop(any(UserInfo.class), anyString())).thenReturn(UUID);
-		when(keyDAO.getEdgeStatus(anyString())).thenReturn(STOPPED_STATE);
-		when(edgeService.stop(any(UserInfo.class))).thenReturn(UUID);
 
 		environmentService.stopEnvironment(userInfo, USER);
 
 		verify(exploratoryDAO).fetchRunningExploratoryFields(USER);
 		verify(exploratoryService).stop(refEq(userInfo), eq(EXPLORATORY_NAME_1));
 		verify(exploratoryService).stop(refEq(userInfo), eq(EXPLORATORY_NAME_2));
-		verify(keyDAO, times(2)).getEdgeStatus(USER);
-		verify(edgeService, never()).stop(refEq(userInfo));
 		verify(exploratoryDAO).fetchUserExploratoriesWhereStatusIn(USER, Arrays.asList(UserInstanceStatus.CREATING,
 				UserInstanceStatus.STARTING, UserInstanceStatus.CREATING_IMAGE),
 				UserInstanceStatus.CREATING, UserInstanceStatus.STARTING, UserInstanceStatus.CREATING_IMAGE);
-		verifyNoMoreInteractions(keyDAO, envDAO, exploratoryDAO, edgeService, exploratoryService);
+		verifyNoMoreInteractions(envDAO, exploratoryDAO, exploratoryService);
 	}
 
 	@Test
@@ -230,32 +206,6 @@ public class EnvironmentServiceImplTest {
 	}
 
 	@Test
-	public void stopEdge() {
-		final UserInfo userInfo = getUserInfo();
-		when(keyDAO.getEdgeStatus(anyString())).thenReturn(RUNNING_STATE);
-		when(securityService.getUserInfoOffline(anyString())).thenReturn(userInfo);
-		when(edgeService.stop(any(UserInfo.class))).thenReturn(UUID);
-
-		environmentService.stopEdge(USER);
-
-		verify(keyDAO).getEdgeStatus(USER);
-		verify(securityService).getUserInfoOffline(USER);
-		verify(edgeService).stop(refEq(userInfo));
-		verifyNoMoreInteractions(keyDAO, securityService, edgeService);
-	}
-
-	@Test
-	public void stopEdgeWhenItIsNotRunning() {
-		when(keyDAO.getEdgeStatus(anyString())).thenReturn("starting");
-
-		environmentService.stopEdge(USER);
-
-		verify(keyDAO).getEdgeStatus(USER);
-		verifyZeroInteractions(securityService, edgeService);
-		verifyNoMoreInteractions(keyDAO);
-	}
-
-	@Test
 	public void stopExploratory() {
 		final UserInfo userInfo = getUserInfo();
 		when(exploratoryService.stop(any(UserInfo.class), anyString())).thenReturn(UUID);
@@ -278,76 +228,6 @@ public class EnvironmentServiceImplTest {
 	}
 
 	@Test
-	@SuppressWarnings("unchecked")
-	public void terminateEnvironment() {
-		final UserInfo userInfo = getUserInfo();
-		when(exploratoryDAO.fetchUserExploratoriesWhereStatusIn(anyString(), any(List.class), anyVararg()))
-				.thenReturn(Collections.emptyList());
-		when(securityService.getUserInfoOffline(anyString())).thenReturn(userInfo);
-		when(exploratoryService.terminate(any(UserInfo.class), anyString())).thenReturn(UUID);
-		when(keyDAO.edgeNodeExist(anyString())).thenReturn(true);
-		when(edgeService.terminate(any(UserInfo.class))).thenReturn(UUID);
-
-		environmentService.terminateEnvironment(userInfo, USER);
-
-		verify(exploratoryDAO).fetchUserExploratoriesWhereStatusIn(anyString(), any(List.class), anyVararg());
-		verify(securityService).getUserInfoOffline(USER);
-		verify(keyDAO).edgeNodeExist(USER);
-		verify(edgeService).terminate(refEq(userInfo));
-		verify(exploratoryService).updateExploratoryStatuses(USER, UserInstanceStatus.TERMINATING);
-		verify(keyDAO).getEdgeStatus(userInfo.getName());
-		verify(exploratoryDAO).fetchUserExploratoriesWhereStatusIn(USER, Arrays.asList(UserInstanceStatus.CREATING,
-				UserInstanceStatus.STARTING, UserInstanceStatus.CREATING_IMAGE),
-				UserInstanceStatus.CREATING, UserInstanceStatus.STARTING, UserInstanceStatus.CREATING_IMAGE);
-		verifyNoMoreInteractions(keyDAO, envDAO, exploratoryDAO, edgeService, exploratoryService);
-	}
-
-	@Test
-	@SuppressWarnings("unchecked")
-	public void terminateEnvironmentWithoutEdge() {
-		final UserInfo userInfo = getUserInfo();
-		when(exploratoryDAO.fetchUserExploratoriesWhereStatusIn(anyString(), any(List.class),
-				eq(UserInstanceStatus.CREATING), eq(UserInstanceStatus.STARTING))).thenReturn(Collections.emptyList());
-		when(exploratoryDAO.fetchUserExploratoriesWhereStatusNotIn(anyString(), eq(UserInstanceStatus.TERMINATED),
-				eq(UserInstanceStatus.FAILED), eq(UserInstanceStatus.TERMINATING))).thenReturn(getUserInstances());
-		when(exploratoryService.terminate(any(UserInfo.class), anyString())).thenReturn(UUID);
-		when(keyDAO.edgeNodeExist(anyString())).thenReturn(false);
-		when(edgeService.terminate(any(UserInfo.class))).thenReturn(UUID);
-
-		environmentService.terminateEnvironment(userInfo, USER);
-
-		verify(exploratoryDAO).fetchUserExploratoriesWhereStatusNotIn(USER, UserInstanceStatus.TERMINATED,
-				UserInstanceStatus.FAILED, UserInstanceStatus.TERMINATING);
-		verify(exploratoryService).terminate(refEq(userInfo), eq(EXPLORATORY_NAME_1));
-		verify(exploratoryService).terminate(refEq(userInfo), eq(EXPLORATORY_NAME_2));
-		verify(keyDAO).edgeNodeExist(USER);
-		verify(edgeService, never()).terminate(refEq(userInfo));
-		verify(keyDAO).getEdgeStatus(USER);
-		verify(exploratoryDAO).fetchUserExploratoriesWhereStatusIn(USER, Arrays.asList(UserInstanceStatus.CREATING,
-				UserInstanceStatus.STARTING, UserInstanceStatus.CREATING_IMAGE),
-				UserInstanceStatus.CREATING, UserInstanceStatus.STARTING, UserInstanceStatus.CREATING_IMAGE);
-		verifyNoMoreInteractions(keyDAO, envDAO, exploratoryDAO, edgeService, exploratoryService);
-	}
-
-	@Test
-	@SuppressWarnings("unchecked")
-	public void terminateEnvironmentWithWrongResourceState() {
-		when(exploratoryDAO.fetchUserExploratoriesWhereStatusIn(anyString(), any(List.class), anyVararg()))
-				.thenReturn(getUserInstances());
-		expectedException.expect(ResourceConflictException.class);
-
-		environmentService.terminateEnvironment(getUserInfo(), USER);
-	}
-
-	@Test
-	public void terminateEnvironmentWithEdgeStarting() {
-		when(keyDAO.getEdgeStatus(anyString())).thenReturn("starting");
-		expectedException.expect(ResourceConflictException.class);
-
-		environmentService.terminateEnvironment(getUserInfo(), USER);
-	}
-
-	@Test
 	public void terminateExploratory() {
 		final UserInfo userInfo = getUserInfo();
 		when(exploratoryService.terminate(any(UserInfo.class), anyString())).thenReturn(UUID);
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 f37071a..5d0bdb2 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
@@ -31,6 +31,7 @@ import com.epam.dlab.backendapi.service.EndpointService;
 import com.epam.dlab.backendapi.service.ProjectService;
 import com.epam.dlab.backendapi.service.TagService;
 import com.epam.dlab.backendapi.util.RequestBuilder;
+import com.epam.dlab.cloud.CloudProvider;
 import com.epam.dlab.dto.StatusEnvBaseDTO;
 import com.epam.dlab.dto.UserInstanceDTO;
 import com.epam.dlab.dto.UserInstanceStatus;
@@ -117,7 +118,7 @@ public class ExploratoryServiceImplTest {
 
 		ExploratoryActionDTO egcuDto = new ExploratoryGitCredsUpdateDTO();
 		egcuDto.withExploratoryName(EXPLORATORY_NAME);
-		when(requestBuilder.newExploratoryStart(any(UserInfo.class), any(UserInstanceDTO.class),
+		when(requestBuilder.newExploratoryStart(any(UserInfo.class), any(UserInstanceDTO.class), any(EndpointDTO.class),
 				any(ExploratoryGitCredsDTO.class))).thenReturn(egcuDto);
 
 		String exploratoryStart = "exploratory/start";
@@ -167,7 +168,8 @@ public class ExploratoryServiceImplTest {
 
 		ExploratoryActionDTO eaDto = new ExploratoryActionDTO();
 		eaDto.withExploratoryName(EXPLORATORY_NAME);
-		when(requestBuilder.newExploratoryStop(any(UserInfo.class), any(UserInstanceDTO.class))).thenReturn(eaDto);
+		when(requestBuilder.newExploratoryStop(any(UserInfo.class), any(UserInstanceDTO.class), any(EndpointDTO.class)))
+				.thenReturn(eaDto);
 
 		String exploratoryStop = "exploratory/stop";
 		when(provisioningService.post(anyString(), anyString(), any(ExploratoryActionDTO.class), any())).thenReturn
@@ -219,7 +221,8 @@ public class ExploratoryServiceImplTest {
 
 		ExploratoryActionDTO eaDto = new ExploratoryActionDTO();
 		eaDto.withExploratoryName(EXPLORATORY_NAME);
-		when(requestBuilder.newExploratoryStop(any(UserInfo.class), any(UserInstanceDTO.class))).thenReturn(eaDto);
+		when(requestBuilder.newExploratoryStop(any(UserInfo.class), any(UserInstanceDTO.class), any(EndpointDTO.class)))
+				.thenReturn(eaDto);
 
 		String exploratoryTerminate = "exploratory/terminate";
 		when(provisioningService.post(anyString(), anyString(), any(ExploratoryActionDTO.class), any())).thenReturn
@@ -237,7 +240,7 @@ public class ExploratoryServiceImplTest {
 		verify(computationalDAO).updateComputationalStatusesForExploratory(USER, EXPLORATORY_NAME, UserInstanceStatus
 						.TERMINATING, UserInstanceStatus.TERMINATING, UserInstanceStatus.TERMINATED,
 				UserInstanceStatus.FAILED);
-		verify(requestBuilder).newExploratoryStop(userInfo, userInstance);
+		verify(requestBuilder).newExploratoryStop(userInfo, userInstance, endpointDTO());
 		verify(provisioningService).post(endpointDTO().getUrl() + exploratoryTerminate, TOKEN, eaDto, String.class);
 		verify(requestId).put(USER, UUID);
 		verifyNoMoreInteractions(exploratoryDAO, computationalDAO, requestBuilder, provisioningService, requestId);
... 876 lines suppressed ...


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