Fix find AlarmDefinition by dimension

Some of the SQL wasn't updated when the tables were renamed

Also, rename SubAlarmQueries to match its use in AlarmDefinitions

Fix alarm.sql so AlarmDefinitionMySqlRepositoryImplTest runs

Add more comprehensive unit tests that would have caught this error

Change-Id: I4bd9519fb1b24f9763f1bb34bbd960c69879eb80
This commit is contained in:
Craig Bryant 2015-02-13 07:39:03 -07:00
parent eaf7b43719
commit bd3255629a
6 changed files with 62 additions and 51 deletions

View File

@ -18,18 +18,18 @@ import java.util.Map;
/**
* Utilities for building sub alarm queries.
*/
public final class SubAlarmQueries {
private SubAlarmQueries() {}
public final class SubAlarmDefinitionQueries {
private SubAlarmDefinitionQueries() {}
public static String buildJoinClauseFor(Map<String, String> dimensions) {
StringBuilder sbJoin = null;
if (dimensions != null) {
sbJoin = new StringBuilder();
for (int i = 0; i < dimensions.size(); i++) {
sbJoin.append(" inner join sub_alarm_dimension d").append(i).append(" on d").append(i)
sbJoin.append(" inner join sub_alarm_definition_dimension d").append(i).append(" on d").append(i)
.append(".dimension_name = :dname").append(i).append(" and d").append(i)
.append("" + ".value = :dvalue").append(i).append(" and dim.sub_alarm_id = d")
.append(i).append(".sub_alarm_id");
.append("" + ".value = :dvalue").append(i).append(" and dim.sub_alarm_definition_id = d")
.append(i).append(".sub_alarm_definition_id");
}
}

View File

@ -40,7 +40,7 @@ import monasca.api.domain.exception.EntityNotFoundException;
import monasca.api.domain.model.alarmdefinition.AlarmDefinition;
import monasca.api.domain.model.alarmdefinition.AlarmDefinitionRepository;
import monasca.api.infrastructure.persistence.DimensionQueries;
import monasca.api.infrastructure.persistence.SubAlarmQueries;
import monasca.api.infrastructure.persistence.SubAlarmDefinitionQueries;
import monasca.common.persistence.BeanMapper;
/**
@ -141,7 +141,7 @@ public class AlarmDefinitionMySqlRepositoryImpl implements AlarmDefinitionReposi
String limit = offset != null ? " limit :limit" : "";
String sql = String.format(query, SubAlarmQueries.buildJoinClauseFor(dimensions), sbWhere, orderBy,
String sql = String.format(query, SubAlarmDefinitionQueries.buildJoinClauseFor(dimensions), sbWhere, orderBy,
limit);
Query<?> q = h.createQuery(sql).bind("tenantId", tenantId);

View File

@ -34,7 +34,7 @@ import org.skife.jdbi.v2.util.StringMapper;
import monasca.api.domain.model.alarmstatehistory.AlarmStateHistory;
import monasca.api.domain.model.alarmstatehistory.AlarmStateHistoryRepository;
import monasca.api.infrastructure.persistence.DimensionQueries;
import monasca.api.infrastructure.persistence.SubAlarmQueries;
import monasca.api.infrastructure.persistence.SubAlarmDefinitionQueries;
import monasca.common.persistence.BeanMapper;
/**
@ -86,7 +86,7 @@ public class AlarmStateHistoryVerticaRepositoryImpl implements AlarmStateHistory
// Find alarm Ids for dimensions
try (Handle h = mysql.open()) {
String sql = String.format(FIND_ALARMS_SQL, SubAlarmQueries.buildJoinClauseFor(dimensions));
String sql = String.format(FIND_ALARMS_SQL, SubAlarmDefinitionQueries.buildJoinClauseFor(dimensions));
Query<Map<String, Object>> query = h.createQuery(sql).bind("tenantId", tenantId);
DimensionQueries.bindDimensionsToQuery(query, dimensions);
alarmIds = query.map(StringMapper.FIRST).list();

View File

@ -18,33 +18,34 @@ import java.util.HashMap;
import java.util.Map;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
@Test
public class SubAlarmQueriesTest {
public class SubAlarmDefinitionQueriesTest {
public void metricQueriesSubAlarmQueriesTest1() {
String expectedResult =
" inner join sub_alarm_dimension d0 on d0.dimension_name = :dname0 "
+ "and d0.value = :dvalue0 and dim.sub_alarm_id = d0.sub_alarm_id inner join "
+ "sub_alarm_dimension d1 on d1.dimension_name = :dname1 and d1.value = :dvalue1 and dim"
+ ".sub_alarm_id = d1.sub_alarm_id";
" inner join sub_alarm_definition_dimension d0 on d0.dimension_name = :dname0 "
+ "and d0.value = :dvalue0 and dim.sub_alarm_definition_id = d0.sub_alarm_definition_id inner join "
+ "sub_alarm_definition_dimension d1 on d1.dimension_name = :dname1 and d1.value = :dvalue1 and dim"
+ ".sub_alarm_definition_id = d1.sub_alarm_definition_id";
Map<String, String> dimsMap = new HashMap<>();
dimsMap.put("foo", "bar");
dimsMap.put("biz", "baz");
assert (expectedResult.equals(SubAlarmQueries.buildJoinClauseFor(dimsMap)));
assertEquals(SubAlarmDefinitionQueries.buildJoinClauseFor(dimsMap), expectedResult);
}
public void metricQueriesSubAlarmQueriesTest2() {
String expectedResult = "";
Map<String, String> dimsMap = new HashMap<>();
assert (expectedResult.equals(SubAlarmQueries.buildJoinClauseFor(dimsMap)));
assertEquals(SubAlarmDefinitionQueries.buildJoinClauseFor(dimsMap), expectedResult);
}
public void metricQueriesSubAlarmQueriesTest3() {
String expectedResult = "";
Map<String, String> dimsMap = null;
assert (expectedResult.equals(SubAlarmQueries.buildJoinClauseFor(dimsMap)));
assertEquals(SubAlarmDefinitionQueries.buildJoinClauseFor(dimsMap), expectedResult);
}
}

View File

@ -53,6 +53,8 @@ public class AlarmDefinitionMySqlRepositoryImplTest {
private Handle handle;
private AlarmDefinitionRepository repo;
private List<String> alarmActions;
private AlarmDefinition alarmDef_123;
private AlarmDefinition alarmDef_234;
@BeforeClass
protected void setupClass() throws Exception {
@ -108,6 +110,15 @@ public class AlarmDefinitionMySqlRepositoryImplTest {
handle.execute("insert into sub_alarm_definition_dimension values ('222', 'metric_name', 'mem')");
handle.execute("insert into alarm_action values ('234', 'ALARM', '29387234')");
handle.execute("insert into alarm_action values ('234', 'ALARM', '77778687')");
alarmDef_123 = new AlarmDefinition("123", "90% CPU", null, "LOW",
"avg(hpcs.compute{flavor_id=777, image_id=888, metric_name=cpu, device=1}) > 10",
Arrays.asList("flavor_id", "image_id"), true, Arrays.asList("29387234", "77778687"),
Collections.<String>emptyList(), Collections.<String>emptyList());
alarmDef_234 = new AlarmDefinition("234","50% CPU", null, "LOW",
"avg(hpcs.compute{flavor_id=777, image_id=888, metric_name=mem}) > 20 and avg(hpcs.compute) < 100",
Arrays.asList("flavor_id", "image_id"), true, Arrays.asList("29387234", "77778687"),
Collections.<String>emptyList(), Collections.<String>emptyList());
}
public void shouldCreate() {
@ -173,16 +184,12 @@ public class AlarmDefinitionMySqlRepositoryImplTest {
}
public void shouldFindById() {
AlarmDefinition alarm = repo.findById("bob", "123");
assertEquals(alarmDef_123, repo.findById("bob", "123"));
assertEquals(alarm.getId(), "123");
assertEquals(alarm.getName(), "90% CPU");
assertEquals(alarm.getSeverity(), "LOW");
assertEquals(alarm.getExpression(),
"avg(hpcs.compute{flavor_id=777, image_id=888, metric_name=cpu, device=1}) > 10");
assertEquals(alarm.getMatchBy(), Arrays.asList("flavor_id", "image_id"));
assertEquals(alarm.isActionsEnabled(), true);
assertEquals(alarm.getAlarmActions(), alarmActions);
// Make sure it still finds AlarmDefinitions with no notifications
handle.execute("delete from alarm_action");
alarmDef_123.setAlarmActions(new ArrayList<String>(0));
assertEquals(alarmDef_123, repo.findById("bob", "123"));
}
@Test(groups = "database")
@ -238,34 +245,36 @@ public class AlarmDefinitionMySqlRepositoryImplTest {
}
public void shouldFind() {
List<AlarmDefinition> alarms = repo.find("bob", null, null, null);
assertEquals(Arrays.asList(alarmDef_123, alarmDef_234), repo.find("bob", null, null, null));
assertEquals(
alarms,
Arrays.asList(
new AlarmDefinition("123", "90% CPU", null, "LOW",
"avg(hpcs.compute{flavor_id=777, image_id=888, metric_name=cpu, device=1}) > 10",
Arrays.asList("flavor_id", "image_id"), true,
Arrays.asList("29387234", "77778687"), Collections.<String>emptyList(), Collections
.<String>emptyList()),
new AlarmDefinition(
"234",
"50% CPU",
null,
"LOW",
"avg(hpcs.compute{flavor_id=777, image_id=888, metric_name=mem}) > 20 and avg(hpcs.compute) < 100",
Arrays.asList("flavor_id", "image_id"), true,
Arrays.asList("29387234", "77778687"), Collections.<String>emptyList(), Collections
.<String>emptyList())));
// Make sure it still finds AlarmDefinitions with no notifications
handle.execute("delete from alarm_action");
alarmDef_123.setAlarmActions(new ArrayList<String>(0));
alarmDef_234.setAlarmActions(new ArrayList<String>(0));
assertEquals(Arrays.asList(alarmDef_123, alarmDef_234), repo.find("bob", null, null, null));
assertEquals(0, repo.find("bill", null, null, null).size());
}
public void shouldFindByDimension() {
final Map<String, String> dimensions = new HashMap<>();
dimensions.put("image_id", "888");
assertEquals(Arrays.asList(alarmDef_123, alarmDef_234),
repo.find("bob", null, dimensions, null));
dimensions.clear();
dimensions.put("device", "1");
assertEquals(Arrays.asList(alarmDef_123), repo.find("bob", null, dimensions, null));
dimensions.clear();
dimensions.put("Not real", "AA");
assertEquals(0, repo.find("bob", null, dimensions, null).size());
}
public void shouldFindByName() {
List<AlarmDefinition> alarms = repo.find("bob", "90% CPU", null, null);
assertEquals(Arrays.asList(alarmDef_123), repo.find("bob", "90% CPU", null, null));
assertEquals(alarms, Arrays.asList(new AlarmDefinition("123", "90% CPU", null, "LOW",
"avg(hpcs.compute{flavor_id=777, image_id=888, metric_name=cpu, device=1}) > 10", Arrays
.asList("flavor_id", "image_id"), true, Arrays.asList("29387234", "77778687"),
Collections.<String>emptyList(), Collections.<String>emptyList())));
assertEquals(0, repo.find("bob", "Does not exist", null, null).size());
}
public void shouldDeleteById() {
@ -276,5 +285,6 @@ public class AlarmDefinitionMySqlRepositoryImplTest {
fail();
} catch (EntityNotFoundException expected) {
}
assertEquals(Arrays.asList(alarmDef_234), repo.find("bob", null, null, null));
}
}

View File

@ -81,8 +81,8 @@ CREATE TABLE `sub_alarm` (
);
CREATE TABLE `alarm_action` (
`alarm_id` varchar(36) NOT NULL,
`alarm_definition_id` varchar(36) NOT NULL,
`alarm_state` varchar(20) NOT NULL check alarm_state in ('UNDETERMINED','OK','ALARM'),
`action_id` varchar(36) NOT NULL DEFAULT '',
PRIMARY KEY (`alarm_id`,`alarm_state`,`action_id`)
PRIMARY KEY (`alarm_definition_id`,`alarm_state`,`action_id`)
);