Add easy cache creation and documentation

This commit is contained in:
Reinhard Prechtl 2017-12-17 17:39:26 +01:00
parent 882ebaf6d8
commit e375c73813
2 changed files with 69 additions and 21 deletions

View file

@ -1,27 +1,44 @@
package de.rpr.testcontainers.infinispan; package de.rpr.testcontainers.infinispan;
import com.github.dockerjava.api.command.InspectContainerResponse; import com.github.dockerjava.api.command.InspectContainerResponse;
import org.apache.commons.lang.StringUtils;
import org.infinispan.client.hotrod.ProtocolVersion; import org.infinispan.client.hotrod.ProtocolVersion;
import org.infinispan.client.hotrod.RemoteCacheManager; import org.infinispan.client.hotrod.RemoteCacheManager;
import org.infinispan.client.hotrod.configuration.ConfigurationBuilder; import org.infinispan.client.hotrod.configuration.ConfigurationBuilder;
import org.junit.runner.Description; import org.junit.runner.Description;
import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.LogMessageWaitStrategy; import org.testcontainers.containers.wait.LogMessageWaitStrategy;
import org.testcontainers.shaded.io.netty.util.internal.StringUtil;
import java.time.Duration; import java.time.Duration;
import java.util.*; import java.util.*;
import static java.time.temporal.ChronoUnit.SECONDS; import static java.time.temporal.ChronoUnit.SECONDS;
/**
* An implementation of the {@link org.testcontainers.containers.GenericContainer} class that can be
* used to easily instantiate an Infinispan server for integration tests.
*
* @param <SELF>
*/
@SuppressWarnings("ALL") @SuppressWarnings("ALL")
public class InfinispanContainer<SELF extends InfinispanContainer<SELF>> extends GenericContainer<SELF> { public class InfinispanContainer<SELF extends InfinispanContainer<SELF>> extends GenericContainer<SELF> {
private static final String IMAGE_NAME = "jboss/infinispan-server"; private static final String IMAGE_NAME = "jboss/infinispan-server";
public static final String STANDALONE_MODE_CMD = "standalone"; public static final String STANDALONE_MODE_CMD = "standalone";
private static Set<ProtocolVersion> incompatibleProtocolVersions = new HashSet<>(); /*
* An enumeration of the endpoints provided by Infinispan, that this container provides access to.
*/
private enum InfinispanEndpoints {
HOTROD(11222);
private final int protocolPort;
private InfinispanEndpoints(final int port) {
this.protocolPort = port;
}
}
private static final Set<ProtocolVersion> incompatibleProtocolVersions = new HashSet<>();
static { static {
incompatibleProtocolVersions.add(ProtocolVersion.PROTOCOL_VERSION_10); incompatibleProtocolVersions.add(ProtocolVersion.PROTOCOL_VERSION_10);
@ -35,18 +52,26 @@ public class InfinispanContainer<SELF extends InfinispanContainer<SELF>> extends
private RemoteCacheManager cacheManager; private RemoteCacheManager cacheManager;
/**
* Construct an instance using the latest Infinispan image version.
*/
public InfinispanContainer() { public InfinispanContainer() {
this(IMAGE_NAME + ":latest"); this(IMAGE_NAME + ":latest");
} }
/**
* Construct n instance using the specifice image name.
*
* @param imageName The image name, must contain a version reference
*/
public InfinispanContainer(final String imageName) { public InfinispanContainer(final String imageName) {
super(imageName); super(imageName);
this.withCommand(STANDALONE_MODE_CMD); this.withCommand(STANDALONE_MODE_CMD);
withExposedPorts(Arrays.stream(InfinispanEndpoints.values()).map(endpoint -> endpoint.protocolPort).toArray(Integer[]::new));
this.waitStrategy = new LogMessageWaitStrategy() this.waitStrategy = new LogMessageWaitStrategy()
.withRegEx(".*Infinispan Server.*started in.*\\s") .withRegEx(".*Infinispan Server.*started in.*\\s")
.withTimes(2)
.withStartupTimeout(Duration.of(20, SECONDS)); .withStartupTimeout(Duration.of(20, SECONDS));
} }
@ -91,37 +116,51 @@ public class InfinispanContainer<SELF extends InfinispanContainer<SELF>> extends
} }
public InfinispanContainer withProtocolVersion(final ProtocolVersion protocolVersion) { public InfinispanContainer withProtocolVersion(final ProtocolVersion protocolVersion) {
if (incompatibleProtocolVersions.contains(protocolVersion)) {
throw new IllegalArgumentException("You have to use a Hotrod protocol version of 2.0 at least. 1.x can't create caches through the API.");
}
this.protocolVersion = protocolVersion; this.protocolVersion = protocolVersion;
return this; return this;
} }
public InfinispanContainer withCaches(final Collection<String> cacheNames) { /**
this.cacheNames = cacheNames; * Defines caches that should be created after the container has started.
return this; *
} * @param cacheNames An array of cache names
* @return The container itself
*/
public InfinispanContainer withCaches(final String... cacheNames) { public InfinispanContainer withCaches(final String... cacheNames) {
return withCaches(Arrays.asList(cacheNames)); return withCaches(Arrays.asList(cacheNames));
} }
/**
* Defines caches that should be created after the container has started.
*
* @param cacheNames A collection of cache names
* @return The container itself
*/
public InfinispanContainer withCaches(final Collection<String> cacheNames) {
if (incompatibleProtocolVersions.contains(protocolVersion)) {
throw new IllegalArgumentException(
"You have to use a Hotrod protocol version of 2.0 at least. 1.x can't create caches through the API. " +
"You can still map a configuration file into the container using '.withClasspathResourceMapping()'");
}
this.cacheNames = cacheNames;
return this;
}
@Override @Override
protected void containerIsStarted(final InspectContainerResponse containerInfo) { protected void containerIsStarted(final InspectContainerResponse containerInfo) {
cacheManager = new RemoteCacheManager(new ConfigurationBuilder() cacheManager = new RemoteCacheManager(new ConfigurationBuilder()
.addServers(getServerAddress()) .addServers(getHotrodEndpointConnectionString())
.version(getProtocolVersion()) .version(getProtocolVersion())
.build()); .build());
this.cacheNames.forEach(cacheName -> { this.cacheNames.forEach(cacheName -> cacheManager.administration().createCache(cacheName, null));
cacheManager.administration().createCache(cacheName, null);
});
} }
@Override @Override
protected void finished(final Description description) { protected void finished(final Description description) {
if (cacheManager != null) {
cacheManager.stop(); cacheManager.stop();
}
super.finished(description); super.finished(description);
} }
@ -129,10 +168,20 @@ public class InfinispanContainer<SELF extends InfinispanContainer<SELF>> extends
return protocolVersion != null ? protocolVersion : ProtocolVersion.PROTOCOL_VERSION_26; return protocolVersion != null ? protocolVersion : ProtocolVersion.PROTOCOL_VERSION_26;
} }
public String getServerAddress() { /**
return getContainerIpAddress() + ":" + getMappedPort(11222); * Retrieve the Hotrod endpoint address used to connect to the Infinispan instance inside the container.
*
* @return A String of the format [ipaddress]:[port]
*/
public String getHotrodEndpointConnectionString() {
return getContainerIpAddress() + ":" + getMappedPort(InfinispanEndpoints.HOTROD.protocolPort);
} }
/**
* Retrieve a preconfigured {@link org.infinispan.client.hotrod.RemoteCacheManager}.
*
* @return A cacheManager
*/
public RemoteCacheManager getCacheManager() { public RemoteCacheManager getCacheManager() {
return cacheManager; return cacheManager;
} }

View file

@ -8,8 +8,7 @@ import static org.junit.Assert.assertNotNull;
public class InfinispanContainerIntegrationTest { public class InfinispanContainerIntegrationTest {
@ClassRule @ClassRule
public static InfinispanContainer infinispan = public static InfinispanContainer infinispan = new InfinispanContainer()
new InfinispanContainer("9.1.3.Final")
.withProtocolVersion(ProtocolVersion.PROTOCOL_VERSION_26) .withProtocolVersion(ProtocolVersion.PROTOCOL_VERSION_26)
.withCaches("testCache"); .withCaches("testCache");