com.sap.cloud.mt.subscription.InstanceLifecycleManagerSqLite Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of multi-tenant-subscription Show documentation
Show all versions of multi-tenant-subscription Show documentation
Spring Boot Enablement Parent
/*******************************************************************************
* © 2019-2024 SAP SE or an SAP affiliate company. All rights reserved.
******************************************************************************/
package com.sap.cloud.mt.subscription;
import com.google.common.annotations.VisibleForTesting;
import com.sap.cloud.mt.subscription.DbIdentifiers.DB;
import com.sap.cloud.mt.subscription.exceptions.InternalError;
import com.sap.cloud.mt.subscription.exceptions.UnknownTenant;
import java.net.URI;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* This implementation of {@link InstanceLifecycleManager} intended for multi tenancy based on SQLite database
* files. It should not be used in production.
*/
public class InstanceLifecycleManagerSqLite implements InstanceLifecycleManager {
// Open mode READWRITE will not create empty SQLite file
private static final String SQLITE_CONNECTION_OPTIONS = "open_mode=2";
private final SqLiteFileResolver sqLiteFileResolver;
public InstanceLifecycleManagerSqLite(Path root) {
this(new SqLiteFileResolver(root));
}
@VisibleForTesting
public InstanceLifecycleManagerSqLite(SqLiteFileResolver sqliteFileResolver) {
this.sqLiteFileResolver = sqliteFileResolver;
}
@Override
public void createNewInstance(String tenant, ProvisioningParameters provisioningParameters, BindingParameters bindingParameters) {
// MTX sidecar will create the database on subscribe or update
}
@Override
public void deleteInstance(String tenant) {
// MTX sidecar will delete the database on unsubscribe
}
@Override
public DataSourceInfo getDataSourceInfo(String tenant, boolean forceCacheUpdate) throws UnknownTenant {
Optional path = findPathForTenant(tenant);
if (path.isPresent()) {
return buildWithCredentials(newCredentials(tenant, path.get()));
} else {
throw new UnknownTenant(tenant);
}
}
@Override
public ContainerStatus getContainerStatus(String tenant) {
if (findPathForTenant(tenant).isPresent()) {
return ContainerStatus.OK;
} else {
return ContainerStatus.DOES_NOT_EXIST;
}
}
@Override
public boolean hasCredentials(String tenantId, boolean forceCacheUpdate) throws InternalError {
return getContainerStatus(tenantId).equals(ContainerStatus.OK);
}
@Override
public Map getAllTenantInfos(boolean forceCacheUpdate) {
return sqLiteFileResolver.get().keySet().stream().map(s -> {
TenantMetadata tenantInfo = new TenantMetadata(s);
tenantInfo.putAdditionalProperty(DATABASE_ID, s);
return tenantInfo;
}).filter(tenantInfo -> FilterTenants.realTenants().test(tenantInfo.getTenantId()))
.collect(Collectors.toMap(TenantMetadata::getTenantId, Function.identity()));
}
@Override
public void checkThatTenantExists(String tenant) throws UnknownTenant {
if (!findPathForTenant(tenant).isPresent()) {
throw new UnknownTenant(tenant);
}
}
@Override
public List createAndGetLibContainers(DataSourceInfo dataSourceInfo) {
return Collections.singletonList(dataSourceInfo);
}
@Override
public List getLibContainers() {
return new ArrayList<>();
}
@Override
public void insertDbIdentifiers(DbIdentifiers dbIdentifiers) {
// NOOP
}
@Override
public boolean hasDbIdentifiers() {
return true;
}
@Override
public DB getDbType() {
return DB.SQLITE;
}
private DbCredentials newCredentials(String tenant, Path file) {
try {
return new DbCredentialsSqlite(tenant, file);
} catch (InternalError e) {
throw new IllegalStateException("The DbCredentialsSqlite threw unexpected Internal Error", e);
}
}
private Optional findPathForTenant(String tenant) {
return Optional.ofNullable(sqLiteFileResolver.get().get(tenant));
}
private DataSourceInfo buildWithCredentials(DbCredentials credentials) {
return DataSourceInfoBuilder.createBuilder()
.driver(credentials.getDriver())
.url(credentials.getUrl())
.host(credentials.getHost())
.dbKey(credentials.getDatabaseId())
.tenantId(credentials.getDatabaseId())
.id(credentials.getDatabaseId())
.databaseId(credentials.getDatabaseId())
.build();
}
private static class DbCredentialsSqlite extends DbCredentials {
public static final String DRIVER = "org.sqlite.JDBC";
private final String tenant;
private final Path file;
private DbCredentialsSqlite(String tenant, Path file) throws InternalError {
super("sa",
"",
"localhost",
"0",
DRIVER,
"");
this.tenant = tenant;
this.file = file;
}
@Override
public String getDatabaseId() {
return this.tenant;
}
@Override
public DB getDB() {
return DB.SQLITE;
}
@Override
public DbCredentials createCopy() {
throw new UnsupportedOperationException("Not implemented");
}
@Override
protected String buildUrl() {
return "jdbc:sqlite:" + file + "?".concat(SQLITE_CONNECTION_OPTIONS);
}
@Override
protected List getHostsFromUri(URI uri) {
return Collections.emptyList();
}
@Override
protected UserAndPassword getUserFromUri(URI uri) {
return new UserAndPassword();
}
}
}