From e1cc43e1cad74e9c28f44182162acbe52de41c95 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Thu, 17 May 2018 15:17:42 +0200 Subject: [PATCH] #361 - Polishing. Move EmbeddedMongo to utils module. Inline MongosSystemForTestFactory to control process output. Add Javadoc. --- mongodb/pom.xml | 3 +- mongodb/transactions/pom.xml | 98 +++--- .../reactive/ReactiveTransitionService.java | 2 +- .../ReactiveTransitionServiceTests.java | 4 +- .../mongodb/sync/TransitionServiceTests.java | 8 +- .../src/test/resources/logback.xml | 2 +- mongodb/util/pom.xml | 28 ++ .../mongodb/util}/EmbeddedMongo.java | 118 +++++++- .../util/MongosSystemForTestFactory.java | 280 ++++++++++++++++++ 9 files changed, 472 insertions(+), 71 deletions(-) create mode 100644 mongodb/util/pom.xml rename mongodb/{transactions/src/test/java/utils => util/src/main/java/example/springdata/mongodb/util}/EmbeddedMongo.java (76%) create mode 100644 mongodb/util/src/main/java/example/springdata/mongodb/util/MongosSystemForTestFactory.java diff --git a/mongodb/pom.xml b/mongodb/pom.xml index 5fe2180c..f7788b91 100644 --- a/mongodb/pom.xml +++ b/mongodb/pom.xml @@ -28,6 +28,7 @@ security text-search transactions + util @@ -56,7 +57,7 @@ de.flapdoodle.embed de.flapdoodle.embed.mongo - runtime + provided diff --git a/mongodb/transactions/pom.xml b/mongodb/transactions/pom.xml index 1b7d6d19..c06f8297 100644 --- a/mongodb/transactions/pom.xml +++ b/mongodb/transactions/pom.xml @@ -1,72 +1,56 @@ - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - - org.springframework.data.examples - spring-data-mongodb-examples - 2.0.0.BUILD-SNAPSHOT - + + org.springframework.data.examples + spring-data-mongodb-examples + 2.0.0.BUILD-SNAPSHOT + - spring-data-mongodb-transactions - Spring Data MongoDB - Transactions + spring-data-mongodb-transactions + Spring Data MongoDB - Transactions - + + 3.8.0-beta2 + 1.9.0-beta1 + Lovelace-M3 + - - org.springframework.boot - spring-boot-starter-data-mongodb-reactive - - - org.mongodb - mongodb-driver - - - + - - org.springframework.data - spring-data-mongodb - 2.1.0.BUILD-SNAPSHOT - + - - org.springframework.data - spring-data-commons - 2.1.0.BUILD-SNAPSHOT - + + spring-data-next + + Lovelace-M3 + + - - org.mongodb - mongo-java-driver - 3.8.0-beta2 - + - - org.mongodb - mongodb-driver-async - 3.8.0-beta2 - + - - org.mongodb - mongodb-driver-reactivestreams - 1.9.0-beta1 - + + org.springframework.boot + spring-boot-starter-data-mongodb-reactive + - - io.projectreactor - reactor-core - 3.1.7.RELEASE - + + ${project.groupId} + spring-data-mongodb-example-utils + ${project.version} + test + - - io.projectreactor - reactor-test - 3.1.7.RELEASE - test - + + io.projectreactor + reactor-test + 3.1.7.RELEASE + test + - + diff --git a/mongodb/transactions/src/main/java/example/springdata/mongodb/reactive/ReactiveTransitionService.java b/mongodb/transactions/src/main/java/example/springdata/mongodb/reactive/ReactiveTransitionService.java index 4ff966bf..126a3406 100644 --- a/mongodb/transactions/src/main/java/example/springdata/mongodb/reactive/ReactiveTransitionService.java +++ b/mongodb/transactions/src/main/java/example/springdata/mongodb/reactive/ReactiveTransitionService.java @@ -53,7 +53,7 @@ public class ReactiveTransitionService { return lookup(id) // .flatMap(process -> start(action, process)) // - .flatMap(this::verify) // + .flatMap(it -> verify(it)) // .flatMap(process -> finish(action, process)); }).next().map(Process::getId); diff --git a/mongodb/transactions/src/test/java/example/springdata/mongodb/reactive/ReactiveTransitionServiceTests.java b/mongodb/transactions/src/test/java/example/springdata/mongodb/reactive/ReactiveTransitionServiceTests.java index 26c14c10..c75eacc6 100644 --- a/mongodb/transactions/src/test/java/example/springdata/mongodb/reactive/ReactiveTransitionServiceTests.java +++ b/mongodb/transactions/src/test/java/example/springdata/mongodb/reactive/ReactiveTransitionServiceTests.java @@ -19,9 +19,9 @@ import static org.assertj.core.api.Assertions.*; import example.springdata.mongodb.Process; import example.springdata.mongodb.State; +import example.springdata.mongodb.util.EmbeddedMongo; import reactor.core.publisher.Flux; import reactor.test.StepVerifier; -import utils.EmbeddedMongo; import org.bson.Document; import org.junit.ClassRule; @@ -40,6 +40,8 @@ import com.mongodb.reactivestreams.client.MongoClient; import com.mongodb.reactivestreams.client.MongoClients; /** + * Test showing MongoDB Transaction usage through a reactive API. + * * @author Christoph Strobl * @currentRead The Core - Peter V. Brett */ diff --git a/mongodb/transactions/src/test/java/example/springdata/mongodb/sync/TransitionServiceTests.java b/mongodb/transactions/src/test/java/example/springdata/mongodb/sync/TransitionServiceTests.java index 89efbc60..61f8fd94 100644 --- a/mongodb/transactions/src/test/java/example/springdata/mongodb/sync/TransitionServiceTests.java +++ b/mongodb/transactions/src/test/java/example/springdata/mongodb/sync/TransitionServiceTests.java @@ -17,7 +17,7 @@ package example.springdata.mongodb.sync; import example.springdata.mongodb.Process; import example.springdata.mongodb.State; -import utils.EmbeddedMongo; +import example.springdata.mongodb.util.EmbeddedMongo; import java.util.function.Consumer; @@ -36,6 +36,7 @@ import org.springframework.data.mongodb.config.AbstractMongoConfiguration; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; @@ -44,10 +45,13 @@ import com.mongodb.client.model.Filters; import com.mongodb.client.model.Projections; /** + * Test showing MongoDB Transaction usage through a synchronous (imperative) API using Spring's managed transactions. + * * @author Christoph Strobl * @currentRead The Core - Peter V. Brett + * @see org.springframework.transaction.annotation.Transactional */ -@RunWith(SpringJUnit4ClassRunner.class) +@RunWith(SpringRunner.class) @ContextConfiguration public class TransitionServiceTests { diff --git a/mongodb/transactions/src/test/resources/logback.xml b/mongodb/transactions/src/test/resources/logback.xml index 7869183a..910b1b43 100644 --- a/mongodb/transactions/src/test/resources/logback.xml +++ b/mongodb/transactions/src/test/resources/logback.xml @@ -7,7 +7,7 @@ - + diff --git a/mongodb/util/pom.xml b/mongodb/util/pom.xml new file mode 100644 index 00000000..8d47af8a --- /dev/null +++ b/mongodb/util/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + + org.springframework.data.examples + spring-data-mongodb-examples + 2.0.0.BUILD-SNAPSHOT + + + spring-data-mongodb-example-utils + Spring Data MongoDB - Example Utilities + + + + + junit + junit + + + + org.mongodb + mongo-java-driver + + + + + diff --git a/mongodb/transactions/src/test/java/utils/EmbeddedMongo.java b/mongodb/util/src/main/java/example/springdata/mongodb/util/EmbeddedMongo.java similarity index 76% rename from mongodb/transactions/src/test/java/utils/EmbeddedMongo.java rename to mongodb/util/src/main/java/example/springdata/mongodb/util/EmbeddedMongo.java index 26e09da1..cef508a2 100644 --- a/mongodb/transactions/src/test/java/utils/EmbeddedMongo.java +++ b/mongodb/util/src/main/java/example/springdata/mongodb/util/EmbeddedMongo.java @@ -13,8 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package utils; +package example.springdata.mongodb.util; +import de.flapdoodle.embed.mongo.Command; import de.flapdoodle.embed.mongo.config.IMongoCmdOptions; import de.flapdoodle.embed.mongo.config.IMongodConfig; import de.flapdoodle.embed.mongo.config.IMongosConfig; @@ -26,8 +27,9 @@ import de.flapdoodle.embed.mongo.config.Storage; import de.flapdoodle.embed.mongo.distribution.Feature; import de.flapdoodle.embed.mongo.distribution.IFeatureAwareVersion; import de.flapdoodle.embed.mongo.distribution.Versions; -import de.flapdoodle.embed.mongo.tests.MongosSystemForTestFactory; +import de.flapdoodle.embed.process.config.io.ProcessOutput; import de.flapdoodle.embed.process.distribution.GenericVersion; +import de.flapdoodle.embed.process.io.Processors; import de.flapdoodle.embed.process.runtime.Network; import java.io.IOException; @@ -37,6 +39,7 @@ import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; import org.junit.rules.ExternalResource; import org.slf4j.Logger; @@ -48,7 +51,10 @@ import com.mongodb.MongoClient; import com.mongodb.MongoClientURI; /** + * {@link org.junit.rules.TestRule} for a MongoDB server resource that is started/stopped along the test lifecycle. + * * @author Christoph Strobl + * @author Mark Paluch */ public class EmbeddedMongo extends ExternalResource { @@ -70,10 +76,20 @@ public class EmbeddedMongo extends ExternalResource { this.resource = resource; } + /** + * Create a new {@link Builder} to build {@link EmbeddedMongo}. + * + * @return + */ public static Builder builder() { return new Builder(); } + /** + * Create a new {@link Builder} that is initialized as replica set to build {@link EmbeddedMongo}. + * + * @return + */ public static Builder replSet() { return replSet(DEFAULT_REPLICA_SET_NAME); } @@ -82,12 +98,16 @@ public class EmbeddedMongo extends ExternalResource { return new Builder().withReplicaSetName(replicaSetName); } + /** + * {@link Builder} for {@link EmbeddedMongo}. + */ public static class Builder { IFeatureAwareVersion version; String replicaSetName; List serverPorts; List configServerPorts; + boolean silent = true; Builder() { @@ -97,30 +117,62 @@ public class EmbeddedMongo extends ExternalResource { configServerPorts = Collections.emptyList(); } + /** + * Configure the MongoDB {@link IFeatureAwareVersion version}. + * + * @param version + * @return + */ public Builder withVersion(IFeatureAwareVersion version) { this.version = version; return this; } + /** + * Configure the replica set name. + * + * @param version + * @return + */ public Builder withReplicaSetName(String replicaSetName) { this.replicaSetName = replicaSetName; return this; } + /** + * Configure the server ports. + * + * @param version + * @return + */ public Builder withServerPorts(Integer... ports) { this.serverPorts = Arrays.asList(ports); return this; } + /** + * Configure whether to stay silent (stream only Mongo process errors to stdout) or to stream all process output to + * stdout. By default, only process errors are forwarded to stdout. + * + * @param silent + * @return + */ + public Builder withSilent(boolean silent) { + + this.silent = silent; + return this; + } + public EmbeddedMongo configure() { if (serverPorts.size() > 1 || StringUtils.hasText(replicaSetName)) { String rsName = StringUtils.hasText(replicaSetName) ? replicaSetName : DEFAULT_REPLICA_SET_NAME; - return new EmbeddedMongo(new ReplSet(version, rsName, serverPorts.toArray(new Integer[serverPorts.size()]))); + return new EmbeddedMongo( + new ReplSet(version, rsName, silent, serverPorts.toArray(new Integer[serverPorts.size()]))); } throw new UnsupportedOperationException("implement me"); @@ -155,12 +207,24 @@ public class EmbeddedMongo extends ExternalResource { } } + /** + * Interface specifying a test resource which exposes lifecycle methods and connection coordinates. + */ interface TestResource { + /** + * Start the resource. + */ void start(); + /** + * Stop the resource. + */ void stop(); + /** + * @return the connection string to configure a MongoDB client. + */ String connectionString(); default MongoClient mongoClient() { @@ -179,10 +243,11 @@ public class EmbeddedMongo extends ExternalResource { private final int mongosPort; private final Integer[] serverPorts; private final Integer[] configServerPorts; + private final Function outputFunction; private MongosSystemForTestFactory mongosTestFactory; - ReplSet(IFeatureAwareVersion serverVersion, String replicaSetName, Integer... serverPorts) { + ReplSet(IFeatureAwareVersion serverVersion, String replicaSetName, boolean silent, Integer... serverPorts) { this.serverVersion = serverVersion; this.replicaSetName = replicaSetName; @@ -190,6 +255,13 @@ public class EmbeddedMongo extends ExternalResource { this.configServerPorts = defaultPortsIfRequired(null); this.configServerReplicaSetName = DEFAULT_CONFIG_SERVER_REPLICA_SET_NAME; this.mongosPort = randomOrDefaultServerPort(); + + if (silent) { + outputFunction = it -> new ProcessOutput(Processors.silent(), + Processors.namedConsole("[ " + it.commandName() + " error]"), Processors.console()); + } else { + outputFunction = it -> ProcessOutput.getDefaultInstance(it.commandName()); + } } Integer[] defaultPortsIfRequired(Integer[] ports) { @@ -226,7 +298,7 @@ public class EmbeddedMongo extends ExternalResource { configServerReplicaSetName, configServerPorts[0]); mongosTestFactory = new MongosSystemForTestFactory(mongosConfig, replicaSets, Collections.emptyList(), - DEFAULT_SHARDING, DEFAULT_SHARDING, DEFAULT_SHARD_KEY); + DEFAULT_SHARDING, DEFAULT_SHARDING, DEFAULT_SHARD_KEY, outputFunction); try { LOGGER.info(String.format("Starting config servers at ports %s", @@ -244,15 +316,17 @@ public class EmbeddedMongo extends ExternalResource { } private List initReplicaSet() { - List replicaSet1 = new ArrayList<>(); + + List rs = new ArrayList<>(); for (int port : serverPorts) { - replicaSet1.add(defaultMongodConfig(serverVersion, port, defaultCommandOptions(), false, true, replicaSetName)); + rs.add(defaultMongodConfig(serverVersion, port, defaultCommandOptions(), false, true, replicaSetName)); } - return replicaSet1; + return rs; } private List initConfigServers() { + List configServers = new ArrayList<>(configServerPorts.length); for (Integer port : configServerPorts) { @@ -280,6 +354,9 @@ public class EmbeddedMongo extends ExternalResource { } } + /** + * @return Default {@link IMongoCmdOptions command options}. + */ private static IMongoCmdOptions defaultCommandOptions() { return new MongoCmdOptionsBuilder() // @@ -291,12 +368,25 @@ public class EmbeddedMongo extends ExternalResource { .build(); } + /** + * Create a default {@code mongod} config. + * + * @param version + * @param port + * @param cmdOptions + * @param configServer + * @param shardServer + * @param replicaSet + * @return + */ private static IMongodConfig defaultMongodConfig(IFeatureAwareVersion version, int port, IMongoCmdOptions cmdOptions, boolean configServer, boolean shardServer, String replicaSet) { try { + MongodConfigBuilder builder = new MongodConfigBuilder() // .version(version) // + .withLaunchArgument("--quiet") // .net(new Net(LOCALHOST, port, Network.localhostIsIPv6())) // .configServer(configServer).cmdOptions(cmdOptions); // @@ -318,12 +408,24 @@ public class EmbeddedMongo extends ExternalResource { } } + /** + * Create a default {@code mongos} config. + * + * @param version + * @param port + * @param cmdOptions + * @param configServerReplicaSet + * @param configServerPort + * @return + */ private static IMongosConfig defaultMongosConfig(IFeatureAwareVersion version, int port, IMongoCmdOptions cmdOptions, String configServerReplicaSet, int configServerPort) { try { + MongosConfigBuilder builder = new MongosConfigBuilder() // .version(version) // + .withLaunchArgument("--quiet", null) // .net(new Net(LOCALHOST, port, Network.localhostIsIPv6())) // .cmdOptions(cmdOptions); diff --git a/mongodb/util/src/main/java/example/springdata/mongodb/util/MongosSystemForTestFactory.java b/mongodb/util/src/main/java/example/springdata/mongodb/util/MongosSystemForTestFactory.java new file mode 100644 index 00000000..0dc39091 --- /dev/null +++ b/mongodb/util/src/main/java/example/springdata/mongodb/util/MongosSystemForTestFactory.java @@ -0,0 +1,280 @@ +/* + * Copyright 2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package example.springdata.mongodb.util; + +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.Map.Entry; + +import com.mongodb.*; +import de.flapdoodle.embed.process.config.IRuntimeConfig; +import de.flapdoodle.embed.process.config.io.ProcessOutput; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import de.flapdoodle.embed.mongo.Command; +import de.flapdoodle.embed.mongo.MongodExecutable; +import de.flapdoodle.embed.mongo.MongodProcess; +import de.flapdoodle.embed.mongo.MongodStarter; +import de.flapdoodle.embed.mongo.MongosExecutable; +import de.flapdoodle.embed.mongo.MongosProcess; +import de.flapdoodle.embed.mongo.MongosStarter; +import de.flapdoodle.embed.mongo.config.IMongodConfig; +import de.flapdoodle.embed.mongo.config.IMongosConfig; +import de.flapdoodle.embed.mongo.config.RuntimeConfigBuilder; + +class MongosSystemForTestFactory { + + private final static Logger logger = LoggerFactory + .getLogger(MongosSystemForTestFactory.class); + + public static final String ADMIN_DATABASE_NAME = "admin"; + public static final String LOCAL_DATABASE_NAME = "local"; + public static final String REPLICA_SET_NAME = "rep1"; + public static final String OPLOG_COLLECTION = "oplog.rs"; + + private final IMongosConfig config; + private final Map> replicaSets; + private final List configServers; + private final String shardDatabase; + private final String shardCollection; + private final String shardKey; + private final Function outputFunction; + + private MongosExecutable mongosExecutable; + private MongosProcess mongosProcess; + private List mongodProcessList; + private List mongodConfigProcessList; + + public MongosSystemForTestFactory(IMongosConfig config, + Map> replicaSets, + List configServers, String shardDatabase, + String shardCollection, String shardKey, Function outputFunction) { + this.config = config; + this.replicaSets = replicaSets; + this.configServers = configServers; + this.shardDatabase = shardDatabase; + this.shardCollection = shardCollection; + this.shardKey = shardKey; + this.outputFunction = outputFunction; + } + + public void start() throws Throwable { + this.mongodProcessList = new ArrayList<>(); + this.mongodConfigProcessList = new ArrayList<>(); + for (Entry> entry : replicaSets.entrySet()) { + initializeReplicaSet(entry); + } + for (IMongodConfig config : configServers) { + initializeConfigServer(config); + } + initializeMongos(); + configureMongos(); + } + + private void initializeReplicaSet(Entry> entry) + throws Exception { + String replicaName = entry.getKey(); + List mongoConfigList = entry.getValue(); + + if (mongoConfigList.size() < 3) { + throw new Exception( + "A replica set must contain at least 3 members."); + } + // Create 3 mongod processes + for (IMongodConfig mongoConfig : mongoConfigList) { + if (!mongoConfig.replication().getReplSetName().equals(replicaName)) { + throw new Exception( + "Replica set name must match in mongo configuration"); + } + IRuntimeConfig runtimeConfig = new RuntimeConfigBuilder() + .defaultsWithLogger(Command.MongoD,logger) + .processOutput(outputFunction.apply(Command.MongoD)) + .build(); + MongodStarter starter = MongodStarter.getInstance(runtimeConfig); + MongodExecutable mongodExe = starter.prepare(mongoConfig); + MongodProcess process = mongodExe.start(); + mongodProcessList.add(process); + } + Thread.sleep(1000); + MongoClientOptions mo = MongoClientOptions.builder() + .connectTimeout(10) + .build(); + MongoClient mongo = new MongoClient(new ServerAddress(mongoConfigList.get(0).net() + .getServerAddress().getHostName(), mongoConfigList.get(0).net() + .getPort()), mo); + DB mongoAdminDB = mongo.getDB(ADMIN_DATABASE_NAME); + + CommandResult cr = mongoAdminDB + .command(new BasicDBObject("isMaster", 1)); + logger.info("isMaster: {}", cr); + + // Build BSON object replica set settings + DBObject replicaSetSetting = new BasicDBObject(); + replicaSetSetting.put("_id", replicaName); + BasicDBList members = new BasicDBList(); + int i = 0; + for (IMongodConfig mongoConfig : mongoConfigList) { + DBObject host = new BasicDBObject(); + host.put("_id", i++); + host.put("host", mongoConfig.net().getServerAddress().getHostName() + + ":" + mongoConfig.net().getPort()); + members.add(host); + } + + replicaSetSetting.put("members", members); + logger.info(replicaSetSetting.toString()); + // Initialize replica set + cr = mongoAdminDB.command(new BasicDBObject("replSetInitiate", + replicaSetSetting)); + logger.info("replSetInitiate: {}", cr); + + Thread.sleep(5000); + cr = mongoAdminDB.command(new BasicDBObject("replSetGetStatus", 1)); + logger.info("replSetGetStatus: {}", cr); + + // Check replica set status before to proceed + while (!isReplicaSetStarted(cr)) { + logger.info("Waiting for 3 seconds..."); + Thread.sleep(1000); + cr = mongoAdminDB.command(new BasicDBObject("replSetGetStatus", 1)); + logger.info("replSetGetStatus: {}", cr); + } + + mongo.close(); + mongo = null; + } + + private boolean isReplicaSetStarted(BasicDBObject setting) { + if (setting.get("members") == null) { + return false; + } + + BasicDBList members = (BasicDBList) setting.get("members"); + for (Object m : members.toArray()) { + BasicDBObject member = (BasicDBObject) m; + logger.info(member.toString()); + int state = member.getInt("state"); + logger.info("state: {}", state); + // 1 - PRIMARY, 2 - SECONDARY, 7 - ARBITER + if (state != 1 && state != 2 && state != 7) { + return false; + } + } + return true; + } + + private void initializeConfigServer(IMongodConfig config) throws Exception { + if (!config.isConfigServer()) { + throw new Exception( + "Mongo configuration is not a defined for a config server."); + } + MongodStarter starter = MongodStarter.getDefaultInstance(); + MongodExecutable mongodExe = starter.prepare(config); + MongodProcess process = mongodExe.start(); + mongodProcessList.add(process); + } + + private void initializeMongos() throws Exception { + MongosStarter runtime = MongosStarter.getInstance(new RuntimeConfigBuilder() + .defaultsWithLogger(Command.MongoS,logger) + .processOutput(outputFunction.apply(Command.MongoS)) + .build()); + + mongosExecutable = runtime.prepare(config); + mongosProcess = mongosExecutable.start(); + } + + private void configureMongos() throws Exception { + CommandResult cr; + MongoClientOptions options = MongoClientOptions.builder() + .connectTimeout(10) + .build(); + try (MongoClient mongo = new MongoClient( + new ServerAddress(this.config.net().getServerAddress() + .getHostName(), this.config.net().getPort()), options)) { + DB mongoAdminDB = mongo.getDB(ADMIN_DATABASE_NAME); + + // Add shard from the replica set list + for (Entry> entry : this.replicaSets + .entrySet()) { + String replicaName = entry.getKey(); + String command = ""; + for (IMongodConfig mongodConfig : entry.getValue()) { + if (command.isEmpty()) { + command = replicaName + "/"; + } else { + command += ","; + } + command += mongodConfig.net().getServerAddress().getHostName() + + ":" + mongodConfig.net().getPort(); + } + logger.info("Execute add shard command: {}", command); + cr = mongoAdminDB.command(new BasicDBObject("addShard", command)); + logger.info(cr.toString()); + } + + logger.info("Execute list shards."); + cr = mongoAdminDB.command(new BasicDBObject("listShards", 1)); + logger.info(cr.toString()); + + // Enabled sharding at database level + logger.info("Enabled sharding at database level"); + cr = mongoAdminDB.command(new BasicDBObject("enableSharding", + this.shardDatabase)); + logger.info(cr.toString()); + + // Create index in sharded collection + logger.info("Create index in sharded collection"); + DB db = mongo.getDB(this.shardDatabase); + db.getCollection(this.shardCollection).createIndex(this.shardKey); + + // Shard the collection + logger.info("Shard the collection: {}.{}", this.shardDatabase, this.shardCollection); + DBObject cmd = new BasicDBObject(); + cmd.put("shardCollection", this.shardDatabase + "." + this.shardCollection); + cmd.put("key", new BasicDBObject(this.shardKey, 1)); + cr = mongoAdminDB.command(cmd); + logger.info(cr.toString()); + + logger.info("Get info from config/shards"); + DBCursor cursor = mongo.getDB("config").getCollection("shards").find(); + while (cursor.hasNext()) { + DBObject item = cursor.next(); + logger.info(item.toString()); + } + } + + } + + public Mongo getMongo() throws UnknownHostException, MongoException { + return new MongoClient(new ServerAddress(mongosProcess.getConfig().net() + .getServerAddress(), mongosProcess.getConfig().net().getPort())); + } + + public void stop() { + for (MongodProcess process : this.mongodProcessList) { + process.stop(); + } + for (MongodProcess process : this.mongodConfigProcessList) { + process.stop(); + } + this.mongosProcess.stop(); + } +}