diff --git a/src/main/java/com/netflix/simianarmy/basic/chaos/BasicChaosEmailNotifier.java b/src/main/java/com/netflix/simianarmy/basic/chaos/BasicChaosEmailNotifier.java index 29f10b7d..9f194301 100644 --- a/src/main/java/com/netflix/simianarmy/basic/chaos/BasicChaosEmailNotifier.java +++ b/src/main/java/com/netflix/simianarmy/basic/chaos/BasicChaosEmailNotifier.java @@ -66,17 +66,12 @@ public BasicChaosEmailNotifier(MonkeyConfiguration cfg, AmazonSimpleEmailService @Override public void sendTerminationGlobalNotification(InstanceGroup group, String instanceId) { String to = cfg.getStr("simianarmy.chaos.notification.global.receiverEmail"); - if (StringUtils.isBlank(to)) { LOGGER.warn("Global email address was not set, but global email notification was enabled!"); return; } - - String body = String.format("Instance %s of %s %s is being terminated by Chaos monkey.", - instanceId, group.type(), group.name()); - String subject = buildEmailSubject(to); LOGGER.info("sending termination notification to global email address {}", to); - sendEmail(to, subject, body); + buildAndSendEmail(to, group, instanceId); } /** @@ -88,11 +83,8 @@ public void sendTerminationGlobalNotification(InstanceGroup group, String instan @Override public void sendTerminationNotification(InstanceGroup group, String instanceId) { String to = getOwnerEmail(group); - String body = String.format("Instance %s of %s %s is being terminated by Chaos monkey.", - instanceId, group.type(), group.name()); - String subject = buildEmailSubject(to); LOGGER.info("sending termination notification to group owner email address {}", to); - sendEmail(to, subject, body); + buildAndSendEmail(to, group, instanceId); } /** @@ -113,9 +105,52 @@ protected String getOwnerEmail(InstanceGroup group) { } } + /** + * Builds the body and subject for the email, sends the email. + * @param group + * the instance group + * @param instanceId + * the instance id + * @param to + * the email address to be sent to + */ + public void buildAndSendEmail(String to, InstanceGroup group, String instanceId) { + String body = buildEmailBody(group, instanceId); + + String subject; + boolean emailSubjectIsBody = cfg.getBoolOrElse( + "simianarmy.chaos.notification.subject.isBody", false); + if (emailSubjectIsBody) { + subject = body; + } else { + subject = buildEmailSubject(to); + } + + sendEmail(to, subject, body); + } + @Override public String buildEmailSubject(String to) { - return String.format("Chaos Monkey Termination Notification for %s", to); + String emailSubjectPrefix = cfg.getStrOrElse("simianarmy.chaos.notification.subject.prefix", ""); + String emailSubjectSuffix = cfg.getStrOrElse("simianarmy.chaos.notification.subject.suffix", ""); + return String.format("%sChaos Monkey Termination Notification for %s%s", + emailSubjectPrefix, to, emailSubjectSuffix); + } + + /** + * Builds the body for the email. + * @param group + * the instance group + * @param instanceId + * the instance id + * @return the created string + */ + public String buildEmailBody(InstanceGroup group, String instanceId) { + String emailBodyPrefix = cfg.getStrOrElse("simianarmy.chaos.notification.body.prefix", ""); + String emailBodySuffix = cfg.getStrOrElse("simianarmy.chaos.notification.body.suffix", ""); + String body = String.format("%sInstance %s of %s %s is being terminated by Chaos monkey.%s", + emailBodyPrefix, instanceId, group.type(), group.name(), emailBodySuffix); + return body; } @Override diff --git a/src/main/resources/chaos.properties b/src/main/resources/chaos.properties index ae9bcb6a..c7518623 100644 --- a/src/main/resources/chaos.properties +++ b/src/main/resources/chaos.properties @@ -42,3 +42,28 @@ simianarmy.chaos.mandatoryTermination.defaultProbability = 0.5 # Set the source email that sends the termination notification # simianarmy.chaos.notification.sourceEmail = foo@bar.com + +# Enable notification for Chaos termination for all instance groups +#simianarmy.chaos.notification.global.enabled = true + +# Set the destination email the termination notification is sent to for all instance groups +#simianarmy.chaos.notification.global.receiverEmail = foo@bar.com + +# Set a prefix applied to the subject of all termination notifications +# Probably want to include a trailing space to separate from start of default text +#simianarmy.chaos.notification.subject.prefix = SubjectPrefix + +# Set a suffix applied to the subject of all termination notifications +# Probably want to include an escaped space " \ " to separate from end of default text +#simianarmy.chaos.notification.subject.suffix = \ SubjectSuffix + +# Set a prefix applied to the body of all termination notifications +# Probably want to include a trailing space to separate from start of default text +#simianarmy.chaos.notification.body.prefix = BodyPrefix + +# Set a suffix applied to the body of all termination notifications +# Probably want to include an escaped space " \ " to separate from end of default text +#simianarmy.chaos.notification.body.suffix = \ BodySuffix + +# Enable the email subject to be the same as the body, to include terminated instance and group information +#simianarmy.chaos.notification.subject.isBody = true \ No newline at end of file diff --git a/src/test/java/com/netflix/simianarmy/basic/chaos/TestBasicChaosEmailNotifier.java b/src/test/java/com/netflix/simianarmy/basic/chaos/TestBasicChaosEmailNotifier.java new file mode 100644 index 00000000..08fbac9b --- /dev/null +++ b/src/test/java/com/netflix/simianarmy/basic/chaos/TestBasicChaosEmailNotifier.java @@ -0,0 +1,154 @@ +// CHECKSTYLE IGNORE Javadoc +/* + * + * Copyright 2013 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.basic.chaos; + +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +import java.util.Properties; + +import org.testng.Assert; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.amazonaws.services.simpleemail.AmazonSimpleEmailServiceClient; +import com.netflix.simianarmy.basic.BasicConfiguration; +import com.netflix.simianarmy.chaos.TestChaosMonkeyContext.TestInstanceGroup; + +public class TestBasicChaosEmailNotifier { + + private final AmazonSimpleEmailServiceClient sesClient = new AmazonSimpleEmailServiceClient(); + + private BasicChaosEmailNotifier basicChaosEmailNotifier; + + private Properties properties; + + private enum GroupTypes { + TYPE_A + }; + + private String name = "name0"; + private String region = "reg1"; + private String to = "foo@bar.com"; + private String instanceId = "i-123456780"; + private String subjectPrefix = "Subject Prefix - "; + private String subjectSuffix = " - Subject Suffix "; + private String bodyPrefix = "Body Prefix - "; + private String bodySuffix = " - Body Suffix"; + + private final TestInstanceGroup testInstanceGroup = new TestInstanceGroup(GroupTypes.TYPE_A, name, region, "0:" + + instanceId); + + private String defaultBody = "Instance " + instanceId + " of " + GroupTypes.TYPE_A + " " + name + + " is being terminated by Chaos monkey."; + + private String defaultSubject = "Chaos Monkey Termination Notification for " + to; + + @BeforeMethod + public void beforeMethod() { + properties = new Properties(); + } + + @Test + public void testbuildEmailSubject() { + basicChaosEmailNotifier = new BasicChaosEmailNotifier(new BasicConfiguration(properties), sesClient, null); + String subject = basicChaosEmailNotifier.buildEmailSubject(to); + Assert.assertEquals(subject, defaultSubject); + } + + @Test + public void testbuildEmailSubjectWithSubjectPrefix() { + properties.setProperty("simianarmy.chaos.notification.subject.prefix", subjectPrefix); + basicChaosEmailNotifier = new BasicChaosEmailNotifier(new BasicConfiguration(properties), sesClient, null); + String subject = basicChaosEmailNotifier.buildEmailSubject(to); + Assert.assertEquals(subject, subjectPrefix + defaultSubject); + } + + @Test + public void testbuildEmailSubjectWithSubjectSuffix() { + properties.setProperty("simianarmy.chaos.notification.subject.suffix", subjectSuffix); + basicChaosEmailNotifier = new BasicChaosEmailNotifier(new BasicConfiguration(properties), sesClient, null); + String subject = basicChaosEmailNotifier.buildEmailSubject(to); + Assert.assertEquals(subject, defaultSubject + subjectSuffix); + } + + @Test + public void testbuildEmailSubjectWithSubjectPrefixSuffix() { + properties.setProperty("simianarmy.chaos.notification.subject.prefix", subjectPrefix); + properties.setProperty("simianarmy.chaos.notification.subject.suffix", subjectSuffix); + basicChaosEmailNotifier = new BasicChaosEmailNotifier(new BasicConfiguration(properties), sesClient, null); + String subject = basicChaosEmailNotifier.buildEmailSubject(to); + Assert.assertEquals(subject, subjectPrefix + defaultSubject + subjectSuffix); + } + + @Test + public void testbuildEmailBody() { + basicChaosEmailNotifier = new BasicChaosEmailNotifier(new BasicConfiguration(properties), sesClient, null); + String subject = basicChaosEmailNotifier.buildEmailBody(testInstanceGroup, instanceId); + Assert.assertEquals(subject, defaultBody); + } + + @Test + public void testbuildEmailBodyPrefix() { + properties.setProperty("simianarmy.chaos.notification.body.prefix", bodyPrefix); + basicChaosEmailNotifier = new BasicChaosEmailNotifier(new BasicConfiguration(properties), sesClient, null); + String subject = basicChaosEmailNotifier.buildEmailBody(testInstanceGroup, instanceId); + Assert.assertEquals(subject, bodyPrefix + defaultBody); + } + + @Test + public void testbuildEmailBodySuffix() { + properties.setProperty("simianarmy.chaos.notification.body.suffix", bodySuffix); + basicChaosEmailNotifier = new BasicChaosEmailNotifier(new BasicConfiguration(properties), sesClient, null); + String subject = basicChaosEmailNotifier.buildEmailBody(testInstanceGroup, instanceId); + Assert.assertEquals(subject, defaultBody + bodySuffix); + } + + @Test + public void testbuildEmailBodyPrefixSuffix() { + properties.setProperty("simianarmy.chaos.notification.body.prefix", bodyPrefix); + properties.setProperty("simianarmy.chaos.notification.body.suffix", bodySuffix); + basicChaosEmailNotifier = new BasicChaosEmailNotifier(new BasicConfiguration(properties), sesClient, null); + String subject = basicChaosEmailNotifier.buildEmailBody(testInstanceGroup, instanceId); + Assert.assertEquals(subject, bodyPrefix + defaultBody + bodySuffix); + } + + @Test + public void testBuildAndSendEmail() { + properties.setProperty("simianarmy.chaos.notification.sourceEmail", to); + BasicChaosEmailNotifier spyBasicChaosEmailNotifier = spy(new BasicChaosEmailNotifier(new BasicConfiguration( + properties), sesClient, null)); + doNothing().when(spyBasicChaosEmailNotifier).sendEmail(to, defaultSubject, defaultBody); + spyBasicChaosEmailNotifier.buildAndSendEmail(to, testInstanceGroup, instanceId); + verify(spyBasicChaosEmailNotifier).sendEmail(to, defaultSubject, defaultBody); + } + + @Test + public void testBuildAndSendEmailSubjectIsBody() { + properties.setProperty("simianarmy.chaos.notification.subject.isBody", "true"); + properties.setProperty("simianarmy.chaos.notification.sourceEmail", to); + BasicChaosEmailNotifier spyBasicChaosEmailNotifier = spy(new BasicChaosEmailNotifier(new BasicConfiguration( + properties), sesClient, null)); + doNothing().when(spyBasicChaosEmailNotifier).sendEmail(to, defaultBody, defaultBody); + spyBasicChaosEmailNotifier.buildAndSendEmail(to, testInstanceGroup, instanceId); + verify(spyBasicChaosEmailNotifier).sendEmail(to, defaultBody, defaultBody); + } + +} \ No newline at end of file