Skip to content
This repository has been archived by the owner on Mar 4, 2021. It is now read-only.

Commit

Permalink
Merge changes since RDS PR
Browse files Browse the repository at this point in the history
  • Loading branch information
ebukoski committed Aug 12, 2016
1 parent f608730 commit 2b71a15
Show file tree
Hide file tree
Showing 7 changed files with 360 additions and 21 deletions.
13 changes: 6 additions & 7 deletions src/main/java/com/netflix/simianarmy/basic/BasicCalendar.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public class BasicCalendar implements MonkeyCalendar {
private final TimeZone tz;

/** The holidays. */
private final Set<Integer> holidays = new TreeSet<Integer>();
protected final Set<Integer> holidays = new TreeSet<Integer>();

/** The cfg. */
private MonkeyConfiguration cfg;
Expand Down Expand Up @@ -83,7 +83,7 @@ public BasicCalendar(int open, int close, TimeZone timezone) {
closeHour = close;
tz = timezone;
}

/**
* Instantiates a new basic calendar.
*
Expand Down Expand Up @@ -235,7 +235,7 @@ protected void loadHolidays(int year) {
* the day
* @return the day of the year
*/
private int dayOfYear(int year, int month, int day) {
protected int dayOfYear(int year, int month, int day) {
Calendar holiday = now();
holiday.set(Calendar.YEAR, year);
holiday.set(Calendar.MONTH, month);
Expand All @@ -256,7 +256,7 @@ private int dayOfYear(int year, int month, int day) {
* the week in month
* @return the day of the year
*/
private int dayOfYear(int year, int month, int dayOfWeek, int weekInMonth) {
protected int dayOfYear(int year, int month, int dayOfWeek, int weekInMonth) {
Calendar holiday = now();
holiday.set(Calendar.YEAR, year);
holiday.set(Calendar.MONTH, month);
Expand All @@ -276,7 +276,7 @@ private int dayOfYear(int year, int month, int dayOfWeek, int weekInMonth) {
* the day
* @return the day of the year adjusted to the closest workday
*/
private int workDayInYear(int year, int month, int day) {
protected int workDayInYear(int year, int month, int day) {
Calendar holiday = now();
holiday.set(Calendar.YEAR, year);
holiday.set(Calendar.MONTH, month);
Expand Down Expand Up @@ -308,8 +308,7 @@ public Date getBusinessDay(Date date, int n) {

private boolean isWeekend(Calendar calendar) {
int dow = calendar.get(Calendar.DAY_OF_WEEK);
return dow == Calendar.SATURDAY
|| dow == Calendar.SUNDAY;
return dow == Calendar.SATURDAY || dow == Calendar.SUNDAY;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -122,19 +122,18 @@ protected BasicSimianArmyContext(String... configFiles) {
}

config = new BasicConfiguration(properties);
calendar = new BasicCalendar(config);

account = config.getStr("simianarmy.client.aws.accountKey");
secret = config.getStr("simianarmy.client.aws.secretKey");
accountName = config.getStrOrElse("simianarmy.client.aws.accountName", "Default");

String defaultRegion = "us-east-1";
Region currentRegion = Regions.getCurrentRegion();

if (currentRegion != null) {
defaultRegion = currentRegion.getName();
}

region = config.getStrOrElse("simianarmy.client.aws.region", defaultRegion);
GLOBAL_OWNER_TAGKEY = config.getStrOrElse("simianarmy.tags.owner", "owner");

Expand Down Expand Up @@ -165,6 +164,8 @@ protected BasicSimianArmyContext(String... configFiles) {

createClient();

createCalendar();

createScheduler();

createRecorder();
Expand Down Expand Up @@ -235,6 +236,17 @@ private void createRecorder() {
}
}

@SuppressWarnings("unchecked")
private void createCalendar() {
@SuppressWarnings("rawtypes")
Class calendarClass = loadClientClass("simianarmy.calendar.class");
if (calendarClass == null || calendarClass.equals(BasicCalendar.class)) {
setCalendar(new BasicCalendar(config));
} else {
setCalendar((MonkeyCalendar) factory(calendarClass));
}
}

/**
* Create the specific client with region taken from properties.
* Override to provide your own client.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*
*
* 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.basic.calendars;

import com.netflix.simianarmy.MonkeyConfiguration;
import com.netflix.simianarmy.basic.BasicCalendar;

import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;

// CHECKSTYLE IGNORE MagicNumberCheck
/**
* The Class BavarianCalendar.
*/
public class BavarianCalendar extends BasicCalendar
{
/**
* Instantiates a new basic calendar.
*
* @param cfg the monkey configuration
*/
public BavarianCalendar(MonkeyConfiguration cfg)
{
super(cfg);
}

/** {@inheritDoc} */
@Override
protected void loadHolidays(int year) {
holidays.clear();

// these aren't all strictly holidays, but days when engineers will likely
// not be in the office to respond to rampaging monkeys

// first of all, we need easter sunday doy,
// because ome other holidays calculated from it
int easter = westernEasterDayOfYear(year);

// new year
holidays.addAll(getHolidayWithBridgeDays(year, dayOfYear(year, Calendar.JANUARY, 1)));

// epiphanie
holidays.addAll(getHolidayWithBridgeDays(year, dayOfYear(year, Calendar.JANUARY, 6)));

// good friday, always friday, don't need to check if it's bridge day
holidays.add(easter - 2);

// easter monday, always monday, don't need to check if it's bridge day
holidays.add(easter + 1);

// labor day
holidays.addAll(getHolidayWithBridgeDays(year, dayOfYear(year, Calendar.MAY, 1)));

// ascension day
holidays.addAll(getHolidayWithBridgeDays(year, easter + 39));

// whit monday, always monday, don't need to check if it's bridge day
holidays.add(easter + 50);

// corpus christi
holidays.add(westernEasterDayOfYear(year) + 60);

// assumption day
holidays.addAll(getHolidayWithBridgeDays(year, dayOfYear(year, Calendar.AUGUST, 15)));

// german unity day
holidays.addAll(getHolidayWithBridgeDays(year, dayOfYear(year, Calendar.OCTOBER, 3)));

// all saints
holidays.addAll(getHolidayWithBridgeDays(year, dayOfYear(year, Calendar.NOVEMBER, 1)));

// monkey goes on christmas vacations between christmas and new year!
holidays.addAll(getHolidayWithBridgeDays(year, dayOfYear(year, Calendar.DECEMBER, 24)));
holidays.add(dayOfYear(year, Calendar.DECEMBER, 25));
holidays.add(dayOfYear(year, Calendar.DECEMBER, 26));
holidays.add(dayOfYear(year, Calendar.DECEMBER, 27));
holidays.add(dayOfYear(year, Calendar.DECEMBER, 28));
holidays.add(dayOfYear(year, Calendar.DECEMBER, 29));
holidays.add(dayOfYear(year, Calendar.DECEMBER, 30));
holidays.add(dayOfYear(year, Calendar.DECEMBER, 31));

// mark the holiday set with the year, so on Jan 1 it will automatically
// recalculate the holidays for next year
holidays.add(year);
}

/**
* Returns collection of holidays, including Monday or Friday
* if given holiday is Thuesday or Thursday.
*
* The behaviour to take Monday as day off if official holiday is Thuesday
* and to take Friday as day off if official holiday is Thursday
* is specific to [at least] Germany.
* We call it, literally, "bridge day".
*
* @param dayOfYear holiday day of year
*/
private Collection<Integer> getHolidayWithBridgeDays(int year, int dayOfYear) {
Calendar holiday = now();
holiday.set(Calendar.YEAR, year);
holiday.set(Calendar.DAY_OF_YEAR, dayOfYear);
int dow = holiday.get(Calendar.DAY_OF_WEEK);
int mon = holiday.get(Calendar.MONTH);
int dom = holiday.get(Calendar.DAY_OF_MONTH);

// We don't want to include Monday if Thuesday is January 1.
if (dow == Calendar.TUESDAY && dayOfYear != 1)
return Arrays.asList(dayOfYear, dayOfYear - 1);

// We don't want to include Friday if Thursday is December 31.
if (dow == Calendar.THURSDAY && (mon != Calendar.DECEMBER || dom != 31))
return Arrays.asList(dayOfYear, dayOfYear + 1);

return Arrays.asList(dayOfYear);
}

/**
* Western easter sunday in year.
*
* @param year
* the year
* @return the day of the year of western easter sunday
*/
protected int westernEasterDayOfYear(int year) {
int a = year % 19,
b = year / 100,
c = year % 100,
d = b / 4,
e = b % 4,
g = (8 * b + 13) / 25,
h = (19 * a + b - d - g + 15) % 30,
j = c / 4,
k = c % 4,
m = (a + 11 * h) / 319,
r = (2 * e + 2 * j - k - h + m + 32) % 7;
int oneBasedMonth = (h - m + r + 90) / 25;
int dayOfYear = (h - m + r + oneBasedMonth + 19) % 32;
return dayOfYear(year, oneBasedMonth - 1, dayOfYear);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

Expand Down Expand Up @@ -58,6 +60,7 @@
* The Class ChaosMonkeyResource for json REST apis.
*/
@Path("/v1/chaos")
@Produces(MediaType.APPLICATION_JSON)
@Singleton
public class ChaosMonkeyResource {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@
import com.netflix.simianarmy.MonkeyRecorder.Event;
import com.netflix.simianarmy.MonkeyRunner;
import com.netflix.simianarmy.janitor.JanitorMonkey;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Map;

import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;

import org.apache.commons.lang.StringUtils;
import org.codehaus.jackson.JsonEncoding;
import org.codehaus.jackson.JsonGenerator;
Expand All @@ -44,6 +58,7 @@
* The Class JanitorMonkeyResource for json REST apis.
*/
@Path("/v1/janitor")
@Produces(MediaType.APPLICATION_JSON)
public class JanitorMonkeyResource {

/** The Constant JSON_FACTORY. */
Expand Down Expand Up @@ -77,7 +92,7 @@ public JanitorMonkeyResource() {
/**
* GET /api/v1/janitor/addEvent will try to a add a new event with the information in the url query string.
* This is the same as the regular POST addEvent except through a query string. This technically isn't
* very REST-ful as it is a GET call that creates an Opt-out/in event, but is a convenience method
* very REST-ful as it is a GET call that creates an Opt-out/in event, but is a convenience method
* for exposing opt-in/opt-out functionality more directly, for example in an email notification.
*
* @param eventType eventType from the query string
Expand All @@ -86,20 +101,20 @@ public JanitorMonkeyResource() {
* @throws IOException
*/
@GET @Path("addEvent")
public Response addEventThroughHttpGet( @QueryParam("eventType") String eventType, @QueryParam("resourceId") String resourceId) throws IOException {
public Response addEventThroughHttpGet( @QueryParam("eventType") String eventType, @QueryParam("resourceId") String resourceId) throws IOException {
Response.Status responseStatus;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write("<html><body style=\"text-align:center\"><img src=\"https://raw.githubusercontent.com/Netflix/SimianArmy/master/assets/janitor.png\" height=\"300\" width=\"300\"><br/>".getBytes());
if (StringUtils.isEmpty(eventType) || StringUtils.isEmpty(resourceId)) {
responseStatus = Response.Status.BAD_REQUEST;
responseStatus = Response.Status.BAD_REQUEST;
baos.write("<p>NOPE!<br/><br/>Janitor didn't get that: eventType and resourceId parameters are both required</p>".getBytes());
} else {
ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
JsonGenerator gen = JSON_FACTORY.createJsonGenerator(baos2, JsonEncoding.UTF8);
gen.writeStartObject();
gen.writeStringField("eventType", eventType);
gen.writeStringField("resourceId", resourceId);

if (eventType.equals("OPTIN")) {
responseStatus = optInResource(resourceId, true, gen);
} else if (eventType.equals("OPTOUT")) {
Expand All @@ -110,21 +125,21 @@ public Response addEventThroughHttpGet( @QueryParam("eventType") String eventTyp
}
gen.writeEndObject();
gen.close();

if(responseStatus == Response.Status.OK) {
baos.write(("<p>SUCCESS!<br/><br/>Resource <strong>" + resourceId + "</strong> has been " + eventType + " of Janitor Monkey!</p>").getBytes());
} else {
baos.write(("<p>NOPE!<br/><br/>Janitor is Confused! Error processing Resource <strong>" + resourceId + "</strong></p>").getBytes());
}

String jsonout = String.format("<p><em>Monkey JSON Response:</em><br/><br/><textarea cols=40 rows=20>%s</textarea></p>", baos2.toString());
baos.write(jsonout.getBytes());

}
baos.write("</body></html>".getBytes());
return Response.status(responseStatus).entity(baos.toString("UTF-8")).build();
}

/**
* POST /api/v1/janitor will try a add a new event with the information in the url context.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ public void testGetBusinessDayWihHolidayNextYear() {
Assert.assertEquals(businessDay.get(Calendar.YEAR), 2013);
Assert.assertEquals(businessDay.get(Calendar.MONTH), Calendar.JANUARY);
Assert.assertEquals(businessDay.get(Calendar.DAY_OF_MONTH), 2);
Assert.assertEquals(businessDay.get(Calendar.HOUR_OF_DAY),
hour);
Assert.assertEquals(businessDay.get(Calendar.HOUR_OF_DAY), hour);
}

}
Loading

0 comments on commit 2b71a15

Please sign in to comment.