com.sap.cds.feature.mt.MtUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cds-feature-mt Show documentation
Show all versions of cds-feature-mt Show documentation
Multi tenancy feature for CDS Services Java
/**************************************************************************
* (C) 2019-2021 SAP SE or an SAP affiliate company. All rights reserved. *
**************************************************************************/
package com.sap.cds.feature.mt;
import java.nio.file.Paths;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.google.common.annotations.VisibleForTesting;
import com.sap.cds.services.environment.CdsProperties.MultiTenancy;
import com.sap.cds.services.environment.ServiceBinding;
import com.sap.cds.services.runtime.CdsRuntime;
import com.sap.cds.services.utils.CdsErrorStatuses;
import com.sap.cds.services.utils.ErrorStatusException;
import com.sap.cds.services.utils.StringUtils;
import com.sap.cds.services.utils.model.DynamicModelUtils;
import com.sap.cloud.mt.subscription.DbCredentials;
import com.sap.cloud.mt.subscription.DbCredentialsBuilder;
import com.sap.cloud.mt.subscription.DbIdentifiers;
import com.sap.cloud.mt.subscription.DbIdentifiersHana;
import com.sap.cloud.mt.subscription.DbIdentifiersSqLite;
import com.sap.cloud.mt.subscription.DbIdentifiersSql;
import com.sap.cloud.mt.subscription.InstanceLifecycleManager;
import com.sap.cloud.mt.subscription.InstanceLifecycleManagerBuilder;
import com.sap.cloud.mt.subscription.exceptions.InternalError;
import com.sap.xsa.core.instancemanager.client.ImClientException;
import com.sap.xsa.core.instancemanager.client.ServiceManagerClient;
import com.sap.xsa.core.instancemanager.client.impl.InstanceManagerClientFactory;
public class MtUtils {
private static final String HANA_OFFERING_NAME = "hana";
private static final String HANA_HDI_PLAN_NAME = "hdi-shared";
static final String SERVICE_MANAGER = "service-manager";
static final String MT_ENABLED = "mt-enabled";
static final String SQLITE_BINDING_NAME = "mtx-sqlite";
private final DynamicModelUtils dynamicModelUtils;
private final MultiTenancy config;
private final List bindings;
private final ServiceBinding defaultBinding;
public MtUtils(CdsRuntime runtime) {
this.dynamicModelUtils = new DynamicModelUtils(runtime);
this.config = runtime.getEnvironment().getCdsProperties().getMultiTenancy();
// calculate bindings
this.bindings = runtime.getEnvironment().getServiceBindings()
.filter(b -> isServiceManagerBinding(b) || isSchemaBasedMtBinding(b))
.collect(Collectors.toList());
String bindingName = runtime.getEnvironment().getCdsProperties().getDataSource().getBinding();
if(StringUtils.isEmpty(bindingName)) {
if(bindings.size() == 1) {
defaultBinding = bindings.get(0);
} else if (bindings.size() > 1) {
throw new ErrorStatusException(CdsErrorStatuses.NO_UNIQUE_DATASOURCE_SERVICE);
} else {
defaultBinding = null;
}
} else {
defaultBinding = bindings.stream().filter(b -> b.getName().equals(bindingName)).findFirst().orElse(null);
}
}
public boolean requiresSubscription() {
boolean deployerConfigured = hasDeployer();
return (defaultBinding != null && (deployerConfigured || isSchemaBasedMtBinding(defaultBinding)))
|| (isSqliteDataSourceEnabled() && deployerConfigured);
}
private boolean hasDeployer() {
boolean dynamicDeployer = !StringUtils.isEmpty(config.getDeployer().getUrl());
boolean sidecarOrProvisioningService = isClassicSidecarEnabled() || isProvisioningServiceEnabled();
if (dynamicDeployer && sidecarOrProvisioningService) {
throw new IllegalArgumentException("Either Sidecar or Deployer URL can be specified");
}
return dynamicDeployer || sidecarOrProvisioningService;
}
// Classic MT sidecar:
public boolean isClassicSidecarEnabled() {
return dynamicModelUtils.isClassicSidecarEnabled();
}
// ProvisioningService:
public boolean isProvisioningServiceEnabled() {
return config.getMtxs().isEnabled() && !StringUtils.isEmpty(getProvisioningServiceUrl());
}
public String getProvisioningServiceUrl() {
return !StringUtils.isEmpty(config.getProvisioning().getUrl()) ? config.getProvisioning().getUrl() : config.getSidecar().getUrl();
}
// Bindings & InstanceLifecycleManagers:
public InstanceLifecycleManager createDefaultInstanceLifecycleManager() {
if (defaultBinding != null) {
return createInstanceLifecycleManager(defaultBinding,true);
} else if (isSqliteDataSourceEnabled()) {
return createInstanceLifecycleManagerSqlite();
}
return null;
}
public Map createInstanceLifecycleManagers() {
Map ilms = new HashMap<>();
for (ServiceBinding binding : bindings) {
ilms.put(binding.getName(), createInstanceLifecycleManager(binding,false));
}
if (isSqliteDataSourceEnabled()) {
ilms.put(SQLITE_BINDING_NAME, createInstanceLifecycleManagerSqlite());
}
return ilms;
}
private boolean isSqliteDataSourceEnabled() {
return bindings.isEmpty() && config.getMock().isEnabled() && isProvisioningServiceEnabled();
}
private boolean isServiceManagerBinding(ServiceBinding b) {
return b.matches(SERVICE_MANAGER, SERVICE_MANAGER);
}
private boolean isSchemaBasedMtBinding(ServiceBinding b) {
return b.matches(MT_ENABLED, null);
}
private InstanceLifecycleManager createInstanceLifecycleManagerSqlite() {
InstanceLifecycleManagerBuilder builder = InstanceLifecycleManagerBuilder.create();
String sqliteDirectory = config.getMock().getSqliteDirectory();
if (!StringUtils.isEmpty(sqliteDirectory)) {
builder.dbIdentifiers(new DbIdentifiersSqLite(Paths.get(sqliteDirectory)));
} else {
builder.dbIdentifiers(new DbIdentifiersSqLite(Paths.get(System.getProperty("user.dir"))));
}
try {
return builder.build();
} catch (InternalError internalError) {
throw new ErrorStatusException(CdsErrorStatuses.MT_LIB_SETUP_FAILED, internalError);
}
}
private InstanceLifecycleManager createInstanceLifecycleManager(ServiceBinding binding, boolean setSmRefreshInterval) {
InstanceLifecycleManagerBuilder builder = InstanceLifecycleManagerBuilder.create();
InstanceLifecycleManager newIlm;
if (isServiceManagerBinding(binding)) {
builder.serviceManagerClient(getServiceManagerClient(binding));
builder.dbIdentifiers(getHanaDatabaseIds());
builder.timeout(config.getServiceManager().getTimeout());
// The service manager cache inside the client lib is a static cache. Therefore, set refresh only
// for one ilm instance.
if (setSmRefreshInterval) {
builder.smCacheRefreshInterval(config.getServiceManager().getCacheRefreshInterval());
}
try {
newIlm = builder.build();
} catch (InternalError internalError) {
throw new ErrorStatusException(CdsErrorStatuses.INSTANCE_MANAGER_CLIENT_FAILED, binding.getName(), internalError);
}
} else {
try {
DbCredentials dbCredentials = DbCredentialsBuilder.create()
.credentials(binding.getCredentials())
.build();
builder.dbIdentifiers(new DbIdentifiersSql(Collections.singletonList(dbCredentials)));
newIlm = builder.build();
} catch (InternalError internalError) {
throw new ErrorStatusException(CdsErrorStatuses.MT_LIB_SETUP_FAILED, internalError.getMessage(), internalError);
}
}
return newIlm;
}
@VisibleForTesting
ServiceManagerClient getServiceManagerClient(ServiceBinding binding) {
try {
Map credentials = binding.getCredentials();
if (!StringUtils.isEmpty((String) credentials.get("clientsecret"))) {
return InstanceManagerClientFactory.getInstance((String) credentials.get("xsappname"), (String) credentials.get("sm_url"),
(String) credentials.get("url"), (String) credentials.get("clientid"), (String) credentials.get("clientsecret"),
HANA_OFFERING_NAME, HANA_HDI_PLAN_NAME);
} else if (!StringUtils.isEmpty((String) credentials.get("certificate"))) {
return InstanceManagerClientFactory.getInstance((String) credentials.get("xsappname"), (String) credentials.get("sm_url"),
(String) credentials.get("certurl"), (String) credentials.get("clientid"), (String) credentials.get("key"),
(String) credentials.get("certificate"), HANA_OFFERING_NAME, HANA_HDI_PLAN_NAME);
} else {
throw new ErrorStatusException(CdsErrorStatuses.INSTANCE_MANAGER_CLIENT_FAILED, binding.getName());
}
} catch (ImClientException e) {
throw new ErrorStatusException(CdsErrorStatuses.INSTANCE_MANAGER_CLIENT_FAILED, binding.getName(), e);
}
}
@VisibleForTesting
DbIdentifiers getHanaDatabaseIds() {
return new DbIdentifiersHana(new HashSet<>(config.getDataSource().getHanaDatabaseIds()));
}
@VisibleForTesting
ServiceBinding getDefaultBinding() {
return defaultBinding;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy