diff --git a/build.gradle b/build.gradle index 9b3fa48a..4f5ecd74 100644 --- a/build.gradle +++ b/build.gradle @@ -48,7 +48,8 @@ dependencies { compile 'org.apache.jclouds.api:ec2:1.9.0' compile 'org.apache.jclouds.provider:aws-ec2:1.9.0' compile 'com.netflix.servo:servo-core:0.9.4' - compile "org.springframework:spring-jdbc:4.2.5.RELEASE" + compile 'org.springframework:spring-jdbc:4.2.5.RELEASE' + compile 'com.zaxxer:HikariCP:2.4.7' testCompile 'org.testng:testng:6.3.1' testCompile 'org.mockito:mockito-core:1.8.5' diff --git a/src/main/java/com/netflix/simianarmy/aws/RDSRecorder.java b/src/main/java/com/netflix/simianarmy/aws/RDSRecorder.java index a25cd9a9..160e2a84 100644 --- a/src/main/java/com/netflix/simianarmy/aws/RDSRecorder.java +++ b/src/main/java/com/netflix/simianarmy/aws/RDSRecorder.java @@ -25,11 +25,11 @@ import com.netflix.simianarmy.MonkeyRecorder; import com.netflix.simianarmy.MonkeyType; import com.netflix.simianarmy.basic.BasicRecorderEvent; +import com.zaxxer.hikari.HikariDataSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.datasource.DriverManagerDataSource; import java.io.IOException; import java.sql.ResultSet; @@ -68,8 +68,11 @@ public class RDSRecorder implements MonkeyRecorder { */ public RDSRecorder(String dbDriver, String dbUser, String dbPass, String dbUrl, String dbTable, String region) { - DriverManagerDataSource dataSource = new DriverManagerDataSource(dbUrl, dbUser, dbPass); - dataSource.setDriverClassName(dbDriver); + HikariDataSource dataSource = new HikariDataSource(); + dataSource.setDriverClassName(dbDriver); + dataSource.setJdbcUrl(dbUrl); + dataSource.setUsername(dbUser); + dataSource.setPassword(dbPass); this.jdbcTemplate = new JdbcTemplate(dataSource); this.table = dbTable; this.region = region; diff --git a/src/main/java/com/netflix/simianarmy/aws/conformity/RDSConformityClusterTracker.java b/src/main/java/com/netflix/simianarmy/aws/conformity/RDSConformityClusterTracker.java index 4a1f5fb4..3caad919 100644 --- a/src/main/java/com/netflix/simianarmy/aws/conformity/RDSConformityClusterTracker.java +++ b/src/main/java/com/netflix/simianarmy/aws/conformity/RDSConformityClusterTracker.java @@ -25,13 +25,13 @@ import com.netflix.simianarmy.conformity.Cluster; import com.netflix.simianarmy.conformity.Conformity; import com.netflix.simianarmy.conformity.ConformityClusterTracker; +import com.zaxxer.hikari.HikariDataSource; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.datasource.DriverManagerDataSource; import java.io.IOException; import java.sql.ResultSet; @@ -62,8 +62,11 @@ public class RDSConformityClusterTracker implements ConformityClusterTracker { */ public RDSConformityClusterTracker(String dbDriver, String dbUser, String dbPass, String dbUrl, String dbTable) { - DriverManagerDataSource dataSource = new DriverManagerDataSource(dbUrl, dbUser, dbPass); - dataSource.setDriverClassName(dbDriver); + HikariDataSource dataSource = new HikariDataSource(); + dataSource.setDriverClassName(dbDriver); + dataSource.setJdbcUrl(dbUrl); + dataSource.setUsername(dbUser); + dataSource.setPassword(dbPass); this.jdbcTemplate = new JdbcTemplate(dataSource); this.table = dbTable; } diff --git a/src/main/java/com/netflix/simianarmy/aws/janitor/RDSJanitorResourceTracker.java b/src/main/java/com/netflix/simianarmy/aws/janitor/RDSJanitorResourceTracker.java index 5bceeae3..130d6235 100644 --- a/src/main/java/com/netflix/simianarmy/aws/janitor/RDSJanitorResourceTracker.java +++ b/src/main/java/com/netflix/simianarmy/aws/janitor/RDSJanitorResourceTracker.java @@ -26,13 +26,13 @@ import com.netflix.simianarmy.ResourceType; import com.netflix.simianarmy.aws.AWSResource; import com.netflix.simianarmy.janitor.JanitorResourceTracker; +import com.zaxxer.hikari.HikariDataSource; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.Validate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; -import org.springframework.jdbc.datasource.DriverManagerDataSource; import java.io.IOException; import java.sql.ResultSet; @@ -60,8 +60,11 @@ public class RDSJanitorResourceTracker implements JanitorResourceTracker { */ public RDSJanitorResourceTracker(String dbDriver, String dbUser, String dbPass, String dbUrl, String dbTable) { - DriverManagerDataSource dataSource = new DriverManagerDataSource(dbUrl, dbUser, dbPass); - dataSource.setDriverClassName(dbDriver); + HikariDataSource dataSource = new HikariDataSource(); + dataSource.setDriverClassName(dbDriver); + dataSource.setJdbcUrl(dbUrl); + dataSource.setUsername(dbUser); + dataSource.setPassword(dbPass); this.jdbcTemplate = new JdbcTemplate(dataSource); this.table = dbTable; } @@ -124,10 +127,11 @@ public void addOrUpdate(Resource resource) { sb.append(AWSResource.FIELD_TERMINATION_REASON).append(","); sb.append(AWSResource.FIELD_EXPECTED_TERMINATION_TIME).append(","); sb.append(AWSResource.FIELD_ACTUAL_TERMINATION_TIME).append(","); + sb.append(AWSResource.FIELD_NOTIFICATION_TIME).append(","); sb.append(AWSResource.FIELD_LAUNCH_TIME).append(","); sb.append(AWSResource.FIELD_MARK_TIME).append(","); sb.append(AWSResource.FIELD_OPT_OUT_OF_JANITOR).append(","); - sb.append("additionalFields").append(") values (?,?,?,?,?,?,?,?,?,?,?,?,?)"); + sb.append("additionalFields").append(") values (?,?,?,?,?,?,?,?,?,?,?,?,?,?)"); LOGGER.debug(String.format("Insert statement is '%s'", sb)); int updated = this.jdbcTemplate.update(sb.toString(), @@ -140,6 +144,7 @@ public void addOrUpdate(Resource resource) { value(resource.getTerminationReason()), value(resource.getExpectedTerminationTime()), value(resource.getActualTerminationTime()), + value(resource.getNotificationTime()), value(resource.getLaunchTime()), value(resource.getMarkTime()), value(resource.isOptOutOfJanitor()), @@ -156,6 +161,7 @@ public void addOrUpdate(Resource resource) { sb.append(AWSResource.FIELD_TERMINATION_REASON).append("=?,"); sb.append(AWSResource.FIELD_EXPECTED_TERMINATION_TIME).append("=?,"); sb.append(AWSResource.FIELD_ACTUAL_TERMINATION_TIME).append("=?,"); + sb.append(AWSResource.FIELD_NOTIFICATION_TIME).append("=?,"); sb.append(AWSResource.FIELD_LAUNCH_TIME).append("=?,"); sb.append(AWSResource.FIELD_MARK_TIME).append("=?,"); sb.append(AWSResource.FIELD_OPT_OUT_OF_JANITOR).append("=?,"); @@ -172,6 +178,7 @@ public void addOrUpdate(Resource resource) { value(resource.getTerminationReason()), value(resource.getExpectedTerminationTime()), value(resource.getActualTerminationTime()), + value(resource.getNotificationTime()), value(resource.getLaunchTime()), value(resource.getMarkTime()), value(resource.isOptOutOfJanitor()), @@ -241,6 +248,7 @@ private Resource mapResource(ResultSet rs) throws SQLException { String expectedTerminationTime = millisToFormattedDate(rs.getString(AWSResource.FIELD_EXPECTED_TERMINATION_TIME)); String actualTerminationTime = millisToFormattedDate(rs.getString(AWSResource.FIELD_ACTUAL_TERMINATION_TIME)); + String notificationTime = millisToFormattedDate(rs.getString(AWSResource.FIELD_NOTIFICATION_TIME)); String launchTime = millisToFormattedDate(rs.getString(AWSResource.FIELD_LAUNCH_TIME)); String markTime = millisToFormattedDate(rs.getString(AWSResource.FIELD_MARK_TIME)); @@ -250,13 +258,16 @@ private Resource mapResource(ResultSet rs) throws SQLException { if (actualTerminationTime != null) { map.put(AWSResource.FIELD_ACTUAL_TERMINATION_TIME, actualTerminationTime); } + if (notificationTime != null) { + map.put(AWSResource.FIELD_NOTIFICATION_TIME, notificationTime); + } if (launchTime != null) { map.put(AWSResource.FIELD_LAUNCH_TIME, launchTime); } if (markTime != null) { map.put(AWSResource.FIELD_MARK_TIME, markTime); } - + resource = AWSResource.parseFieldtoValueMap(map); }catch(IOException ie) { String msg = "Error parsing resource from result set"; @@ -316,8 +327,9 @@ public void init() { + " %s varchar(255), " + " %s BIGINT, " + " %s BIGINT, " - + " %s BIGINT, " + " %s BIGINT, " + + " %s BIGINT, " + + " %s BIGINT, " + " %s varchar(8), " + " %s varchar(4096) )", table, @@ -330,6 +342,7 @@ public void init() { AWSResource.FIELD_TERMINATION_REASON, AWSResource.FIELD_EXPECTED_TERMINATION_TIME, AWSResource.FIELD_ACTUAL_TERMINATION_TIME, + AWSResource.FIELD_NOTIFICATION_TIME, AWSResource.FIELD_LAUNCH_TIME, AWSResource.FIELD_MARK_TIME, AWSResource.FIELD_OPT_OUT_OF_JANITOR, diff --git a/src/main/java/com/netflix/simianarmy/basic/janitor/BasicJanitorMonkey.java b/src/main/java/com/netflix/simianarmy/basic/janitor/BasicJanitorMonkey.java index fecb702b..c3a25a99 100644 --- a/src/main/java/com/netflix/simianarmy/basic/janitor/BasicJanitorMonkey.java +++ b/src/main/java/com/netflix/simianarmy/basic/janitor/BasicJanitorMonkey.java @@ -17,27 +17,22 @@ */ package com.netflix.simianarmy.basic.janitor; -import java.util.Collection; -import java.util.List; -import java.util.concurrent.atomic.AtomicLong; - -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import com.netflix.servo.annotations.DataSourceType; import com.netflix.servo.annotations.Monitor; import com.netflix.servo.monitor.Monitors; -import com.netflix.simianarmy.MonkeyCalendar; -import com.netflix.simianarmy.MonkeyConfiguration; -import com.netflix.simianarmy.MonkeyRecorder; +import com.netflix.simianarmy.*; import com.netflix.simianarmy.MonkeyRecorder.Event; -import com.netflix.simianarmy.Resource; -import com.netflix.simianarmy.ResourceType; import com.netflix.simianarmy.janitor.AbstractJanitor; import com.netflix.simianarmy.janitor.JanitorEmailNotifier; import com.netflix.simianarmy.janitor.JanitorMonkey; import com.netflix.simianarmy.janitor.JanitorResourceTracker; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; /** The basic implementation of Janitor Monkey. */ public class BasicJanitorMonkey extends JanitorMonkey { @@ -140,7 +135,7 @@ public void doMonkeyBusiness() { janitor.cleanupResources(); } catch (Exception e) { monkeyErrors.incrementAndGet(); - LOGGER.error(String.format("Got an exception while %s janitor was cleaning for region %s", janitor.getResourceType()), janitor.getRegion(), e); + LOGGER.error(String.format("Got an exception while %s janitor was cleaning for region %s", janitor.getResourceType(), janitor.getRegion()), e); } LOGGER.info(String.format("Cleaned %d resources of type %s in the last run.", janitor.getCleanedResources().size(), janitor.getResourceType())); diff --git a/src/main/java/com/netflix/simianarmy/resources/janitor/JanitorMonkeyResource.java b/src/main/java/com/netflix/simianarmy/resources/janitor/JanitorMonkeyResource.java index a6cc8bc3..52a09441 100644 --- a/src/main/java/com/netflix/simianarmy/resources/janitor/JanitorMonkeyResource.java +++ b/src/main/java/com/netflix/simianarmy/resources/janitor/JanitorMonkeyResource.java @@ -17,18 +17,9 @@ */ package com.netflix.simianarmy.resources.janitor; -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.QueryParam; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; - +import com.netflix.simianarmy.MonkeyRecorder.Event; +import com.netflix.simianarmy.MonkeyRunner; +import com.netflix.simianarmy.janitor.JanitorMonkey; import org.apache.commons.lang.StringUtils; import org.codehaus.jackson.JsonEncoding; import org.codehaus.jackson.JsonGenerator; @@ -38,9 +29,16 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.netflix.simianarmy.MonkeyRecorder.Event; -import com.netflix.simianarmy.MonkeyRunner; -import com.netflix.simianarmy.janitor.JanitorMonkey; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Map; /** * The Class JanitorMonkeyResource for json REST apis. @@ -52,7 +50,7 @@ public class JanitorMonkeyResource { private static final MappingJsonFactory JSON_FACTORY = new MappingJsonFactory(); /** The monkey. */ - private final JanitorMonkey monkey; + private static JanitorMonkey monkey; /** The Constant LOGGER. */ private static final Logger LOGGER = LoggerFactory.getLogger(JanitorMonkeyResource.class); @@ -64,16 +62,18 @@ public class JanitorMonkeyResource { * the janitor monkey */ public JanitorMonkeyResource(JanitorMonkey monkey) { - this.monkey = monkey; + JanitorMonkeyResource.monkey = monkey; } /** * Instantiates a janitor monkey resource using a registered janitor monkey from factory. */ public JanitorMonkeyResource() { - this.monkey = MonkeyRunner.getInstance().factory(JanitorMonkey.class); + if (JanitorMonkeyResource.monkey == null ) { + JanitorMonkeyResource.monkey = MonkeyRunner.getInstance().factory(JanitorMonkey.class); + } } - + /** * 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 diff --git a/src/test/java/com/netflix/simianarmy/aws/janitor/TestRDSJanitorResourceTracker.java b/src/test/java/com/netflix/simianarmy/aws/janitor/TestRDSJanitorResourceTracker.java index cbcb330a..b3a7e7a9 100644 --- a/src/test/java/com/netflix/simianarmy/aws/janitor/TestRDSJanitorResourceTracker.java +++ b/src/test/java/com/netflix/simianarmy/aws/janitor/TestRDSJanitorResourceTracker.java @@ -49,7 +49,7 @@ public void testInit() { ArgumentCaptor sqlCap = ArgumentCaptor.forClass(String.class); Mockito.doNothing().when(recorder.getJdbcTemplate()).execute(sqlCap.capture()); recorder.init(); - Assert.assertEquals(sqlCap.getValue(), "create table if not exists janitortable ( resourceId varchar(255), resourceType varchar(255), region varchar(25), ownerEmail varchar(255), description varchar(255), state varchar(25), terminationReason varchar(255), expectedTerminationTime BIGINT, actualTerminationTime BIGINT, launchTime BIGINT, markTime BIGINT, optOutOfJanitor varchar(8), additionalFields varchar(4096) )"); + Assert.assertEquals(sqlCap.getValue(), "create table if not exists janitortable ( resourceId varchar(255), resourceType varchar(255), region varchar(25), ownerEmail varchar(255), description varchar(255), state varchar(25), terminationReason varchar(255), expectedTerminationTime BIGINT, actualTerminationTime BIGINT, notificationTime BIGINT, launchTime BIGINT, markTime BIGINT, optOutOfJanitor varchar(8), additionalFields varchar(4096) )"); } @SuppressWarnings("unchecked") @@ -93,7 +93,8 @@ public void testInsertNewResource() { objCap.capture(), objCap.capture(), objCap.capture(), - objCap.capture(), + objCap.capture(), + objCap.capture(), objCap.capture(), objCap.capture(), objCap.capture())).thenReturn(1); @@ -101,8 +102,8 @@ public void testInsertNewResource() { List args = objCap.getAllValues(); - Assert.assertEquals(sqlCap.getValue(), "insert into janitortable (resourceId,resourceType,region,ownerEmail,description,state,terminationReason,expectedTerminationTime,actualTerminationTime,launchTime,markTime,optOutOfJanitor,additionalFields) values (?,?,?,?,?,?,?,?,?,?,?,?,?)"); - Assert.assertEquals(args.size(), 13); + Assert.assertEquals(sqlCap.getValue(), "insert into janitortable (resourceId,resourceType,region,ownerEmail,description,state,terminationReason,expectedTerminationTime,actualTerminationTime,notificationTime,launchTime,markTime,optOutOfJanitor,additionalFields) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?)"); + Assert.assertEquals(args.size(), 14); Assert.assertEquals(args.get(0).toString(), id); Assert.assertEquals(args.get(1).toString(), AWSResourceType.INSTANCE.toString()); Assert.assertEquals(args.get(2).toString(), region); @@ -113,9 +114,10 @@ public void testInsertNewResource() { Assert.assertEquals(args.get(7).toString(), expectedTerminationTime.getTime() + ""); Assert.assertEquals(args.get(8).toString(), "0"); Assert.assertEquals(args.get(9).toString(), "0"); - Assert.assertEquals(args.get(10).toString(), markTime.getTime() + ""); - Assert.assertEquals(args.get(11).toString(), "false"); - Assert.assertEquals(args.get(12).toString(), "{\"fieldName123\":\"fieldValue456\"}"); + Assert.assertEquals(args.get(10).toString(), "0"); + Assert.assertEquals(args.get(11).toString(), markTime.getTime() + ""); + Assert.assertEquals(args.get(12).toString(), "false"); + Assert.assertEquals(args.get(13).toString(), "{\"fieldName123\":\"fieldValue456\"}"); } @SuppressWarnings("unchecked") @@ -167,8 +169,9 @@ public void testUpdateResource() { objCap.capture(), objCap.capture(), objCap.capture(), - objCap.capture(), - objCap.capture(), + objCap.capture(), + objCap.capture(), + objCap.capture(), objCap.capture(), objCap.capture(), objCap.capture(), @@ -176,8 +179,8 @@ public void testUpdateResource() { tracker.addOrUpdate(newResource); List args = objCap.getAllValues(); - Assert.assertEquals(sqlCap.getValue(), "update janitortable set resourceType=?,region=?,ownerEmail=?,description=?,state=?,terminationReason=?,expectedTerminationTime=?,actualTerminationTime=?,launchTime=?,markTime=?,optOutOfJanitor=?,additionalFields=? where resourceId=?"); - Assert.assertEquals(args.size(), 13); + Assert.assertEquals(sqlCap.getValue(), "update janitortable set resourceType=?,region=?,ownerEmail=?,description=?,state=?,terminationReason=?,expectedTerminationTime=?,actualTerminationTime=?,notificationTime=?,launchTime=?,markTime=?,optOutOfJanitor=?,additionalFields=? where resourceId=?"); + Assert.assertEquals(args.size(), 14); Assert.assertEquals(args.get(0).toString(), AWSResourceType.INSTANCE.toString()); Assert.assertEquals(args.get(1).toString(), region); Assert.assertEquals(args.get(2).toString(), ownerEmail); @@ -187,10 +190,11 @@ public void testUpdateResource() { Assert.assertEquals(args.get(6).toString(), expectedTerminationTime.getTime() + ""); Assert.assertEquals(args.get(7).toString(), "0"); Assert.assertEquals(args.get(8).toString(), "0"); - Assert.assertEquals(args.get(9).toString(), markTime.getTime() + ""); - Assert.assertEquals(args.get(10).toString(), "false"); - Assert.assertEquals(args.get(11).toString(), "{\"fieldName123\":\"fieldValue456\"}"); - Assert.assertEquals(args.get(12).toString(), id); + Assert.assertEquals(args.get(9).toString(), "0"); + Assert.assertEquals(args.get(10).toString(), markTime.getTime() + ""); + Assert.assertEquals(args.get(11).toString(), "false"); + Assert.assertEquals(args.get(12).toString(), "{\"fieldName123\":\"fieldValue456\"}"); + Assert.assertEquals(args.get(13).toString(), id); }