diff --git a/src/main/java/com/netflix/simianarmy/basic/chaos/BasicChaosMonkey.java b/src/main/java/com/netflix/simianarmy/basic/chaos/BasicChaosMonkey.java index 827f2963..c63f8246 100644 --- a/src/main/java/com/netflix/simianarmy/basic/chaos/BasicChaosMonkey.java +++ b/src/main/java/com/netflix/simianarmy/basic/chaos/BasicChaosMonkey.java @@ -300,13 +300,23 @@ && noTerminationInLastWindow(group, mandatoryTerminationWindowInDays)) { } } propName = "probability"; - String defaultProp = NS + group.type(); - String probProp = NS + group.type() + "." + group.name() + "." + propName; - double prob = cfg.getNumOrElse(probProp, cfg.getNumOrElse(defaultProp + "." + propName, 1.0)); + double prob = getNumFromCfgOrDefault(group, propName, 1.0); LOGGER.info("Group {} [type {}] enabled [prob {}]", new Object[]{group.name(), group.type(), prob}); return prob; } + protected double getNumFromCfgOrDefault(InstanceGroup group, String propName, double defaultValue) { + String defaultProp = String.format("%s%s.%s", NS, group.type(), propName); + String prop = String.format("%s%s.%s.%s", NS, group.type(), group.name(), propName); + return cfg.getNumOrElse(prop, cfg.getNumOrElse(defaultProp, defaultValue)); + } + + protected boolean getBoolFromCfgOrDefault(InstanceGroup group, String propName, boolean defaultValue) { + String defaultProp = String.format("%s%s.%s", NS, group.type(), propName); + String prop = String.format("%s%s.%s.%s", NS, group.type(), group.name(), propName); + return cfg.getBoolOrElse(prop, cfg.getBoolOrElse(defaultProp, defaultValue)); + } + /** * Returns lastOptInTimeInMilliseconds from the .properties file. * @@ -344,11 +354,12 @@ && getPreviousTerminationCount(group, windowStart.getTime()) <= 0) { * @return boolean */ protected boolean isGroupEnabled(InstanceGroup group) { - String prop = NS + group.type() + "." + group.name() + ".enabled"; - String defaultProp = NS + group.type() + ".enabled"; - if (cfg.getBoolOrElse(prop, cfg.getBool(defaultProp))) { + boolean enabled = getBoolFromCfgOrDefault(group, "enabled", false); + if (enabled) { return true; } else { + String prop = NS + group.type() + "." + group.name() + ".enabled"; + String defaultProp = NS + group.type() + ".enabled"; LOGGER.info("Group {} [type {}] disabled, set {}=true or {}=true", new Object[]{group.name(), group.type(), prop, defaultProp}); return false; @@ -417,10 +428,9 @@ private Event terminateInstance(InstanceGroup group, String inst, ChaosType chao protected boolean isMaxTerminationCountExceeded(InstanceGroup group) { Validate.notNull(group); String propName = "maxTerminationsPerDay"; - String defaultProp = String.format("%s%s.%s", NS, group.type(), propName); - String prop = String.format("%s%s.%s.%s", NS, group.type(), group.name(), propName); - double maxTerminationsPerDay = cfg.getNumOrElse(prop, cfg.getNumOrElse(defaultProp, 1.0)); + double maxTerminationsPerDay = getNumFromCfgOrDefault(group, propName, 1.0); if (maxTerminationsPerDay <= MIN_MAX_TERMINATION_COUNT_PER_DAY) { + String prop = String.format("%s%s.%s.%s", NS, group.type(), group.name(), propName); LOGGER.info("ChaosMonkey is configured to not allow any killing from group {} [{}] " + "with max daily count set as {}", new Object[]{group.name(), group.type(), prop}); return true; diff --git a/src/test/java/com/netflix/simianarmy/basic/chaos/TestBasicChaosMonkey.java b/src/test/java/com/netflix/simianarmy/basic/chaos/TestBasicChaosMonkey.java index d2c10ed7..87bc2b73 100644 --- a/src/test/java/com/netflix/simianarmy/basic/chaos/TestBasicChaosMonkey.java +++ b/src/test/java/com/netflix/simianarmy/basic/chaos/TestBasicChaosMonkey.java @@ -23,6 +23,7 @@ import javax.ws.rs.core.Response; +import com.netflix.simianarmy.GroupType; import org.testng.Assert; import org.testng.annotations.Test; @@ -35,6 +36,10 @@ // CHECKSTYLE IGNORE MagicNumberCheck public class TestBasicChaosMonkey { + private enum GroupTypes implements GroupType { + TYPE_A, TYPE_B + }; + @Test public void testDisabled() { TestChaosMonkeyContext ctx = new TestChaosMonkeyContext("disabled.properties"); @@ -353,6 +358,33 @@ public void testMaxTerminationCountPerDayGroupLevel() { Assert.assertEquals(ctx.terminated().size(), 3); } + @Test + public void testGetValueFromCfgWithDefault() { + TestChaosMonkeyContext ctx = new TestChaosMonkeyContext("propertiesWithDefaults.properties"); + BasicChaosMonkey chaos = new BasicChaosMonkey(ctx); + + // named 1 has actual values in config + InstanceGroup named1 = new BasicInstanceGroup("named1", GroupTypes.TYPE_A, "test-dev-1"); + + // named 2 doesn't have values but it's group has values + InstanceGroup named2 = new BasicInstanceGroup("named2", GroupTypes.TYPE_A, "test-dev-1"); + + // named 3 doesn't have values and it's group doesn't have values + InstanceGroup named3 = new BasicInstanceGroup("named3", GroupTypes.TYPE_B, "test-dev-1"); + + Assert.assertEquals(chaos.getBoolFromCfgOrDefault(named1, "enabled", true), false); + Assert.assertEquals(chaos.getNumFromCfgOrDefault(named1, "probability", 3.0), 1.1); + Assert.assertEquals(chaos.getNumFromCfgOrDefault(named1, "maxTerminationsPerDay", 4.0), 2.1); + + Assert.assertEquals(chaos.getBoolFromCfgOrDefault(named2, "enabled", true), true); + Assert.assertEquals(chaos.getNumFromCfgOrDefault(named2, "probability", 3.0), 1.0); + Assert.assertEquals(chaos.getNumFromCfgOrDefault(named2, "maxTerminationsPerDay", 4.0), 2.0); + + Assert.assertEquals(chaos.getBoolFromCfgOrDefault(named3, "enabled", true), true); + Assert.assertEquals(chaos.getNumFromCfgOrDefault(named3, "probability", 3.0), 3.0); + Assert.assertEquals(chaos.getNumFromCfgOrDefault(named3, "maxTerminationsPerDay", 4.0), 4.0); + } + @Test public void testMandatoryTerminationDisabled() { TestChaosMonkeyContext ctx = new TestChaosMonkeyContext("mandatoryTerminationDisabled.properties"); diff --git a/src/test/resources/com/netflix/simianarmy/chaos/propertiesWithDefaults.properties b/src/test/resources/com/netflix/simianarmy/chaos/propertiesWithDefaults.properties new file mode 100644 index 00000000..e22d30be --- /dev/null +++ b/src/test/resources/com/netflix/simianarmy/chaos/propertiesWithDefaults.properties @@ -0,0 +1,7 @@ +simianarmy.chaos.leashed = false +simianarmy.chaos.TYPE_A.enabled = true +simianarmy.chaos.TYPE_A.probability = 1.0 +simianarmy.chaos.TYPE_A.maxTerminationsPerDay = 2.0 +simianarmy.chaos.TYPE_A.named1.enabled = false +simianarmy.chaos.TYPE_A.named1.probability = 1.1 +simianarmy.chaos.TYPE_A.named1.maxTerminationsPerDay = 2.1