http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBTestHelper.java ---------------------------------------------------------------------- diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBTestHelper.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBTestHelper.java new file mode 100644 index 0000000..9b890fa --- /dev/null +++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/MongoDBTestHelper.java @@ -0,0 +1,126 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.entity.nosql.mongodb; + +import java.net.UnknownHostException; +import java.util.List; +import java.util.Map; + +import org.apache.brooklyn.entity.nosql.mongodb.AbstractMongoDBServer; +import org.apache.brooklyn.entity.nosql.mongodb.MongoDBServer; +import org.bson.types.ObjectId; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Throwables; +import com.google.common.net.HostAndPort; +import com.mongodb.BasicDBObject; +import com.mongodb.CommandResult; +import com.mongodb.DB; +import com.mongodb.DBCollection; +import com.mongodb.DBObject; +import com.mongodb.MongoClient; +import com.mongodb.ReadPreference; + +import brooklyn.location.access.BrooklynAccessUtils; + +public class MongoDBTestHelper { + + private static final Logger LOG = LoggerFactory.getLogger(MongoDBTestHelper.class); + + private static final String TEST_DB = "brooklyn_test"; + private static final String TEST_COLLECTION = "test_collection"; + private static final String ADMIN_DB = "admin"; + + /** + * Inserts a new object with { key: value } at given server. + * @return The new document's id + */ + public static String insert(AbstractMongoDBServer entity, String key, Object value) { + LOG.info("Inserting {}:{} at {}", new Object[]{key, value, entity}); + MongoClient mongoClient = clientForServer(entity); + try { + DB db = mongoClient.getDB(TEST_DB); + DBCollection testCollection = db.getCollection(TEST_COLLECTION); + BasicDBObject doc = new BasicDBObject(key, value); + testCollection.insert(doc); + ObjectId id = (ObjectId) doc.get("_id"); + return id.toString(); + } finally { + mongoClient.close(); + } + } + + /** @return The {@link DBObject} representing the object with the given id */ + public static DBObject getById(AbstractMongoDBServer entity, String id) { + LOG.info("Getting {} from {}", new Object[]{id, entity}); + MongoClient mongoClient = clientForServer(entity); + // Secondary preferred means the driver will let us read from secondaries too. + mongoClient.setReadPreference(ReadPreference.secondaryPreferred()); + try { + DB db = mongoClient.getDB(TEST_DB); + DBCollection testCollection = db.getCollection(TEST_COLLECTION); + return testCollection.findOne(new BasicDBObject("_id", new ObjectId(id))); + } finally { + mongoClient.close(); + } + } + + public static List<String> getDatabaseNames(AbstractMongoDBServer entity) { + LOG.info("Getting database names from {}", entity); + MongoClient mongoClient = clientForServer(entity); + try { + return mongoClient.getDatabaseNames(); + } finally { + mongoClient.close(); + } + } + + public static boolean isConfigServer(AbstractMongoDBServer entity) { + LOG.info("Checking if {} is a config server", entity); + MongoClient mongoClient = clientForServer(entity); + try { + DB db = mongoClient.getDB(ADMIN_DB); + CommandResult commandResult = db.command("getCmdLineOpts"); + Map<?, ?> parsedArgs = (Map<?, ?>)commandResult.get("parsed"); + if (parsedArgs == null) return false; + Boolean configServer = (Boolean)parsedArgs.get("configsvr"); + if (configServer != null) { + // v2.5 format + return Boolean.TRUE.equals(configServer); + } else { + // v2.6 format + String role = (String) ((Map)parsedArgs.get("sharding")).get("clusterRole"); + return "configsvr".equals(role); + } + } finally { + mongoClient.close(); + } + } + + private static MongoClient clientForServer(AbstractMongoDBServer server) { + try { + HostAndPort hap = BrooklynAccessUtils.getBrooklynAccessibleAddress(server, server.getAttribute(MongoDBServer.PORT)); + return new MongoClient(hap.getHostText(), hap.getPort()); + } catch (UnknownHostException e) { + // Fail whatever test called this method. + throw Throwables.propagate(e); + } + } +}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/ReplicaSetConfigTest.java ---------------------------------------------------------------------- diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/ReplicaSetConfigTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/ReplicaSetConfigTest.java new file mode 100644 index 0000000..dc5cb5c --- /dev/null +++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/ReplicaSetConfigTest.java @@ -0,0 +1,240 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.entity.nosql.mongodb; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotEquals; +import static org.testng.Assert.assertTrue; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import javax.annotation.Nullable; + +import org.apache.brooklyn.entity.nosql.mongodb.ReplicaSetConfig; +import org.bson.BSONObject; +import org.bson.BasicBSONObject; +import org.bson.types.BasicBSONList; +import org.testng.annotations.Test; + +import com.google.common.base.Function; +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Lists; +import com.google.common.net.HostAndPort; + +public class ReplicaSetConfigTest { + + // true if object has key "votes" that is > 1 + static Predicate<BasicBSONObject> IS_VOTING_MEMBER = new Predicate<BasicBSONObject>() { + @Override public boolean apply(@Nullable BasicBSONObject input) { + return input != null && input.containsField("votes") && input.getInt("votes") > 0; + } + }; + + private BasicBSONObject makeSetMember(Integer id, String host) { + return new BasicBSONObject(ImmutableMap.of("_id", id, "host", host)); + } + + private BasicBSONObject makeSetConfig(String id, Integer version, BasicBSONObject... members) { + BasicBSONList memberList = new BasicBSONList(); + memberList.addAll(Arrays.asList(members)); + return new BasicBSONObject(ImmutableMap.of("_id", id, "version", version, "members", memberList)); + } + + private BasicBSONObject makeSetWithNMembers(int n) { + ReplicaSetConfig setConfig = ReplicaSetConfig.builder("replica-set-name"); + for (int i = 0; i < n; i++) { + setConfig.member("host-"+i, i, i); + } + return setConfig.build(); + } + + private Collection<HostAndPort> votingMembersOfSet(BasicBSONObject config) { + BasicBSONList membersObject = BasicBSONList.class.cast(config.get("members")); + List<BasicBSONObject> members = Lists.newArrayList(); + for (Object object : membersObject) members.add(BasicBSONObject.class.cast(object)); + return FluentIterable.from(members) + .filter(IS_VOTING_MEMBER) + .transform(new Function<BasicBSONObject, HostAndPort>() { + @Override public HostAndPort apply(BasicBSONObject input) { + return HostAndPort.fromString(input.getString("host")); + } + }) + .toList(); + } + + private Collection<HostAndPort> nonVotingMembersOfSet(BasicBSONObject config) { + BasicBSONList membersObject = BasicBSONList.class.cast(config.get("members")); + List<BasicBSONObject> members = Lists.newArrayList(); + for (Object object : membersObject) members.add(BasicBSONObject.class.cast(object)); + return FluentIterable + .from(members) + .filter(Predicates.not(IS_VOTING_MEMBER)) + .transform(new Function<BasicBSONObject, HostAndPort>() { + @Override public HostAndPort apply(BasicBSONObject input) { + return HostAndPort.fromString(input.getString("host")); + } + }) + .toList(); + } + + @Test + public void testCreateFromScratch() { + BasicBSONObject config = ReplicaSetConfig.builder("rs") + .member("host-a", 12345, 1) + .member("host-b", 54321, 2) + .build(); + assertEquals(config.get("_id"), "rs"); + assertEquals(config.getInt("version"), 1); + assertTrue(config.get("members") instanceof BasicBSONList); + BasicBSONList members = (BasicBSONList) config.get("members"); + assertEquals(members.size(), 2); + } + + @Test + public void testCreateFromExistingConfig() { + // Replica set of one member + int version = 44; + BasicBSONObject config = makeSetConfig("replica-set-name", version, makeSetMember(33, "example.com:7777")); + + // Use existing set to add two more members + BasicBSONObject newConfig = ReplicaSetConfig.fromExistingConfig(config) + .member("foo", 8888, 34) + .member("bar", 9999, 35) + .build(); + + assertEquals(newConfig.get("_id"), "replica-set-name"); + assertEquals(newConfig.get("version"), version + 1); + BasicBSONList members = (BasicBSONList) newConfig.get("members"); + assertEquals(members.size(), 3); + + BSONObject original = (BSONObject) members.get(0); + assertEquals(original.get("_id"), 33); + assertEquals(original.get("host"), "example.com:7777"); + + BSONObject second = (BSONObject) members.get(1); + assertEquals(second.get("_id"), 34); + assertEquals(second.get("host"), "foo:8888"); + + BSONObject third = (BSONObject) members.get(2); + assertEquals(third.get("_id"), 35); + assertEquals(third.get("host"), "bar:9999"); + } + + @Test + public void testRemoveMember() { + int version = 44; + BasicBSONObject config = makeSetConfig("replica-set-name", version, + makeSetMember(33, "example.com:7777"), + makeSetMember(34, "example.com:7778")); + + // Use existing set to add two more members + BasicBSONObject newConfig = ReplicaSetConfig.fromExistingConfig(config) + .remove("example.com", 7777) + .build(); + + assertEquals(newConfig.get("version"), version + 1); + BasicBSONList members = (BasicBSONList) newConfig.get("members"); + assertEquals(members.size(), 1); + assertEquals(BSONObject.class.cast(members.get(0)).get("host"), "example.com:7778"); + + newConfig = ReplicaSetConfig.fromExistingConfig(newConfig) + .remove("example.com", 7778) + .build(); + + members = (BasicBSONList) newConfig.get("members"); + assertTrue(members.isEmpty()); + } + + @Test + public void testRemoveNonExistentMemberHasNoEffect() { + BasicBSONObject config = makeSetConfig("replica-set-name", 1, + makeSetMember(33, "example.com:7777"), + makeSetMember(34, "example.com:7778")); + + BasicBSONList members = (BasicBSONList) config.get("members"); + assertEquals(members.size(), 2); + + BasicBSONObject altered = ReplicaSetConfig.fromExistingConfig(config) + .remove("foo", 99) + .build(); + + members = (BasicBSONList) altered.get("members"); + assertEquals(members.size(), 2); + } + + @Test + public void testSetOfFourMembersHasThreeVoters() { + BasicBSONObject config = makeSetWithNMembers(4); + assertEquals(votingMembersOfSet(config).size(), 3, "Expected three voters in set with four members"); + assertEquals(nonVotingMembersOfSet(config).size(), 1, "Expected one non-voter in set with four members"); + } + + @Test + public void testFourthServerOfFourIsGivenVoteWhenAnotherServerIsRemoved() { + BasicBSONObject config = makeSetWithNMembers(4); + HostAndPort toRemove = votingMembersOfSet(config).iterator().next(); + + BasicBSONObject updated = ReplicaSetConfig.fromExistingConfig(config) + .remove(toRemove) + .build(); + + assertEquals(votingMembersOfSet(updated).size(), 3); + assertTrue(nonVotingMembersOfSet(updated).isEmpty()); + + BasicBSONList newMembers = BasicBSONList.class.cast(updated.get("members")); + for (Object object : newMembers) { + BasicBSONObject member = BasicBSONObject.class.cast(object); + HostAndPort memberHostAndPort = HostAndPort.fromString(member.getString("host")); + assertNotEquals(memberHostAndPort, toRemove); + } + } + + @Test + public void testMaximumNumberOfVotersIsLimited() { + BasicBSONObject config = makeSetWithNMembers(ReplicaSetConfig.MAXIMUM_REPLICA_SET_SIZE); + int voters = ReplicaSetConfig.MAXIMUM_VOTING_MEMBERS; + int nonVoters = ReplicaSetConfig.MAXIMUM_REPLICA_SET_SIZE - voters; + assertEquals(votingMembersOfSet(config).size(), voters, "Expected number of voters in max-size set to be " + voters); + assertEquals(nonVotingMembersOfSet(config).size(), nonVoters, "Expected number of non-voters in max-size set to be " + nonVoters); + } + + @Test(expectedExceptions = IllegalStateException.class) + public void testMoreMembersThanMaximumAllowsRejected() { + makeSetWithNMembers(ReplicaSetConfig.MAXIMUM_REPLICA_SET_SIZE + 1); + } + + @Test + public void testPrimaryGivenVoteWhenLastInMemberList() { + BasicBSONObject config = ReplicaSetConfig.builder("rs") + .member("host-a", 1, 1) + .member("host-b", 2, 2) + .member("host-c", 3, 3) + .member("host-d", 4, 4) + .primary(HostAndPort.fromParts("host-d", 4)) + .build(); + assertEquals(votingMembersOfSet(config).size(), 3); + assertEquals(nonVotingMembersOfSet(config).size(), 1); + assertTrue(votingMembersOfSet(config).contains(HostAndPort.fromParts("host-d", 4))); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBConfigServerIntegrationTest.java ---------------------------------------------------------------------- diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBConfigServerIntegrationTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBConfigServerIntegrationTest.java new file mode 100644 index 0000000..fb748e4 --- /dev/null +++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBConfigServerIntegrationTest.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.entity.nosql.mongodb.sharding; + +import static org.testng.Assert.assertFalse; + +import org.apache.brooklyn.entity.nosql.mongodb.MongoDBServer; +import org.apache.brooklyn.entity.nosql.mongodb.MongoDBTestHelper; +import org.apache.brooklyn.entity.nosql.mongodb.sharding.MongoDBConfigServer; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import brooklyn.entity.basic.ApplicationBuilder; +import brooklyn.entity.basic.Entities; +import brooklyn.entity.proxying.EntitySpec; +import brooklyn.entity.trait.Startable; +import brooklyn.location.basic.LocalhostMachineProvisioningLocation; +import brooklyn.test.Asserts; +import brooklyn.test.EntityTestUtils; +import brooklyn.test.entity.TestApplication; + +import com.google.common.collect.ImmutableList; + +public class MongoDBConfigServerIntegrationTest { + private TestApplication app; + private LocalhostMachineProvisioningLocation localhostProvisioningLocation; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + localhostProvisioningLocation = new LocalhostMachineProvisioningLocation(); + app = ApplicationBuilder.newManagedApp(TestApplication.class); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() throws Exception { + if (app != null) Entities.destroyAll(app.getManagementContext()); + } + + @Test(groups = "Integration") + public void testCanStartAndStop() throws Exception { + MongoDBConfigServer entity = app.createAndManageChild(EntitySpec.create(MongoDBConfigServer.class) + .configure(MongoDBServer.MONGODB_CONF_TEMPLATE_URL, "classpath:///test-mongodb-configserver.conf")); + app.start(ImmutableList.of(localhostProvisioningLocation)); + + EntityTestUtils.assertAttributeEqualsEventually(entity, Startable.SERVICE_UP, true); + Asserts.assertTrue(MongoDBTestHelper.isConfigServer(entity), "Server is not a config server"); + entity.stop(); + assertFalse(entity.getAttribute(Startable.SERVICE_UP)); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentEc2LiveTest.java ---------------------------------------------------------------------- diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentEc2LiveTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentEc2LiveTest.java new file mode 100644 index 0000000..9e8ff55 --- /dev/null +++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentEc2LiveTest.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.entity.nosql.mongodb.sharding; + +import groovy.time.TimeDuration; + +import org.apache.brooklyn.entity.nosql.mongodb.MongoDBReplicaSet; +import org.apache.brooklyn.entity.nosql.mongodb.MongoDBServer; +import org.apache.brooklyn.entity.nosql.mongodb.sharding.MongoDBConfigServer; +import org.apache.brooklyn.entity.nosql.mongodb.sharding.MongoDBRouter; +import org.apache.brooklyn.entity.nosql.mongodb.sharding.MongoDBShardedDeployment; +import org.testng.Assert; +import org.testng.annotations.Test; + +import brooklyn.entity.AbstractEc2LiveTest; +import brooklyn.entity.Entity; +import brooklyn.entity.basic.Entities; +import brooklyn.entity.proxying.EntitySpec; +import brooklyn.location.Location; +import brooklyn.test.Asserts; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +/** + * NOTE: These test will provision 9 machines in AWS, which can cause 'Request limit exceeded' and + * 'Exhausted available authentication methods' exceptions, depending upon current AWS load. You can + * mitigate this issue by adding the following lines to your brooklyn.properties: + * + * brooklyn.location.jclouds.machineCreateAttempts=3 + * brooklyn.jclouds.aws-ec2.maxConcurrentMachineCreations=5 + */ +@Test +public class MongoDBShardedDeploymentEc2LiveTest extends AbstractEc2LiveTest { + + private static final Integer ROUTER_CLUSTER_SIZE = 2; + private static final Integer REPLICASET_SIZE = 2; + private static final Integer SHARD_CLUSTER_SIZE = 3; + private static final TimeDuration TIMEOUT = new TimeDuration(0, 3, 0, 0); + + @Override + protected void doTest(Location loc) throws Exception { + final MongoDBShardedDeployment deployment = app.createAndManageChild(EntitySpec.create(MongoDBShardedDeployment.class) + .configure(MongoDBShardedDeployment.INITIAL_ROUTER_CLUSTER_SIZE, ROUTER_CLUSTER_SIZE) + .configure(MongoDBShardedDeployment.SHARD_REPLICASET_SIZE, REPLICASET_SIZE) + .configure(MongoDBShardedDeployment.INITIAL_SHARD_CLUSTER_SIZE, SHARD_CLUSTER_SIZE) + .configure(MongoDBShardedDeployment.MONGODB_REPLICA_SET_SPEC, EntitySpec.create(MongoDBReplicaSet.class) + .configure(MongoDBServer.MONGODB_CONF_TEMPLATE_URL, "classpath:///test-mongodb.conf") + .configure(MongoDBReplicaSet.MEMBER_SPEC, EntitySpec.create(MongoDBServer.class))) + .configure(MongoDBShardedDeployment.MONGODB_ROUTER_SPEC, EntitySpec.create(MongoDBRouter.class) + .configure(MongoDBConfigServer.MONGODB_CONF_TEMPLATE_URL, "classpath:///test-mongodb-router.conf")) + .configure(MongoDBShardedDeployment.MONGODB_CONFIG_SERVER_SPEC, EntitySpec.create(MongoDBConfigServer.class) + .configure(MongoDBConfigServer.MONGODB_CONF_TEMPLATE_URL, "classpath:///test-mongodb-configserver.conf"))); + + app.start(ImmutableList.of(loc)); + + Entities.dumpInfo(app); + + Asserts.succeedsEventually(ImmutableMap.of("timeout", TIMEOUT), new Runnable() { + public void run() { + Assert.assertEquals(deployment.getRouterCluster().getCurrentSize(), ROUTER_CLUSTER_SIZE); + Assert.assertEquals(deployment.getShardCluster().getCurrentSize(), SHARD_CLUSTER_SIZE); + Assert.assertEquals(deployment.getConfigCluster().getCurrentSize(), MongoDBShardedDeployment.CONFIG_CLUSTER_SIZE.getDefaultValue()); + for (Entity entity : deployment.getShardCluster().getMembers()) { + Assert.assertEquals(((MongoDBReplicaSet) entity).getCurrentSize(), REPLICASET_SIZE); + } + } + }); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentIntegrationTest.java ---------------------------------------------------------------------- diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentIntegrationTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentIntegrationTest.java new file mode 100644 index 0000000..e4947d3 --- /dev/null +++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/mongodb/sharding/MongoDBShardedDeploymentIntegrationTest.java @@ -0,0 +1,135 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.entity.nosql.mongodb.sharding; + +import org.apache.brooklyn.entity.nosql.mongodb.AbstractMongoDBServer; +import org.apache.brooklyn.entity.nosql.mongodb.MongoDBReplicaSet; +import org.apache.brooklyn.entity.nosql.mongodb.MongoDBServer; +import org.apache.brooklyn.entity.nosql.mongodb.MongoDBTestHelper; +import org.apache.brooklyn.entity.nosql.mongodb.sharding.MongoDBConfigServer; +import org.apache.brooklyn.entity.nosql.mongodb.sharding.MongoDBConfigServerCluster; +import org.apache.brooklyn.entity.nosql.mongodb.sharding.MongoDBRouter; +import org.apache.brooklyn.entity.nosql.mongodb.sharding.MongoDBRouterCluster; +import org.apache.brooklyn.entity.nosql.mongodb.sharding.MongoDBShardCluster; +import org.apache.brooklyn.entity.nosql.mongodb.sharding.MongoDBShardedDeployment; +import org.testng.Assert; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import brooklyn.entity.BrooklynAppLiveTestSupport; +import brooklyn.entity.Entity; +import brooklyn.entity.proxying.EntitySpec; +import brooklyn.entity.trait.Startable; +import brooklyn.location.basic.LocalhostMachineProvisioningLocation; +import brooklyn.test.EntityTestUtils; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; +import com.mongodb.DBObject; + +public class MongoDBShardedDeploymentIntegrationTest extends BrooklynAppLiveTestSupport { + + private static final Integer ROUTER_CLUSTER_SIZE = 2; + private static final Integer REPLICASET_SIZE = 2; + private static final Integer SHARD_CLUSTER_SIZE = 3; + + private LocalhostMachineProvisioningLocation localhostProvisioningLocation; + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + super.setUp(); + localhostProvisioningLocation = app.newLocalhostProvisioningLocation(); + } + + private MongoDBShardedDeployment makeAndStartDeployment() { + final MongoDBShardedDeployment deployment = app.createAndManageChild(EntitySpec.create(MongoDBShardedDeployment.class) + .configure(MongoDBShardedDeployment.INITIAL_ROUTER_CLUSTER_SIZE, ROUTER_CLUSTER_SIZE) + .configure(MongoDBShardedDeployment.SHARD_REPLICASET_SIZE, REPLICASET_SIZE) + .configure(MongoDBShardedDeployment.INITIAL_SHARD_CLUSTER_SIZE, SHARD_CLUSTER_SIZE) + .configure(MongoDBShardedDeployment.MONGODB_REPLICA_SET_SPEC, EntitySpec.create(MongoDBReplicaSet.class) + .configure(MongoDBServer.MONGODB_CONF_TEMPLATE_URL, "classpath:///test-mongodb.conf") + .configure(MongoDBReplicaSet.MEMBER_SPEC, EntitySpec.create(MongoDBServer.class))) + .configure(MongoDBShardedDeployment.MONGODB_ROUTER_SPEC, EntitySpec.create(MongoDBRouter.class) + .configure(MongoDBConfigServer.MONGODB_CONF_TEMPLATE_URL, "classpath:///test-mongodb-router.conf")) + .configure(MongoDBShardedDeployment.MONGODB_CONFIG_SERVER_SPEC, EntitySpec.create(MongoDBConfigServer.class) + .configure(MongoDBConfigServer.MONGODB_CONF_TEMPLATE_URL, "classpath:///test-mongodb-configserver.conf"))); + app.start(ImmutableList.of(localhostProvisioningLocation)); + EntityTestUtils.assertAttributeEqualsEventually(deployment, Startable.SERVICE_UP, true); + return deployment; + } + + @Test(groups = "Integration") + public void testCanStartAndStopDeployment() { + MongoDBShardedDeployment deployment = makeAndStartDeployment(); + deployment.stop(); + EntityTestUtils.assertAttributeEqualsEventually(deployment, Startable.SERVICE_UP, false); + } + + @Test(groups = "Integration") + public void testDeployedStructure() { + MongoDBShardedDeployment deployment = makeAndStartDeployment(); + MongoDBConfigServerCluster configServers = deployment.getConfigCluster(); + MongoDBRouterCluster routers = deployment.getRouterCluster(); + MongoDBShardCluster shards = deployment.getShardCluster(); + Assert.assertNotNull(configServers); + Assert.assertNotNull(routers); + Assert.assertNotNull(shards); + Assert.assertEquals(configServers.getCurrentSize(), MongoDBShardedDeployment.CONFIG_CLUSTER_SIZE.getDefaultValue()); + Assert.assertEquals(routers.getCurrentSize(), ROUTER_CLUSTER_SIZE); + Assert.assertEquals(shards.getCurrentSize(), SHARD_CLUSTER_SIZE); + for (Entity entity : deployment.getShardCluster().getMembers()) { + Assert.assertEquals(((MongoDBReplicaSet)entity).getCurrentSize(), REPLICASET_SIZE); + } + for (Entity entity : configServers.getMembers()) { + checkEntityTypeAndServiceUp(entity, MongoDBConfigServer.class); + } + for (Entity entity : routers.getMembers()) { + checkEntityTypeAndServiceUp(entity, MongoDBRouter.class); + } + for (Entity entity : shards.getMembers()) { + checkEntityTypeAndServiceUp(entity, MongoDBReplicaSet.class); + } + } + + @Test(groups = "Integration") + private void testReadAndWriteDifferentRouters() { + MongoDBShardedDeployment deployment = makeAndStartDeployment(); + EntityTestUtils.assertAttributeEqualsEventually(deployment, Startable.SERVICE_UP, true); + MongoDBRouter router1 = (MongoDBRouter) Iterables.get(deployment.getRouterCluster().getMembers(), 0); + MongoDBRouter router2 = (MongoDBRouter) Iterables.get(deployment.getRouterCluster().getMembers(), 1); + EntityTestUtils.assertAttributeEqualsEventually(router1, Startable.SERVICE_UP, true); + EntityTestUtils.assertAttributeEqualsEventually(router2, Startable.SERVICE_UP, true); + + String documentId = MongoDBTestHelper.insert(router1, "meaning-of-life", 42); + DBObject docOut = MongoDBTestHelper.getById(router2, documentId); + Assert.assertEquals(docOut.get("meaning-of-life"), 42); + + for (Entity entity : Iterables.filter(app.getManagementContext().getEntityManager().getEntitiesInApplication(app), AbstractMongoDBServer.class)) { + EntityTestUtils.assertAttributeEqualsEventually(entity, Startable.SERVICE_UP, true); + } + } + + private void checkEntityTypeAndServiceUp(Entity entity, Class<? extends Entity> expectedClass) { + Assert.assertNotNull(entity); + Assert.assertTrue(expectedClass.isAssignableFrom(entity.getClass()), "expected: " + expectedClass + + " on interfaces, found: " + entity.getClass().getInterfaces()); + EntityTestUtils.assertAttributeEqualsEventually(entity, Startable.SERVICE_UP, true); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/redis/JedisSupport.java ---------------------------------------------------------------------- diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/redis/JedisSupport.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/redis/JedisSupport.java new file mode 100644 index 0000000..81abb42 --- /dev/null +++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/redis/JedisSupport.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.entity.nosql.redis; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +import org.apache.brooklyn.entity.nosql.redis.RedisStore; + +import redis.clients.jedis.Jedis; + +import com.google.common.base.Strings; + +/** + * {@link RedisStore} testing using Jedis API. + */ +public class JedisSupport { + private static final String TEST_DATA = Strings.repeat("0123456789", 16); + + private RedisStore redis; + + public JedisSupport(RedisStore redis) { + this.redis = redis; + } + + /** + * Exercise the {@link RedisStore} using the Jedis API. + */ + public void redisTest() throws Exception { + writeData("brooklyn", TEST_DATA); + String result = readData("brooklyn"); + assertEquals(result, TEST_DATA); + } + + public void writeData(String key, String val) throws Exception { + Jedis client = getRedisClient(redis); + try { + client.set(key, val); + } finally { + client.disconnect(); + } + } + + public String readData(String key) throws Exception { + Jedis client = getRedisClient(redis); + try { + return client.get(key); + } finally { + client.disconnect(); + } + } + + private Jedis getRedisClient(RedisStore redis) { + int port = redis.getAttribute(RedisStore.REDIS_PORT); + String host = redis.getAttribute(RedisStore.HOSTNAME); + Jedis client = new Jedis(host, port); + client.connect(); + assertTrue(client.isConnected()); + return client; + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/redis/RedisClusterIntegrationTest.java ---------------------------------------------------------------------- diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/redis/RedisClusterIntegrationTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/redis/RedisClusterIntegrationTest.java new file mode 100644 index 0000000..6331662 --- /dev/null +++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/redis/RedisClusterIntegrationTest.java @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.entity.nosql.redis; + +import static org.testng.Assert.assertEquals; + +import java.util.Collection; +import java.util.List; +import java.util.concurrent.Callable; + +import org.apache.brooklyn.entity.nosql.redis.RedisCluster; +import org.apache.brooklyn.entity.nosql.redis.RedisSlave; +import org.apache.brooklyn.entity.nosql.redis.RedisStore; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import brooklyn.entity.basic.ApplicationBuilder; +import brooklyn.entity.basic.Entities; +import brooklyn.entity.group.DynamicCluster; +import brooklyn.entity.proxying.EntitySpec; +import brooklyn.entity.trait.Startable; +import brooklyn.location.Location; +import brooklyn.location.basic.LocalhostMachineProvisioningLocation; +import brooklyn.test.Asserts; +import brooklyn.test.EntityTestUtils; +import brooklyn.test.entity.TestApplication; + +import com.google.common.collect.ImmutableList; + +public class RedisClusterIntegrationTest { + + private TestApplication app; + private Location loc; + private RedisCluster cluster; + + @BeforeMethod(alwaysRun=true) + public void setup() { + app = ApplicationBuilder.newManagedApp(TestApplication.class); + loc = new LocalhostMachineProvisioningLocation(); + } + + @AfterMethod(alwaysRun=true) + public void shutdown() { + if (app != null) Entities.destroyAll(app.getManagementContext()); + } + + @Test(groups = { "Integration" }) + public void testRedisClusterReplicates() throws Exception { + final String key = "mykey"; + final String val = "1234567890"; + + cluster = app.createAndManageChild(EntitySpec.create(RedisCluster.class) + .configure(DynamicCluster.INITIAL_SIZE, 3)); + app.start(ImmutableList.of(loc)); + + EntityTestUtils.assertAttributeEqualsEventually(cluster, Startable.SERVICE_UP, true); + + RedisStore master = cluster.getMaster(); + List<RedisSlave> slaves = ImmutableList.<RedisSlave>copyOf((Collection)cluster.getSlaves().getMembers()); + + assertEquals(slaves.size(), 3); + + JedisSupport viaMaster = new JedisSupport(master); + viaMaster.writeData(key, val); + assertEquals(viaMaster.readData(key), val); + + for (RedisSlave slave : slaves) { + final JedisSupport viaSlave = new JedisSupport(slave); + Asserts.succeedsEventually(new Callable<Void>() { + @Override public Void call() throws Exception { + assertEquals(viaSlave.readData(key), val); + return null; + }}); + } + + // Check that stopping slave will not stop anything else + // (it used to stop master because wasn't supplying port!) + slaves.get(0).stop(); + EntityTestUtils.assertAttributeEqualsEventually(slaves.get(0), Startable.SERVICE_UP, false); + + assertEquals(master.getAttribute(Startable.SERVICE_UP), Boolean.TRUE); + for (RedisSlave slave : slaves.subList(1, slaves.size())) { + assertEquals(slave.getAttribute(Startable.SERVICE_UP), Boolean.TRUE); + } + + // Check that stopping cluster will stop everything + cluster.stop(); + + EntityTestUtils.assertAttributeEqualsEventually(cluster, Startable.SERVICE_UP, false); + assertEquals(master.getAttribute(Startable.SERVICE_UP), Boolean.FALSE); + for (RedisSlave slave : slaves) { + assertEquals(slave.getAttribute(Startable.SERVICE_UP), Boolean.FALSE); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/redis/RedisEc2LiveTest.java ---------------------------------------------------------------------- diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/redis/RedisEc2LiveTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/redis/RedisEc2LiveTest.java new file mode 100644 index 0000000..3d0b421 --- /dev/null +++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/redis/RedisEc2LiveTest.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.entity.nosql.redis; + +import javax.annotation.Nullable; + +import org.apache.brooklyn.entity.nosql.redis.RedisStore; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.Test; + +import brooklyn.entity.AbstractEc2LiveTest; +import brooklyn.entity.proxying.EntitySpec; +import brooklyn.location.Location; +import brooklyn.test.EntityTestUtils; + +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableList; + +public class RedisEc2LiveTest extends AbstractEc2LiveTest { + + @SuppressWarnings("unused") + private static final Logger LOG = LoggerFactory.getLogger(RedisEc2LiveTest.class); + + @Override + protected void doTest(Location loc) throws Exception { + RedisStore redis = app.createAndManageChild(EntitySpec.create(RedisStore.class)); + app.start(ImmutableList.of(loc)); + EntityTestUtils.assertAttributeEqualsEventually(redis, RedisStore.SERVICE_UP, true); + + JedisSupport support = new JedisSupport(redis); + support.redisTest(); + // Confirm sensors are valid + EntityTestUtils.assertPredicateEventuallyTrue(redis, new Predicate<RedisStore>() { + @Override public boolean apply(@Nullable RedisStore input) { + return input != null && + input.getAttribute(RedisStore.UPTIME) > 0 && + input.getAttribute(RedisStore.TOTAL_COMMANDS_PROCESSED) >= 0 && + input.getAttribute(RedisStore.TOTAL_CONNECTIONS_RECEIVED) >= 0 && + input.getAttribute(RedisStore.EXPIRED_KEYS) >= 0 && + input.getAttribute(RedisStore.EVICTED_KEYS) >= 0 && + input.getAttribute(RedisStore.KEYSPACE_HITS) >= 0 && + input.getAttribute(RedisStore.KEYSPACE_MISSES) >= 0; + } + }); + + } + + @Test(enabled=false) + public void testDummy() {} // Convince testng IDE integration that this really does have test methods +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/redis/RedisIntegrationTest.java ---------------------------------------------------------------------- diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/redis/RedisIntegrationTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/redis/RedisIntegrationTest.java new file mode 100644 index 0000000..8af953f --- /dev/null +++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/redis/RedisIntegrationTest.java @@ -0,0 +1,120 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.entity.nosql.redis; + +import javax.annotation.Nullable; + +import org.apache.brooklyn.entity.nosql.redis.RedisStore; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import brooklyn.entity.basic.Entities; +import brooklyn.entity.proxying.EntitySpec; +import brooklyn.entity.trait.Startable; +import brooklyn.location.Location; +import brooklyn.location.basic.PortRanges; +import brooklyn.test.EntityTestUtils; +import brooklyn.test.entity.TestApplication; +import brooklyn.util.time.Duration; + +import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +/** + * Test the operation of the {@link RedisStore} class. + */ +public class RedisIntegrationTest { + + private TestApplication app; + private Location loc; + private RedisStore redis; + + @BeforeMethod(alwaysRun=true) + public void setup() { + app = TestApplication.Factory.newManagedInstanceForTests(); + loc = app.newLocalhostProvisioningLocation(); + } + + @AfterMethod(alwaysRun=true) + public void shutdown() { + if (app != null) Entities.destroyAll(app.getManagementContext()); + } + + /** + * Test that the server starts up and sets SERVICE_UP correctly. + */ + @Test(groups = { "Integration" }) + public void canStartupAndShutdown() throws Exception { + redis = app.createAndManageChild(EntitySpec.create(RedisStore.class)); + app.start(ImmutableList.of(loc)); + + EntityTestUtils.assertAttributeEqualsEventually(redis, Startable.SERVICE_UP, true); + + redis.stop(); + + EntityTestUtils.assertAttributeEqualsEventually(redis, Startable.SERVICE_UP, false); + } + + /** + * Test that a client can connect to the service. + */ + @Test(groups = { "Integration" }) + public void testRedisConnection() throws Exception { + redis = app.createAndManageChild(EntitySpec.create(RedisStore.class)); + app.start(ImmutableList.of(loc)); + + EntityTestUtils.assertAttributeEqualsEventually(redis, Startable.SERVICE_UP, true); + + JedisSupport support = new JedisSupport(redis); + support.redisTest(); + } + + /** + * Test we get sensors from an instance on a non-default port + */ + @Test(groups = { "Integration" }) + public void testNonStandardPort() throws Exception { + redis = app.createAndManageChild(EntitySpec.create(RedisStore.class) + .configure(RedisStore.REDIS_PORT, PortRanges.fromString("10000+"))); + app.start(ImmutableList.of(loc)); + + EntityTestUtils.assertAttributeEqualsEventually(redis, Startable.SERVICE_UP, true); + JedisSupport support = new JedisSupport(redis); + support.redisTest(); + + // Increase timeout because test was failing on jenkins sometimes. The log shows only one + // call to `info server` (for obtaining uptime) which took 26 seconds; then 4 seconds later + // this assert failed (with it checking every 500ms). The response did correctly contain + // `uptime_in_seconds:27`. + EntityTestUtils.assertPredicateEventuallyTrue(ImmutableMap.of("timeout", Duration.FIVE_MINUTES), redis, new Predicate<RedisStore>() { + @Override public boolean apply(@Nullable RedisStore input) { + return input != null && + input.getAttribute(RedisStore.UPTIME) > 0 && + input.getAttribute(RedisStore.TOTAL_COMMANDS_PROCESSED) >= 0 && + input.getAttribute(RedisStore.TOTAL_CONNECTIONS_RECEIVED) >= 0 && + input.getAttribute(RedisStore.EXPIRED_KEYS) >= 0 && + input.getAttribute(RedisStore.EVICTED_KEYS) >= 0 && + input.getAttribute(RedisStore.KEYSPACE_HITS) >= 0 && + input.getAttribute(RedisStore.KEYSPACE_MISSES) >= 0; + } + }); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/riak/RiakClusterEc2LiveTest.java ---------------------------------------------------------------------- diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/riak/RiakClusterEc2LiveTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/riak/RiakClusterEc2LiveTest.java new file mode 100644 index 0000000..883299f --- /dev/null +++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/riak/RiakClusterEc2LiveTest.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.entity.nosql.riak; + +import org.apache.brooklyn.entity.nosql.riak.RiakCluster; +import org.apache.brooklyn.entity.nosql.riak.RiakNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.Test; + +import brooklyn.entity.AbstractEc2LiveTest; +import brooklyn.entity.basic.Attributes; +import brooklyn.entity.proxying.EntitySpec; +import brooklyn.location.Location; +import brooklyn.test.EntityTestUtils; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; + +public class RiakClusterEc2LiveTest extends AbstractEc2LiveTest { + @SuppressWarnings("unused") + private static final Logger LOG = LoggerFactory.getLogger(RiakNodeEc2LiveTest.class); + + @Override + protected void doTest(Location loc) throws Exception { + RiakCluster cluster = app.createAndManageChild(EntitySpec.create(RiakCluster.class) + .configure(RiakCluster.INITIAL_SIZE, 3) + .configure(RiakCluster.MEMBER_SPEC, EntitySpec.create(RiakNode.class))); + app.start(ImmutableList.of(loc)); + + EntityTestUtils.assertAttributeEqualsEventually(cluster, RiakNode.SERVICE_UP, true); + + RiakNode first = (RiakNode) Iterables.get(cluster.getMembers(), 0); + RiakNode second = (RiakNode) Iterables.get(cluster.getMembers(), 1); + + assertNodesUpAndInCluster(first, second); + + EntityTestUtils.assertAttributeEqualsEventually(cluster, Attributes.SERVICE_UP, true); + } + + private void assertNodesUpAndInCluster(final RiakNode... nodes) { + for (final RiakNode node : nodes) { + EntityTestUtils.assertAttributeEqualsEventually(node, RiakNode.SERVICE_UP, true); + EntityTestUtils.assertAttributeEqualsEventually(node, RiakNode.RIAK_NODE_HAS_JOINED_CLUSTER, true); + } + } + + @Test(enabled = false) + public void testDummy() { + } // Convince TestNG IDE integration that this really does have test methods + + + @Override + public void test_Ubuntu_12_0() throws Exception { + //Override to add the custom securityGroup for opening Riak ports. + // Image: {id=us-east-1/ami-d0f89fb9, providerId=ami-d0f89fb9, name=ubuntu/images/ebs/ubuntu-precise-12.04-amd64-server-20130411.1, location={scope=REGION, id=us-east-1, description=us-east-1, parent=aws-ec2, iso3166Codes=[US-VA]}, os={family=ubuntu, arch=paravirtual, version=12.04, description=099720109477/ubuntu/images/ebs/ubuntu-precise-12.04-amd64-server-20130411.1, is64Bit=true}, description=099720109477/ubuntu/images/ebs/ubuntu-precise-12.04-amd64-server-20130411.1, version=20130411.1, status=AVAILABLE[available], loginUser=ubuntu, userMetadata={owner=099720109477, rootDeviceType=ebs, virtualizationType=paravirtual, hypervisor=xen}} + runTest(ImmutableMap.of("imageId", "us-east-1/ami-d0f89fb9", "loginUser", "ubuntu", "hardwareId", SMALL_HARDWARE_ID, "securityGroups", "RiakSecurityGroup")); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeEc2LiveTest.java ---------------------------------------------------------------------- diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeEc2LiveTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeEc2LiveTest.java new file mode 100644 index 0000000..1d69103 --- /dev/null +++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeEc2LiveTest.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.entity.nosql.riak; + +import org.apache.brooklyn.entity.nosql.riak.RiakNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; + +import brooklyn.entity.AbstractEc2LiveTest; +import brooklyn.entity.proxying.EntitySpec; +import brooklyn.location.Location; +import brooklyn.test.EntityTestUtils; + +public class RiakNodeEc2LiveTest extends AbstractEc2LiveTest { + + @SuppressWarnings("unused") + private static final Logger LOG = LoggerFactory.getLogger(RiakNodeEc2LiveTest.class); + + @Override + protected void doTest(Location loc) throws Exception { + RiakNode entity = app.createAndManageChild(EntitySpec.create(RiakNode.class)); + app.start(ImmutableList.of(loc)); + + EntityTestUtils.assertAttributeEqualsEventually(entity, RiakNode.SERVICE_UP, true); + + } + + @Test(enabled = false) + public void testDummy() { + } // Convince TestNG IDE integration that this really does have test methods + + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeGoogleComputeLiveTest.java ---------------------------------------------------------------------- diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeGoogleComputeLiveTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeGoogleComputeLiveTest.java new file mode 100644 index 0000000..a5877c4 --- /dev/null +++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeGoogleComputeLiveTest.java @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.entity.nosql.riak; + +import org.apache.brooklyn.entity.nosql.riak.RiakCluster; +import org.apache.brooklyn.entity.nosql.riak.RiakNode; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; + +import brooklyn.entity.AbstractGoogleComputeLiveTest; +import brooklyn.entity.proxying.EntitySpec; +import brooklyn.location.Location; +import brooklyn.test.EntityTestUtils; + +public class RiakNodeGoogleComputeLiveTest extends AbstractGoogleComputeLiveTest { + @Override + protected void doTest(Location loc) throws Exception { + RiakCluster cluster = app.createAndManageChild(EntitySpec.create(RiakCluster.class) + .configure(RiakCluster.INITIAL_SIZE, 2) + .configure(RiakCluster.MEMBER_SPEC, EntitySpec.create(RiakNode.class))); + app.start(ImmutableList.of(loc)); + + EntityTestUtils.assertAttributeEqualsEventually(cluster, RiakCluster.SERVICE_UP, true); + + RiakNode first = (RiakNode) Iterables.get(cluster.getMembers(), 0); + RiakNode second = (RiakNode) Iterables.get(cluster.getMembers(), 1); + + EntityTestUtils.assertAttributeEqualsEventually(first, RiakNode.SERVICE_UP, true); + EntityTestUtils.assertAttributeEqualsEventually(second, RiakNode.SERVICE_UP, true); + + EntityTestUtils.assertAttributeEqualsEventually(first, RiakNode.RIAK_NODE_HAS_JOINED_CLUSTER, true); + EntityTestUtils.assertAttributeEqualsEventually(second, RiakNode.RIAK_NODE_HAS_JOINED_CLUSTER, true); + + } + + @Test(groups = {"Live"}) + @Override + public void test_DefaultImage() throws Exception { + super.test_DefaultImage(); + } + + @Test(enabled = false) + public void testDummy() { + } // Convince testng IDE integration that this really does have test methods + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeIntegrationTest.java ---------------------------------------------------------------------- diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeIntegrationTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeIntegrationTest.java new file mode 100644 index 0000000..50c946f --- /dev/null +++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeIntegrationTest.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.entity.nosql.riak; + +import static org.testng.Assert.assertFalse; + +import org.apache.brooklyn.entity.nosql.riak.RiakNode; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; + +import brooklyn.entity.basic.Entities; +import brooklyn.entity.proxying.EntitySpec; +import brooklyn.entity.trait.Startable; +import brooklyn.location.basic.LocalhostMachineProvisioningLocation; +import brooklyn.test.EntityTestUtils; +import brooklyn.test.entity.TestApplication; + +public class RiakNodeIntegrationTest { + + private TestApplication app; + private LocalhostMachineProvisioningLocation localhostProvisioningLocation; + + @BeforeMethod(alwaysRun = true) + public void setUp() throws Exception { + localhostProvisioningLocation = new LocalhostMachineProvisioningLocation(); + app = TestApplication.Factory.newManagedInstanceForTests(); + } + + @AfterMethod(alwaysRun = true) + public void tearDown() throws Exception { + if (app != null) Entities.destroyAll(app.getManagementContext()); + } + + + @Test(groups = "Integration") + public void testCanStartAndStop() throws Exception { + RiakNode entity = app.createAndManageChild(EntitySpec.create(RiakNode.class) + .configure(RiakNode.SUGGESTED_VERSION, "2.1.1")); + app.start(ImmutableList.of(localhostProvisioningLocation)); + + EntityTestUtils.assertAttributeEqualsEventually(entity, Startable.SERVICE_UP, true); + entity.stop(); + assertFalse(entity.getAttribute(Startable.SERVICE_UP)); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeSoftlayerLiveTest.java ---------------------------------------------------------------------- diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeSoftlayerLiveTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeSoftlayerLiveTest.java new file mode 100644 index 0000000..069a920 --- /dev/null +++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/riak/RiakNodeSoftlayerLiveTest.java @@ -0,0 +1,46 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.entity.nosql.riak; + +import org.apache.brooklyn.entity.nosql.riak.RiakNode; +import org.testng.annotations.BeforeMethod; + +import com.google.common.collect.ImmutableList; + +import brooklyn.entity.AbstractSoftlayerLiveTest; +import brooklyn.entity.proxying.EntitySpec; +import brooklyn.location.Location; +import brooklyn.test.EntityTestUtils; + +public class RiakNodeSoftlayerLiveTest extends AbstractSoftlayerLiveTest { + + @BeforeMethod(alwaysRun=true) + public void setUp() throws Exception { + super.setUp(); + } + + @Override + protected void doTest(Location loc) throws Exception { + RiakNode entity = app.createAndManageChild(EntitySpec.create(RiakNode.class) + .configure(RiakNode.SUGGESTED_VERSION, "2.1.1")); + app.start(ImmutableList.of(loc)); + + EntityTestUtils.assertAttributeEqualsEventually(entity, RiakNode.SERVICE_UP, true); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/solr/AbstractSolrServerTest.java ---------------------------------------------------------------------- diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/solr/AbstractSolrServerTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/solr/AbstractSolrServerTest.java new file mode 100644 index 0000000..381a78d --- /dev/null +++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/solr/AbstractSolrServerTest.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.entity.nosql.solr; + +import org.apache.brooklyn.entity.nosql.solr.SolrServer; +import org.testng.annotations.BeforeMethod; + +import brooklyn.entity.BrooklynAppLiveTestSupport; +import brooklyn.location.Location; + +/** + * Solr test framework for integration and live tests. + */ +public class AbstractSolrServerTest extends BrooklynAppLiveTestSupport { + + protected Location testLocation; + protected SolrServer solr; + + @BeforeMethod(alwaysRun = true) + @Override + public void setUp() throws Exception { + super.setUp(); + testLocation = app.newLocalhostProvisioningLocation(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/solr/SolrJSupport.java ---------------------------------------------------------------------- diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/solr/SolrJSupport.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/solr/SolrJSupport.java new file mode 100644 index 0000000..d192c05 --- /dev/null +++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/solr/SolrJSupport.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.entity.nosql.solr; + +import java.util.Map; + +import org.apache.brooklyn.entity.nosql.solr.SolrServer; +import org.apache.solr.client.solrj.SolrQuery; +import org.apache.solr.client.solrj.impl.HttpSolrServer; +import org.apache.solr.common.SolrDocument; +import org.apache.solr.common.SolrInputDocument; + +import brooklyn.entity.basic.Attributes; + +/** + * Solr testing using SolrJ API. + */ +public class SolrJSupport { + + private final HttpSolrServer server; + + public SolrJSupport(SolrServer node, String core) { + this(node.getAttribute(Attributes.HOSTNAME), node.getSolrPort(), core); + } + + public SolrJSupport(String hostname, int solrPort, String core) { + server = new HttpSolrServer(String.format("http://%s:%d/solr/%s", hostname, solrPort, core)); + server.setMaxRetries(1); + server.setConnectionTimeout(5000); + server.setSoTimeout(5000); + } + + public void commit() throws Exception { + server.commit(); + } + + public void addDocument(Map<String, Object> fields) throws Exception { + SolrInputDocument doc = new SolrInputDocument(); + for (String field : fields.keySet()) { + doc.setField(field, fields.get(field)); + } + server.add(doc, 100); + } + + public Iterable<SolrDocument> getDocuments() throws Exception { + SolrQuery solrQuery = new SolrQuery(); + solrQuery.setQuery("*:*"); + + return server.query(solrQuery).getResults(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/solr/SolrServerEc2LiveTest.java ---------------------------------------------------------------------- diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/solr/SolrServerEc2LiveTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/solr/SolrServerEc2LiveTest.java new file mode 100644 index 0000000..ef2f166 --- /dev/null +++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/solr/SolrServerEc2LiveTest.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.entity.nosql.solr; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +import org.apache.brooklyn.entity.nosql.solr.SolrServer; +import org.apache.solr.common.SolrDocument; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import brooklyn.entity.AbstractEc2LiveTest; +import brooklyn.entity.proxying.EntitySpec; +import brooklyn.entity.trait.Startable; +import brooklyn.location.Location; +import brooklyn.test.EntityTestUtils; +import brooklyn.util.collections.MutableMap; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; + +public class SolrServerEc2LiveTest extends AbstractEc2LiveTest { + + private static final Logger log = LoggerFactory.getLogger(SolrServerEc2LiveTest.class); + + @Override + protected void doTest(Location loc) throws Exception { + log.info("Testing Solr on {}", loc); + + SolrServer solr = app.createAndManageChild(EntitySpec.create(SolrServer.class) + .configure(SolrServer.SOLR_CORE_CONFIG, ImmutableMap.of("example", "classpath://solr/example.tgz"))); + app.start(ImmutableList.of(loc)); + + EntityTestUtils.assertAttributeEqualsEventually(solr, Startable.SERVICE_UP, true); + + SolrJSupport client = new SolrJSupport(solr, "example"); + + Iterable<SolrDocument> results = client.getDocuments(); + assertTrue(Iterables.isEmpty(results)); + + client.addDocument(MutableMap.<String, Object>of("id", "1", "description", "first")); + client.addDocument(MutableMap.<String, Object>of("id", "2", "description", "second")); + client.addDocument(MutableMap.<String, Object>of("id", "3", "description", "third")); + client.commit(); + + results = client.getDocuments(); + assertEquals(Iterables.size(results), 3); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/solr/SolrServerIntegrationTest.java ---------------------------------------------------------------------- diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/solr/SolrServerIntegrationTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/solr/SolrServerIntegrationTest.java new file mode 100644 index 0000000..23ca974 --- /dev/null +++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/solr/SolrServerIntegrationTest.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.entity.nosql.solr; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +import org.apache.brooklyn.entity.nosql.solr.SolrServer; +import org.apache.solr.common.SolrDocument; +import org.testng.annotations.Test; + +import brooklyn.entity.basic.Entities; +import brooklyn.entity.proxying.EntitySpec; +import brooklyn.entity.trait.Startable; +import brooklyn.test.EntityTestUtils; +import brooklyn.util.collections.MutableMap; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; + +/** + * Solr integration tests. + * + * Test the operation of the {@link SolrServer} class. + */ +public class SolrServerIntegrationTest extends AbstractSolrServerTest { + + /** + * Test that a node starts and sets SERVICE_UP correctly. + */ + @Test(groups = "Integration") + public void canStartupAndShutdown() { + solr = app.createAndManageChild(EntitySpec.create(SolrServer.class)); + app.start(ImmutableList.of(testLocation)); + + EntityTestUtils.assertAttributeEqualsEventually(solr, Startable.SERVICE_UP, true); + Entities.dumpInfo(app); + + solr.stop(); + + EntityTestUtils.assertAttributeEqualsEventually(solr, Startable.SERVICE_UP, false); + } + + /** + * Test that a core can be created and used with SolrJ client. + */ + @Test(groups = "Integration") + public void testConnection() throws Exception { + solr = app.createAndManageChild(EntitySpec.create(SolrServer.class) + .configure(SolrServer.SOLR_CORE_CONFIG, ImmutableMap.of("example", "classpath://solr/example.tgz"))); + app.start(ImmutableList.of(testLocation)); + + EntityTestUtils.assertAttributeEqualsEventually(solr, Startable.SERVICE_UP, true); + + SolrJSupport client = new SolrJSupport(solr, "example"); + + Iterable<SolrDocument> results = client.getDocuments(); + assertTrue(Iterables.isEmpty(results)); + + client.addDocument(MutableMap.<String, Object>of("id", "1", "description", "first")); + client.addDocument(MutableMap.<String, Object>of("id", "2", "description", "second")); + client.addDocument(MutableMap.<String, Object>of("id", "3", "description", "third")); + client.commit(); + + results = client.getDocuments(); + assertEquals(Iterables.size(results), 3); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/solr/SolrServerLiveTest.java ---------------------------------------------------------------------- diff --git a/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/solr/SolrServerLiveTest.java b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/solr/SolrServerLiveTest.java new file mode 100644 index 0000000..d9fc27f --- /dev/null +++ b/software/nosql/src/test/java/org/apache/brooklyn/entity/nosql/solr/SolrServerLiveTest.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.brooklyn.entity.nosql.solr; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; + +import java.util.Map; + +import org.apache.brooklyn.entity.nosql.solr.SolrServer; +import org.apache.solr.common.SolrDocument; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import brooklyn.entity.proxying.EntitySpec; +import brooklyn.entity.trait.Startable; +import brooklyn.test.EntityTestUtils; +import brooklyn.util.collections.MutableMap; +import brooklyn.util.text.Strings; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; + +/** + * Solr live tests. + * + * Test the operation of the {@link SolrServer} class using the jclouds {@code rackspace-cloudservers-uk} + * and {@code aws-ec2} providers, with different OS images. The tests use the {@link SolrJSupport} class + * to exercise the node, and will need to have {@code brooklyn.jclouds.provider.identity} and {@code .credential} + * set, usually in the {@code .brooklyn/brooklyn.properties} file. + */ +public class SolrServerLiveTest extends AbstractSolrServerTest { + + private static final Logger log = LoggerFactory.getLogger(SolrServerLiveTest.class); + + @DataProvider(name = "virtualMachineData") + public Object[][] provideVirtualMachineData() { + return new Object[][] { // ImageId, Provider, Region, Description (for logging) + new Object[] { "eu-west-1/ami-0307d674", "aws-ec2", "eu-west-1", "Ubuntu Server 14.04 LTS (HVM), SSD Volume Type" }, + new Object[] { "LON/f9b690bf-88eb-43c2-99cf-391f2558732e", "rackspace-cloudservers-uk", "", "Ubuntu 12.04 LTS (Precise Pangolin)" }, + new Object[] { "LON/a84b1592-6817-42da-a57c-3c13f3cfc1da", "rackspace-cloudservers-uk", "", "CentOS 6.5 (PVHVM)" }, + }; + } + + @Test(groups = "Live", dataProvider = "virtualMachineData") + protected void testOperatingSystemProvider(String imageId, String provider, String region, String description) throws Exception { + log.info("Testing Solr on {}{} using {} ({})", new Object[] { provider, Strings.isNonEmpty(region) ? ":" + region : "", description, imageId }); + + Map<String, String> properties = MutableMap.of("imageId", imageId); + testLocation = app.getManagementContext().getLocationRegistry() + .resolve(provider + (Strings.isNonEmpty(region) ? ":" + region : ""), properties); + solr = app.createAndManageChild(EntitySpec.create(SolrServer.class) + .configure(SolrServer.SOLR_CORE_CONFIG, ImmutableMap.of("example", "classpath://solr/example.tgz"))); + app.start(ImmutableList.of(testLocation)); + + EntityTestUtils.assertAttributeEqualsEventually(solr, Startable.SERVICE_UP, true); + + SolrJSupport client = new SolrJSupport(solr, "example"); + + Iterable<SolrDocument> results = client.getDocuments(); + assertTrue(Iterables.isEmpty(results)); + + client.addDocument(MutableMap.<String, Object>of("id", "1", "description", "first")); + client.addDocument(MutableMap.<String, Object>of("id", "2", "description", "second")); + client.addDocument(MutableMap.<String, Object>of("id", "3", "description", "third")); + client.commit(); + + results = client.getDocuments(); + assertEquals(Iterables.size(results), 3); + } +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/usage/cli/src/main/resources/brooklyn/default.catalog.bom ---------------------------------------------------------------------- diff --git a/usage/cli/src/main/resources/brooklyn/default.catalog.bom b/usage/cli/src/main/resources/brooklyn/default.catalog.bom index 9cc4afd..839662a 100644 --- a/usage/cli/src/main/resources/brooklyn/default.catalog.bom +++ b/usage/cli/src/main/resources/brooklyn/default.catalog.bom @@ -183,7 +183,7 @@ brooklyn.catalog: $brooklyn:entity("riak-cluster").attributeWhenReady("main.uri")) # use the off-the-shelf Riak cluster - - type: brooklyn.entity.nosql.riak.RiakCluster + - type: org.apache.brooklyn.entity.nosql.riak.RiakCluster id: riak-cluster initialSize: 3 # and add a policy to scale based on ops per minute http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/usage/launcher/src/test/resources/cassandra-blueprint.yaml ---------------------------------------------------------------------- diff --git a/usage/launcher/src/test/resources/cassandra-blueprint.yaml b/usage/launcher/src/test/resources/cassandra-blueprint.yaml index 3af6e7b..1b08802 100644 --- a/usage/launcher/src/test/resources/cassandra-blueprint.yaml +++ b/usage/launcher/src/test/resources/cassandra-blueprint.yaml @@ -18,7 +18,7 @@ # name: cassandra-cluster-app services: -- type: brooklyn.entity.nosql.cassandra.CassandraCluster +- type: org.apache.brooklyn.entity.nosql.cassandra.CassandraCluster name: Cassandra Cluster brooklyn.config: cluster.initial.size: 5 http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/usage/launcher/src/test/resources/couchbase-cluster-singleNode.yaml ---------------------------------------------------------------------- diff --git a/usage/launcher/src/test/resources/couchbase-cluster-singleNode.yaml b/usage/launcher/src/test/resources/couchbase-cluster-singleNode.yaml index f40c779..f1f426c 100644 --- a/usage/launcher/src/test/resources/couchbase-cluster-singleNode.yaml +++ b/usage/launcher/src/test/resources/couchbase-cluster-singleNode.yaml @@ -21,7 +21,7 @@ name: Couchbase One Bucket location: softlayer:wdc01 services: -- type: brooklyn.entity.nosql.couchbase.CouchbaseCluster +- type: org.apache.brooklyn.entity.nosql.couchbase.CouchbaseCluster initialSize: 1 intialQuorumSize: 1 adminUsername: Administrator http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/usage/launcher/src/test/resources/couchbase-cluster.yaml ---------------------------------------------------------------------- diff --git a/usage/launcher/src/test/resources/couchbase-cluster.yaml b/usage/launcher/src/test/resources/couchbase-cluster.yaml index b85884b..48fbc90 100644 --- a/usage/launcher/src/test/resources/couchbase-cluster.yaml +++ b/usage/launcher/src/test/resources/couchbase-cluster.yaml @@ -21,7 +21,7 @@ name: Couchbase One Bucket location: softlayer:wdc01 services: -- type: brooklyn.entity.nosql.couchbase.CouchbaseCluster +- type: org.apache.brooklyn.entity.nosql.couchbase.CouchbaseCluster initialSize: 3 intialQuorumSize: 2 adminUsername: Administrator http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/d5cf5285/usage/launcher/src/test/resources/couchbase-node.yaml ---------------------------------------------------------------------- diff --git a/usage/launcher/src/test/resources/couchbase-node.yaml b/usage/launcher/src/test/resources/couchbase-node.yaml index 63a6348..01db0a8 100644 --- a/usage/launcher/src/test/resources/couchbase-node.yaml +++ b/usage/launcher/src/test/resources/couchbase-node.yaml @@ -21,6 +21,6 @@ name: Couchbase Node location: softlayer:wdc01 services: -- type: brooklyn.entity.nosql.couchbase.CouchbaseNode +- type: org.apache.brooklyn.entity.nosql.couchbase.CouchbaseNode adminUsername: Administrator adminPassword: Password
