From 4b1c664bcd7ee822fb74c37c5c24f9b669985d02 Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Fri, 13 Jul 2012 16:07:59 -0700 Subject: [PATCH 1/2] * abstract ChaosMonkey and Selection interface, moved impl to basic/chaos. fix #1 --- .../java/com/netflix/simianarmy/Monkey.java | 4 ++ .../com/netflix/simianarmy/MonkeyRunner.java | 37 +++++++++--- .../simianarmy/basic/BasicContext.java | 5 +- .../simianarmy/basic/BasicMonkeyServer.java | 6 +- .../basic/{ => chaos}/BasicChaosCrawler.java | 4 +- .../chaos/BasicChaosInstanceSelector.java} | 5 +- .../chaos/BasicChaosMonkey.java} | 59 ++++++------------- .../{ => chaos}/TestBasicChaosCrawler.java | 2 +- .../TestBasicChaosInstanceSelector.java} | 9 +-- .../chaos/TestBasicChaosMonkey.java} | 27 +++++---- .../chaos/TestBasicChaosMonkeyServlet.java} | 15 +++-- .../chaos/TestChaosMonkeyContext.java | 5 +- .../chaos/getChaosEventsResponse.json | 0 13 files changed, 96 insertions(+), 82 deletions(-) rename src/main/java/com/netflix/simianarmy/basic/{ => chaos}/BasicChaosCrawler.java (98%) rename src/main/java/com/netflix/simianarmy/{chaos/ChaosInstanceSelector.java => basic/chaos/BasicChaosInstanceSelector.java} (90%) rename src/main/java/com/netflix/simianarmy/{chaos/ChaosMonkey.java => basic/chaos/BasicChaosMonkey.java} (82%) rename src/test/java/com/netflix/simianarmy/basic/{ => chaos}/TestBasicChaosCrawler.java (98%) rename src/test/java/com/netflix/simianarmy/{chaos/TestChaosInstanceSelector.java => basic/chaos/TestBasicChaosInstanceSelector.java} (93%) rename src/test/java/com/netflix/simianarmy/{chaos/TestChaosMonkey.java => basic/chaos/TestBasicChaosMonkey.java} (92%) rename src/test/java/com/netflix/simianarmy/{chaos/TestChaosMonkeyServlet.java => basic/chaos/TestBasicChaosMonkeyServlet.java} (89%) rename src/test/resources/com/netflix/simianarmy/{ => basic}/chaos/getChaosEventsResponse.json (100%) diff --git a/src/main/java/com/netflix/simianarmy/Monkey.java b/src/main/java/com/netflix/simianarmy/Monkey.java index d7b76b00..23fc25a5 100644 --- a/src/main/java/com/netflix/simianarmy/Monkey.java +++ b/src/main/java/com/netflix/simianarmy/Monkey.java @@ -43,6 +43,10 @@ public Monkey(Context ctx) { public abstract void doMonkeyBusiness(); + public Context context() { + return ctx; + } + public void start() { final Monkey me = this; ctx.scheduler().start(type().name(), new Runnable() { diff --git a/src/main/java/com/netflix/simianarmy/MonkeyRunner.java b/src/main/java/com/netflix/simianarmy/MonkeyRunner.java index 7772c561..1cb586a1 100644 --- a/src/main/java/com/netflix/simianarmy/MonkeyRunner.java +++ b/src/main/java/com/netflix/simianarmy/MonkeyRunner.java @@ -88,7 +88,8 @@ public void replaceMonkey(Class monkeyClass, Class monkeyClass) { @@ -101,12 +102,22 @@ public void removeMonkey(Class monkeyClass) { break; } } - monkeyMap.remove(monkeyClass); } public T factory(Class monkeyClass) { - return factory(monkeyClass, getContextClass(monkeyClass)); + Class ctxClass = getContextClass(monkeyClass); + if (ctxClass == null) { + // look for derived class already in our map + for (Map.Entry, Class> pair : monkeyMap.entrySet()) { + if (monkeyClass.isAssignableFrom(pair.getKey())) { + @SuppressWarnings("unchecked") + T monkey = (T) factory(pair.getKey(), pair.getValue()); + return monkey; + } + } + } + return factory(monkeyClass, ctxClass); } public T factory(Class monkeyClass, Class contextClass) { @@ -115,14 +126,22 @@ public T factory(Class monkeyClass, Class ctor = monkeyClass.getDeclaredConstructor(ctorArgClass); - return ctor.newInstance(contextClass.newInstance()); + for (Constructor ctor : monkeyClass.getDeclaredConstructors()) { + Class[] paramTypes = ctor.getParameterTypes(); + if (paramTypes.length != 1) { + continue; + } + if (paramTypes[0].getName().endsWith("$Context")) { + @SuppressWarnings("unchecked") + T monkey = (T) ctor.newInstance(contextClass.newInstance()); + return monkey; + } + } } catch (Exception e) { - LOGGER.error("monkeyFactory error: ", e); + LOGGER.error("monkeyFactory error, cannot make monkey from " + monkeyClass.getName() + " with " + + (contextClass == null ? null : contextClass.getName()), e); } return null; diff --git a/src/main/java/com/netflix/simianarmy/basic/BasicContext.java b/src/main/java/com/netflix/simianarmy/basic/BasicContext.java index 1c81dc18..853ad5d0 100644 --- a/src/main/java/com/netflix/simianarmy/basic/BasicContext.java +++ b/src/main/java/com/netflix/simianarmy/basic/BasicContext.java @@ -32,6 +32,9 @@ import com.netflix.simianarmy.aws.AWSClient; import com.netflix.simianarmy.aws.SimpleDBRecorder; +import com.netflix.simianarmy.basic.chaos.BasicChaosCrawler; +import com.netflix.simianarmy.basic.chaos.BasicChaosInstanceSelector; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -72,7 +75,7 @@ public BasicContext() { client = new AWSClient(account, secret, region); scheduler = new BasicScheduler((int) config.getNumOrElse("monkey.threads", MONKEY_THREADS)); crawler = new BasicChaosCrawler(client); - selector = new ChaosInstanceSelector(); + selector = new BasicChaosInstanceSelector(); String domain = config.getStrOrElse("domain", "SIMIAN_ARMY"); recorder = new SimpleDBRecorder(account, secret, region, domain); } diff --git a/src/main/java/com/netflix/simianarmy/basic/BasicMonkeyServer.java b/src/main/java/com/netflix/simianarmy/basic/BasicMonkeyServer.java index 36522db2..1c4f81d0 100644 --- a/src/main/java/com/netflix/simianarmy/basic/BasicMonkeyServer.java +++ b/src/main/java/com/netflix/simianarmy/basic/BasicMonkeyServer.java @@ -24,7 +24,7 @@ import org.slf4j.LoggerFactory; import com.netflix.simianarmy.MonkeyRunner; -import com.netflix.simianarmy.chaos.ChaosMonkey; +import com.netflix.simianarmy.basic.chaos.BasicChaosMonkey; @SuppressWarnings("serial") public class BasicMonkeyServer extends HttpServlet { @@ -34,14 +34,14 @@ public class BasicMonkeyServer extends HttpServlet { @Override public void init() throws ServletException { super.init(); - RUNNER.replaceMonkey(ChaosMonkey.class, BasicContext.class); + RUNNER.replaceMonkey(BasicChaosMonkey.class, BasicContext.class); RUNNER.start(); } @Override public void destroy() { RUNNER.stop(); - RUNNER.removeMonkey(ChaosMonkey.class); + RUNNER.removeMonkey(BasicChaosMonkey.class); super.destroy(); } } diff --git a/src/main/java/com/netflix/simianarmy/basic/BasicChaosCrawler.java b/src/main/java/com/netflix/simianarmy/basic/chaos/BasicChaosCrawler.java similarity index 98% rename from src/main/java/com/netflix/simianarmy/basic/BasicChaosCrawler.java rename to src/main/java/com/netflix/simianarmy/basic/chaos/BasicChaosCrawler.java index 15a416c1..c11cca93 100644 --- a/src/main/java/com/netflix/simianarmy/basic/BasicChaosCrawler.java +++ b/src/main/java/com/netflix/simianarmy/basic/chaos/BasicChaosCrawler.java @@ -15,7 +15,7 @@ * limitations under the License. * */ -package com.netflix.simianarmy.basic; +package com.netflix.simianarmy.basic.chaos; import java.util.List; import java.util.LinkedList; @@ -43,7 +43,7 @@ public BasicChaosCrawler(AWSClient awsClient) { public static class BasicInstanceGroup implements InstanceGroup { private final String name; private final Enum type; - + public BasicInstanceGroup(String name) { this.name = name; this.type = Types.ASG; diff --git a/src/main/java/com/netflix/simianarmy/chaos/ChaosInstanceSelector.java b/src/main/java/com/netflix/simianarmy/basic/chaos/BasicChaosInstanceSelector.java similarity index 90% rename from src/main/java/com/netflix/simianarmy/chaos/ChaosInstanceSelector.java rename to src/main/java/com/netflix/simianarmy/basic/chaos/BasicChaosInstanceSelector.java index 4ebbe1d1..60745796 100644 --- a/src/main/java/com/netflix/simianarmy/chaos/ChaosInstanceSelector.java +++ b/src/main/java/com/netflix/simianarmy/basic/chaos/BasicChaosInstanceSelector.java @@ -15,16 +15,17 @@ * limitations under the License. * */ -package com.netflix.simianarmy.chaos; +package com.netflix.simianarmy.basic.chaos; import java.util.Random; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.netflix.simianarmy.chaos.ChaosInstanceSelector; import com.netflix.simianarmy.chaos.ChaosCrawler.InstanceGroup; -public class ChaosInstanceSelector { +public class BasicChaosInstanceSelector implements ChaosInstanceSelector { private static final Logger LOGGER = LoggerFactory.getLogger(ChaosInstanceSelector.class); private static final Random RANDOM = new Random(); diff --git a/src/main/java/com/netflix/simianarmy/chaos/ChaosMonkey.java b/src/main/java/com/netflix/simianarmy/basic/chaos/BasicChaosMonkey.java similarity index 82% rename from src/main/java/com/netflix/simianarmy/chaos/ChaosMonkey.java rename to src/main/java/com/netflix/simianarmy/basic/chaos/BasicChaosMonkey.java index 3ef85f8f..910a367d 100644 --- a/src/main/java/com/netflix/simianarmy/chaos/ChaosMonkey.java +++ b/src/main/java/com/netflix/simianarmy/basic/chaos/BasicChaosMonkey.java @@ -15,10 +15,13 @@ * limitations under the License. * */ -package com.netflix.simianarmy.chaos; +package com.netflix.simianarmy.basic.chaos; -import com.netflix.simianarmy.Monkey; +import com.netflix.simianarmy.chaos.ChaosMonkey; import com.netflix.simianarmy.MonkeyConfiguration; +import com.netflix.simianarmy.MonkeyRunner; +import com.netflix.simianarmy.MonkeyRecorder.Event; +import com.netflix.simianarmy.chaos.ChaosCrawler.InstanceGroup; import java.util.Map; import java.util.HashMap; @@ -32,13 +35,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.netflix.simianarmy.MonkeyRunner; -import com.netflix.simianarmy.MonkeyRecorder.Event; -import com.netflix.simianarmy.chaos.ChaosCrawler.InstanceGroup; - import javax.ws.rs.GET; import javax.ws.rs.Path; -import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; @@ -46,25 +44,16 @@ import org.codehaus.jackson.JsonGenerator; import org.codehaus.jackson.map.MappingJsonFactory; -public class ChaosMonkey extends Monkey { +public class BasicChaosMonkey extends ChaosMonkey { private static final Logger LOGGER = LoggerFactory.getLogger(ChaosMonkey.class); private static final String NS = "simianarmy.chaos."; - public interface Context extends Monkey.Context { - MonkeyConfiguration configuration(); - - ChaosCrawler chaosCrawler(); - - ChaosInstanceSelector chaosInstanceSelector(); - } - - private Context ctx; private MonkeyConfiguration cfg; private long runsPerDay; - public ChaosMonkey(Context ctx) { + public BasicChaosMonkey(ChaosMonkey.Context ctx) { super(ctx); - this.ctx = ctx; + this.cfg = ctx.configuration(); Calendar open = ctx.calendar().now(); @@ -77,18 +66,6 @@ public ChaosMonkey(Context ctx) { runsPerDay = units / ctx.scheduler().frequency(); } - public enum Type { - CHAOS - } - - public Enum type() { - return Type.CHAOS; - } - - public enum EventTypes { - CHAOS_TERMINATION - } - public void doMonkeyBusiness() { cfg.reload(); String prop = NS + "enabled"; @@ -97,13 +74,13 @@ public void doMonkeyBusiness() { return; } - for (InstanceGroup group : ctx.chaosCrawler().groups()) { + for (InstanceGroup group : context().chaosCrawler().groups()) { prop = NS + group.type() + "." + group.name() + ".enabled"; String defaultProp = NS + group.type(); if (cfg.getBoolOrElse(prop, cfg.getBool(defaultProp + ".enabled"))) { String probProp = NS + group.type() + "." + group.name() + ".probability"; double prob = cfg.getNumOrElse(probProp, cfg.getNumOrElse(defaultProp + ".probability", 1.0)); - String inst = ctx.chaosInstanceSelector().select(group, prob / runsPerDay); + String inst = context().chaosInstanceSelector().select(group, prob / runsPerDay); if (inst != null) { prop = NS + "leashed"; if (cfg.getBoolOrElse(prop, true)) { @@ -116,7 +93,7 @@ public void doMonkeyBusiness() { } try { recordTermination(group, inst); - ctx.cloudClient().terminateInstance(inst); + context().cloudClient().terminateInstance(inst); } catch (Exception e) { handleTerminationError(inst, e); } @@ -135,7 +112,7 @@ protected void handleTerminationError(String instance, Throwable e) { throw new RuntimeException("failed to terminate instance " + instance, e); } - protected boolean hasPreviousTerminations(InstanceGroup group) { + public boolean hasPreviousTerminations(InstanceGroup group) { Map query = new HashMap(); query.put("groupType", group.type().name()); query.put("groupName", group.name()); @@ -145,15 +122,16 @@ protected boolean hasPreviousTerminations(InstanceGroup group) { today.set(Calendar.MINUTE, 0); today.set(Calendar.SECOND, 0); today.set(Calendar.MILLISECOND, 0); - List evts = ctx.recorder().findEvents(Type.CHAOS, EventTypes.CHAOS_TERMINATION, query, today.getTime()); + List evts = context().recorder().findEvents(Type.CHAOS, EventTypes.CHAOS_TERMINATION, query, + today.getTime()); return !evts.isEmpty(); } - protected void recordTermination(InstanceGroup group, String instance) { - Event evt = ctx.recorder().newEvent(Type.CHAOS, EventTypes.CHAOS_TERMINATION, instance); + public void recordTermination(InstanceGroup group, String instance) { + Event evt = context().recorder().newEvent(Type.CHAOS, EventTypes.CHAOS_TERMINATION, instance); evt.addField("groupType", group.type().name()); evt.addField("groupName", group.name()); - ctx.recorder().recordEvent(evt); + context().recorder().recordEvent(evt); } @Path("/chaos") @@ -178,7 +156,8 @@ public Response getChaosEvents(@javax.ws.rs.core.Context UriInfo uriInfo) throws } } - List evts = monkey.ctx.recorder().findEvents(Type.CHAOS, EventTypes.CHAOS_TERMINATION, query, date); + List evts = monkey.context().recorder() + .findEvents(Type.CHAOS, EventTypes.CHAOS_TERMINATION, query, date); ByteArrayOutputStream baos = new ByteArrayOutputStream(); JsonGenerator gen = JSON_FACTORY.createJsonGenerator(baos, JsonEncoding.UTF8); diff --git a/src/test/java/com/netflix/simianarmy/basic/TestBasicChaosCrawler.java b/src/test/java/com/netflix/simianarmy/basic/chaos/TestBasicChaosCrawler.java similarity index 98% rename from src/test/java/com/netflix/simianarmy/basic/TestBasicChaosCrawler.java rename to src/test/java/com/netflix/simianarmy/basic/chaos/TestBasicChaosCrawler.java index ab7e0ba9..0dd72200 100644 --- a/src/test/java/com/netflix/simianarmy/basic/TestBasicChaosCrawler.java +++ b/src/test/java/com/netflix/simianarmy/basic/chaos/TestBasicChaosCrawler.java @@ -15,7 +15,7 @@ * limitations under the License. * */ -package com.netflix.simianarmy.basic; +package com.netflix.simianarmy.basic.chaos; import org.testng.annotations.Test; import org.testng.Assert; diff --git a/src/test/java/com/netflix/simianarmy/chaos/TestChaosInstanceSelector.java b/src/test/java/com/netflix/simianarmy/basic/chaos/TestBasicChaosInstanceSelector.java similarity index 93% rename from src/test/java/com/netflix/simianarmy/chaos/TestChaosInstanceSelector.java rename to src/test/java/com/netflix/simianarmy/basic/chaos/TestBasicChaosInstanceSelector.java index 3c2f1a0d..7adfb23f 100644 --- a/src/test/java/com/netflix/simianarmy/chaos/TestChaosInstanceSelector.java +++ b/src/test/java/com/netflix/simianarmy/basic/chaos/TestBasicChaosInstanceSelector.java @@ -15,12 +15,13 @@ * limitations under the License. * */ -package com.netflix.simianarmy.chaos; +package com.netflix.simianarmy.basic.chaos; import java.util.List; import java.util.Arrays; import java.util.Map; import java.util.HashMap; +import com.netflix.simianarmy.chaos.ChaosInstanceSelector; import com.netflix.simianarmy.chaos.ChaosCrawler.InstanceGroup; import org.testng.annotations.Test; @@ -31,9 +32,9 @@ import static org.slf4j.helpers.NOPLogger.NOP_LOGGER; // CHECKSTYLE IGNORE MagicNumberCheck -public class TestChaosInstanceSelector { - private ChaosInstanceSelector selector = new ChaosInstanceSelector() { - // turn off selector logger for this test since we call is ~1m times +public class TestBasicChaosInstanceSelector { + private ChaosInstanceSelector selector = new BasicChaosInstanceSelector() { + // turn off selector logger for this test since we call it ~1M times protected Logger logger() { return NOP_LOGGER; } diff --git a/src/test/java/com/netflix/simianarmy/chaos/TestChaosMonkey.java b/src/test/java/com/netflix/simianarmy/basic/chaos/TestBasicChaosMonkey.java similarity index 92% rename from src/test/java/com/netflix/simianarmy/chaos/TestChaosMonkey.java rename to src/test/java/com/netflix/simianarmy/basic/chaos/TestBasicChaosMonkey.java index d0c36e25..361f60e1 100644 --- a/src/test/java/com/netflix/simianarmy/chaos/TestChaosMonkey.java +++ b/src/test/java/com/netflix/simianarmy/basic/chaos/TestBasicChaosMonkey.java @@ -15,20 +15,23 @@ * limitations under the License. * */ -package com.netflix.simianarmy.chaos; +package com.netflix.simianarmy.basic.chaos; import java.util.List; +import com.netflix.simianarmy.chaos.ChaosMonkey; import com.netflix.simianarmy.chaos.ChaosCrawler.InstanceGroup; +import com.netflix.simianarmy.chaos.TestChaosMonkeyContext; + import org.testng.annotations.Test; import org.testng.Assert; // CHECKSTYLE IGNORE MagicNumberCheck -public class TestChaosMonkey { +public class TestBasicChaosMonkey { @Test public void testDisabled() { TestChaosMonkeyContext ctx = new TestChaosMonkeyContext("disabled.properties"); - ChaosMonkey chaos = new ChaosMonkey(ctx); + ChaosMonkey chaos = new BasicChaosMonkey(ctx); chaos.start(); chaos.stop(); List selectedOn = ctx.selectedOn(); @@ -40,7 +43,7 @@ public void testDisabled() { @Test public void testEnabledA() { TestChaosMonkeyContext ctx = new TestChaosMonkeyContext("enabledA.properties"); - ChaosMonkey chaos = new ChaosMonkey(ctx); + ChaosMonkey chaos = new BasicChaosMonkey(ctx); chaos.start(); chaos.stop(); List selectedOn = ctx.selectedOn(); @@ -56,7 +59,7 @@ public void testEnabledA() { @Test public void testUnleashedEnabledA() { TestChaosMonkeyContext ctx = new TestChaosMonkeyContext("unleashedEnabledA.properties"); - ChaosMonkey chaos = new ChaosMonkey(ctx); + ChaosMonkey chaos = new BasicChaosMonkey(ctx); chaos.start(); chaos.stop(); List selectedOn = ctx.selectedOn(); @@ -74,7 +77,7 @@ public void testUnleashedEnabledA() { @Test public void testEnabledB() { TestChaosMonkeyContext ctx = new TestChaosMonkeyContext("enabledB.properties"); - ChaosMonkey chaos = new ChaosMonkey(ctx); + ChaosMonkey chaos = new BasicChaosMonkey(ctx); chaos.start(); chaos.stop(); List selectedOn = ctx.selectedOn(); @@ -90,7 +93,7 @@ public void testEnabledB() { @Test public void testUnleashedEnabledB() { TestChaosMonkeyContext ctx = new TestChaosMonkeyContext("unleashedEnabledB.properties"); - ChaosMonkey chaos = new ChaosMonkey(ctx); + ChaosMonkey chaos = new BasicChaosMonkey(ctx); chaos.start(); chaos.stop(); List selectedOn = ctx.selectedOn(); @@ -108,7 +111,7 @@ public void testUnleashedEnabledB() { @Test public void testEnabledAwithout1() { TestChaosMonkeyContext ctx = new TestChaosMonkeyContext("enabledAwithout1.properties"); - ChaosMonkey chaos = new ChaosMonkey(ctx); + ChaosMonkey chaos = new BasicChaosMonkey(ctx); chaos.start(); chaos.stop(); List selectedOn = ctx.selectedOn(); @@ -123,7 +126,7 @@ public void testEnabledAwithout1() { @Test public void testEnabledAwith0() { TestChaosMonkeyContext ctx = new TestChaosMonkeyContext("enabledAwith0.properties"); - ChaosMonkey chaos = new ChaosMonkey(ctx); + ChaosMonkey chaos = new BasicChaosMonkey(ctx); chaos.start(); chaos.stop(); List selectedOn = ctx.selectedOn(); @@ -138,7 +141,7 @@ public void testEnabledAwith0() { @Test public void testAll() { TestChaosMonkeyContext ctx = new TestChaosMonkeyContext("all.properties"); - ChaosMonkey chaos = new ChaosMonkey(ctx); + ChaosMonkey chaos = new BasicChaosMonkey(ctx); chaos.start(); chaos.stop(); List selectedOn = ctx.selectedOn(); @@ -162,7 +165,7 @@ public void testAll() { @Test public void testNoProbability() { TestChaosMonkeyContext ctx = new TestChaosMonkeyContext("noProbability.properties"); - ChaosMonkey chaos = new ChaosMonkey(ctx); + ChaosMonkey chaos = new BasicChaosMonkey(ctx); chaos.start(); chaos.stop(); List selectedOn = ctx.selectedOn(); @@ -182,7 +185,7 @@ public void testNoProbability() { @Test public void testNoProbabilityByName() { TestChaosMonkeyContext ctx = new TestChaosMonkeyContext("noProbabilityByName.properties"); - ChaosMonkey chaos = new ChaosMonkey(ctx); + ChaosMonkey chaos = new BasicChaosMonkey(ctx); chaos.start(); chaos.stop(); List selectedOn = ctx.selectedOn(); diff --git a/src/test/java/com/netflix/simianarmy/chaos/TestChaosMonkeyServlet.java b/src/test/java/com/netflix/simianarmy/basic/chaos/TestBasicChaosMonkeyServlet.java similarity index 89% rename from src/test/java/com/netflix/simianarmy/chaos/TestChaosMonkeyServlet.java rename to src/test/java/com/netflix/simianarmy/basic/chaos/TestBasicChaosMonkeyServlet.java index ef2eeb93..e0715e7f 100644 --- a/src/test/java/com/netflix/simianarmy/chaos/TestChaosMonkeyServlet.java +++ b/src/test/java/com/netflix/simianarmy/basic/chaos/TestBasicChaosMonkeyServlet.java @@ -15,7 +15,7 @@ * limitations under the License. * */ -package com.netflix.simianarmy.chaos; +package com.netflix.simianarmy.basic.chaos; import java.util.Arrays; import java.util.Date; @@ -42,13 +42,16 @@ import com.netflix.simianarmy.MonkeyRunner; import com.netflix.simianarmy.MonkeyRecorder; +import com.netflix.simianarmy.chaos.ChaosMonkey; import com.netflix.simianarmy.basic.BasicRecorderEvent; +import com.netflix.simianarmy.chaos.TestChaosMonkeyContext; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class TestChaosMonkeyServlet { - private static final Logger LOGGER = LoggerFactory.getLogger(TestChaosMonkey.class); +public class TestBasicChaosMonkeyServlet { + private static final Logger LOGGER = LoggerFactory.getLogger(TestBasicChaosMonkeyServlet.class); @Captor private ArgumentCaptor monkeyTypeArg; @@ -71,9 +74,9 @@ public void init() { @Test public void testServlet() { - MonkeyRunner.getInstance().replaceMonkey(ChaosMonkey.class, MockTestChaosMonkeyContext.class); + MonkeyRunner.getInstance().replaceMonkey(BasicChaosMonkey.class, MockTestChaosMonkeyContext.class); - ChaosMonkey.Servlet servlet = new ChaosMonkey.Servlet(); + BasicChaosMonkey.Servlet servlet = new BasicChaosMonkey.Servlet(); MultivaluedMap queryParams = new MultivaluedMapImpl(); queryParams.add("groupType", "ASG"); @@ -124,6 +127,6 @@ public MonkeyRecorder recorder() { String getResource(String name) { // get resource as stream, use Scanner to read stream as one token - return new Scanner(TestChaosMonkey.class.getResourceAsStream(name), "UTF-8").useDelimiter("\\A").next(); + return new Scanner(TestBasicChaosMonkey.class.getResourceAsStream(name), "UTF-8").useDelimiter("\\A").next(); } } diff --git a/src/test/java/com/netflix/simianarmy/chaos/TestChaosMonkeyContext.java b/src/test/java/com/netflix/simianarmy/chaos/TestChaosMonkeyContext.java index 1410499b..31917b90 100644 --- a/src/test/java/com/netflix/simianarmy/chaos/TestChaosMonkeyContext.java +++ b/src/test/java/com/netflix/simianarmy/chaos/TestChaosMonkeyContext.java @@ -19,9 +19,10 @@ import com.netflix.simianarmy.TestMonkeyContext; import com.netflix.simianarmy.MonkeyConfiguration; -import com.netflix.simianarmy.basic.BasicConfiguration; import com.netflix.simianarmy.CloudClient; import com.netflix.simianarmy.chaos.ChaosCrawler.InstanceGroup; +import com.netflix.simianarmy.basic.BasicConfiguration; +import com.netflix.simianarmy.basic.chaos.BasicChaosInstanceSelector; import java.util.Properties; import java.io.InputStream; @@ -117,7 +118,7 @@ public List selectedOn() { } public ChaosInstanceSelector chaosInstanceSelector() { - return new ChaosInstanceSelector() { + return new BasicChaosInstanceSelector() { public String select(InstanceGroup group, double probability) { selectedOn.add(group); return super.select(group, probability); diff --git a/src/test/resources/com/netflix/simianarmy/chaos/getChaosEventsResponse.json b/src/test/resources/com/netflix/simianarmy/basic/chaos/getChaosEventsResponse.json similarity index 100% rename from src/test/resources/com/netflix/simianarmy/chaos/getChaosEventsResponse.json rename to src/test/resources/com/netflix/simianarmy/basic/chaos/getChaosEventsResponse.json From d7bca958e5d76b5c6a3da2c10b50a4fc7953e4c8 Mon Sep 17 00:00:00 2001 From: Cory Bennett Date: Fri, 13 Jul 2012 16:19:54 -0700 Subject: [PATCH 2/2] * adding missing interfaces from previous commit --- .../chaos/ChaosInstanceSelector.java | 24 ++++++++ .../netflix/simianarmy/chaos/ChaosMonkey.java | 61 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 src/main/java/com/netflix/simianarmy/chaos/ChaosInstanceSelector.java create mode 100644 src/main/java/com/netflix/simianarmy/chaos/ChaosMonkey.java diff --git a/src/main/java/com/netflix/simianarmy/chaos/ChaosInstanceSelector.java b/src/main/java/com/netflix/simianarmy/chaos/ChaosInstanceSelector.java new file mode 100644 index 00000000..077fff98 --- /dev/null +++ b/src/main/java/com/netflix/simianarmy/chaos/ChaosInstanceSelector.java @@ -0,0 +1,24 @@ +/* + * + * Copyright 2012 Netflix, Inc. + * + * 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 com.netflix.simianarmy.chaos; + +import com.netflix.simianarmy.chaos.ChaosCrawler.InstanceGroup; + +public interface ChaosInstanceSelector { + String select(InstanceGroup group, double probability); +} diff --git a/src/main/java/com/netflix/simianarmy/chaos/ChaosMonkey.java b/src/main/java/com/netflix/simianarmy/chaos/ChaosMonkey.java new file mode 100644 index 00000000..860f273b --- /dev/null +++ b/src/main/java/com/netflix/simianarmy/chaos/ChaosMonkey.java @@ -0,0 +1,61 @@ +/* + * + * Copyright 2012 Netflix, Inc. + * + * 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 com.netflix.simianarmy.chaos; + +import com.netflix.simianarmy.Monkey; +import com.netflix.simianarmy.MonkeyConfiguration; + +public abstract class ChaosMonkey extends Monkey { + + public interface Context extends Monkey.Context { + MonkeyConfiguration configuration(); + + ChaosCrawler chaosCrawler(); + + ChaosInstanceSelector chaosInstanceSelector(); + } + + private Context ctx; + + public ChaosMonkey(Context ctx) { + super(ctx); + this.ctx = ctx; + } + + public enum Type { + CHAOS + } + + public enum EventTypes { + CHAOS_TERMINATION + } + + public final Enum type() { + return Type.CHAOS; + } + + public Context context() { + return ctx; + } + + public abstract void doMonkeyBusiness(); + + public abstract boolean hasPreviousTerminations(ChaosCrawler.InstanceGroup group); + + public abstract void recordTermination(ChaosCrawler.InstanceGroup group, String instance); +}