com.turbospaces.boot.test.MockSpannerDiModule Maven / Gradle / Ivy
package com.turbospaces.boot.test;
import java.util.Objects;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy;
import com.google.cloud.NoCredentials;
import com.google.cloud.spanner.DatabaseAdminClient;
import com.google.cloud.spanner.InstanceConfigId;
import com.google.cloud.spanner.InstanceId;
import com.google.cloud.spanner.InstanceInfo;
import com.google.cloud.spanner.SessionPoolOptions;
import com.google.cloud.spanner.Spanner;
import com.google.cloud.spanner.SpannerOptions;
import com.google.cloud.spanner.connection.SpannerPool;
import com.google.common.collect.ImmutableList;
import com.turbospaces.plugins.FlywaySpannerBootstrapInitializer;
import com.turbospaces.spanner.AbstractSpannerDiModule;
import com.turbospaces.spanner.SpannerClientFactoryBean;
import lombok.extern.slf4j.Slf4j;
@Configuration
@Slf4j
public class MockSpannerDiModule extends AbstractSpannerDiModule {
public static final int GRPC_PORT = 9010;
@Bean
public SpannerClientFactoryBean spannerClientFactoryBean() {
return new SpannerClientFactoryBean() {
private GenericContainer> container;
private DatabaseAdminClient admin;
@Override
protected Spanner createInstance() throws Exception {
//
// do not upgrade to latest until bug resolution available
// https://github.com/GoogleCloudPlatform/cloud-spanner-emulator/issues/98
//
container = new GenericContainer<>("gcr.io/cloud-spanner-emulator/emulator:1.5.2");
container.addExposedPorts(GRPC_PORT);
container.waitingFor(new LogMessageWaitStrategy().withRegEx(".*Cloud Spanner emulator running\\..*"));
container.start();
String projectId = "embedded";
SpannerOptions.Builder options = SpannerOptions.newBuilder();
options.setEmulatorHost(container.getHost() + ":" + container.getMappedPort(GRPC_PORT));
options.setCredentials(NoCredentials.getInstance());
options.setProjectId(projectId);
options.setSessionPoolOption(SessionPoolOptions.newBuilder().setMinSessions(1).build());
Spanner spanner = options.build().getService();
var props = bootstrap.props();
var instanceConfig = InstanceConfigId.of(projectId, "emulator-config");
var instanceId = InstanceId.of(projectId, props.SPANNER_INSTANCE_NAME.get());
var instanceInfo = InstanceInfo.newBuilder(instanceId).setNodeCount(1).setDisplayName("Uber").setInstanceConfigId(instanceConfig);
var instanceAdmin = spanner.getInstanceAdminClient();
instanceAdmin.createInstance(instanceInfo.build()).get();
admin = spanner.getDatabaseAdminClient();
var db = admin.createDatabase(props.SPANNER_INSTANCE_NAME.get(), props.SPANNER_DATABASE_NAME.get(), ImmutableList.of()).get();
log.info(db.getState().toString());
String jdbcUrl = String.format("jdbc:cloudspanner://%s:%d/projects/%s/instances/%s/databases/%s?autoConfigEmulator=true",
container.getHost(),
container.getMappedPort(GRPC_PORT),
projectId,
props.SPANNER_INSTANCE_NAME.get(),
props.SPANNER_DATABASE_NAME.get());
try {
FlywaySpannerBootstrapInitializer flyway = new FlywaySpannerBootstrapInitializer(props, jdbcUrl);
flyway.migrate();
} catch (Throwable err) {
ExceptionUtils.wrapAndThrow(err);
}
return spanner;
}
@Override
protected void destroyInstance(Spanner instance) throws Exception {
try {
super.destroyInstance(instance);
} finally {
try {
SpannerPool.closeSpannerPool(); // ~ crucial (cause shutdown hook hang)
} finally {
if (Objects.nonNull(container)) {
container.close();
}
}
}
}
};
}
}