All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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.cfg.ApplicationProperties;
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(ApplicationProperties props) {
        return new SpannerClientFactoryBean(props) {
            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");
                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 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();
                        }
                    }
                }
            }
        };
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy