Wrap all lists in JSON object

Affected resources:
    alarm-definition-list   List alarm definitions for this tenant.
    alarm-history         Alarm state transition history.
    alarm-history-list   List alarms state history.
    alarm-list                List alarms for this tenant.
    measurement-list   List measurements for the specified metric.
    metric-list               List metrics for this tenant.
    metric-statistics     List measurement statistics for the specified metric.
    notification-list        List notifications for this tenant.

Change-Id: I9edc42c88c7e16a4fee8310d7dcfcf367bf2bfff
This commit is contained in:
Deklan Dieterly 2015-03-10 14:29:45 -06:00
parent c934fdb6f5
commit 68ef496cc9
6 changed files with 124 additions and 39 deletions

View File

@ -180,7 +180,9 @@ public final class Links {
} else { } else {
return elements; Paged paged = new Paged();
paged.elements = elements;
return paged;
} }
} }

View File

@ -81,7 +81,9 @@ public class MeasurementResource {
paged.elements = pagedList; paged.elements = pagedList;
return paged; return paged;
} else { } else {
return pagedList; Paged paged = new Paged();
paged.elements = pagedList;
return paged;
} }
} }
} }

View File

@ -33,6 +33,7 @@ import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import monasca.api.app.validation.Validation; import monasca.api.app.validation.Validation;
import monasca.api.domain.model.common.Paged;
import monasca.api.domain.model.statistic.StatisticRepo; import monasca.api.domain.model.statistic.StatisticRepo;
import monasca.api.domain.model.statistic.Statistics; import monasca.api.domain.model.statistic.Statistics;
@ -55,7 +56,7 @@ public class StatisticResource {
@GET @GET
@Timed @Timed
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public List<Statistics> get(@HeaderParam("X-Tenant-Id") String tenantId, public Object get(@HeaderParam("X-Tenant-Id") String tenantId,
@QueryParam("name") String name, @QueryParam("dimensions") String dimensionsStr, @QueryParam("name") String name, @QueryParam("dimensions") String dimensionsStr,
@QueryParam("start_time") String startTimeStr, @QueryParam("end_time") String endTimeStr, @QueryParam("start_time") String startTimeStr, @QueryParam("end_time") String endTimeStr,
@QueryParam("statistics") String statisticsStr, @QueryParam("statistics") String statisticsStr,
@ -73,6 +74,11 @@ public class StatisticResource {
Strings.isNullOrEmpty(dimensionsStr) ? null : Validation.parseAndValidateNameAndDimensions( Strings.isNullOrEmpty(dimensionsStr) ? null : Validation.parseAndValidateNameAndDimensions(
name, dimensionsStr); name, dimensionsStr);
return repo.find(tenantId, name, dimensions, startTime, endTime, statistics, period); List<Statistics> statisticsList =
repo.find(tenantId, name, dimensions, startTime, endTime, statistics, period);
Paged paged = new Paged();
paged.elements = statisticsList;
return paged;
} }
} }

View File

@ -36,7 +36,7 @@ databaseConfiguration:
# Uncomment if databaseType is influxDB # Uncomment if databaseType is influxDB
influxDB: influxDB:
# version can be (V8 | V9) # version can be (V8 | V9)
# If noversion set then defaults to V8. # If no version set then defaults to V8.
version: V8 version: V8
# Used only if version is V9. # Used only if version is V9.
maxHttpConnections: 100 maxHttpConnections: 100

View File

@ -40,6 +40,7 @@ import org.testng.annotations.Test;
import monasca.api.app.AlarmDefinitionService; import monasca.api.app.AlarmDefinitionService;
import monasca.api.app.command.CreateAlarmDefinitionCommand; import monasca.api.app.command.CreateAlarmDefinitionCommand;
import monasca.api.app.command.UpdateAlarmDefinitionCommand; import monasca.api.app.command.UpdateAlarmDefinitionCommand;
import monasca.api.domain.model.common.Paged;
import monasca.common.model.alarm.AlarmExpression; import monasca.common.model.alarm.AlarmExpression;
import monasca.api.domain.exception.EntityNotFoundException; import monasca.api.domain.exception.EntityNotFoundException;
import monasca.api.domain.model.alarmdefinition.AlarmDefinition; import monasca.api.domain.model.alarmdefinition.AlarmDefinition;
@ -101,9 +102,9 @@ public class AlarmDefinitionResourceTest extends AbstractMonApiResourceTest {
assertEquals(location, "/v2.0/alarm-definitions/" + newAlarm.getId()); assertEquals(location, "/v2.0/alarm-definitions/" + newAlarm.getId());
assertEquals(newAlarm, alarm); assertEquals(newAlarm, alarm);
verify(service).create(eq("abc"), eq("Disk Exceeds 1k Operations"), any(String.class), verify(service).create(eq("abc"), eq("Disk Exceeds 1k Operations"), any(String.class),
eq("LOW"), eq(expression), eq(AlarmExpression.of(expression)), eq("LOW"), eq(expression), eq(AlarmExpression.of(expression)),
eq(Arrays.asList("service", "instance_id")), any(List.class), any(List.class), eq(Arrays.asList("service", "instance_id")), any(List.class),
any(List.class)); any(List.class), any(List.class));
} }
public void shouldUpdate() { public void shouldUpdate() {
@ -115,10 +116,10 @@ public class AlarmDefinitionResourceTest extends AbstractMonApiResourceTest {
.resource("/v2.0/alarm-definitions/123") .resource("/v2.0/alarm-definitions/123")
.header("X-Tenant-Id", "abc") .header("X-Tenant-Id", "abc")
.header("Content-Type", MediaType.APPLICATION_JSON) .header("Content-Type", MediaType.APPLICATION_JSON)
.put( .put(ClientResponse.class,
ClientResponse.class, new UpdateAlarmDefinitionCommand("Disk Exceeds 1k Operations", null, expression,
new UpdateAlarmDefinitionCommand("Disk Exceeds 1k Operations", null, expression, Arrays.asList("service", "instance_id"), "LOW",
Arrays.asList("service", "instance_id"), "LOW", true, alarmActions, null, null)); true, alarmActions, null, null));
assertEquals(response.getStatus(), 200); assertEquals(response.getStatus(), 200);
verify(service).update(eq("abc"), eq("123"), any(AlarmExpression.class), verify(service).update(eq("abc"), eq("123"), any(AlarmExpression.class),
@ -153,8 +154,8 @@ public class AlarmDefinitionResourceTest extends AbstractMonApiResourceTest {
expression, Arrays.asList("service", "instance_id"), "LOW", alarmActions, null, null)); expression, Arrays.asList("service", "instance_id"), "LOW", alarmActions, null, null));
ErrorMessages.assertThat(response.getEntity(String.class)).matches("unprocessable_entity", 422, ErrorMessages.assertThat(response.getEntity(String.class)).matches("unprocessable_entity", 422,
"The alarm expression is invalid", "The alarm expression is invalid",
"More than one value was given for dimension instance_id"); "More than one value was given for dimension instance_id");
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -175,7 +176,8 @@ public class AlarmDefinitionResourceTest extends AbstractMonApiResourceTest {
createResponseFor("{\"alarmasdf\"::{\"name\":\"Disk Exceeds 1k Operations\"}}"); createResponseFor("{\"alarmasdf\"::{\"name\":\"Disk Exceeds 1k Operations\"}}");
ErrorMessages.assertThat(response.getEntity(String.class)).matches("bad_request", 400, ErrorMessages.assertThat(response.getEntity(String.class)).matches("bad_request", 400,
"Unable to process the provided JSON", "Unexpected character (':'"); "Unable to process the provided JSON",
"Unexpected character (':'");
} }
public void shouldErrorOnCreateWithInvalidOperator() { public void shouldErrorOnCreateWithInvalidOperator() {
@ -186,7 +188,8 @@ public class AlarmDefinitionResourceTest extends AbstractMonApiResourceTest {
expression, Arrays.asList("service", "instance_id"), "LOW", alarmActions, null, null)); expression, Arrays.asList("service", "instance_id"), "LOW", alarmActions, null, null));
ErrorMessages.assertThat(response.getEntity(String.class)).matches("unprocessable_entity", 422, ErrorMessages.assertThat(response.getEntity(String.class)).matches("unprocessable_entity", 422,
"The alarm expression is invalid", "Syntax Error"); "The alarm expression is invalid",
"Syntax Error");
} }
public void shouldErrorOnCreateWith0Period() { public void shouldErrorOnCreateWith0Period() {
@ -197,7 +200,7 @@ public class AlarmDefinitionResourceTest extends AbstractMonApiResourceTest {
expression, Arrays.asList("service", "instance_id"), "LOW", alarmActions, null, null)); expression, Arrays.asList("service", "instance_id"), "LOW", alarmActions, null, null));
ErrorMessages.assertThat(response.getEntity(String.class)).matches("unprocessable_entity", 422, ErrorMessages.assertThat(response.getEntity(String.class)).matches("unprocessable_entity", 422,
"Period must not be 0"); "Period must not be 0");
} }
public void shouldErrorOnCreateWithNonMod60Period() { public void shouldErrorOnCreateWithNonMod60Period() {
@ -208,7 +211,7 @@ public class AlarmDefinitionResourceTest extends AbstractMonApiResourceTest {
expression, Arrays.asList("service", "instance_id"), "LOW", alarmActions, null, null)); expression, Arrays.asList("service", "instance_id"), "LOW", alarmActions, null, null));
ErrorMessages.assertThat(response.getEntity(String.class)).matches("unprocessable_entity", 422, ErrorMessages.assertThat(response.getEntity(String.class)).matches("unprocessable_entity", 422,
"Period 61 must be a multiple of 60"); "Period 61 must be a multiple of 60");
} }
public void shouldErrorOnCreateWithPeriodsLessThan1() { public void shouldErrorOnCreateWithPeriodsLessThan1() {
@ -219,7 +222,7 @@ public class AlarmDefinitionResourceTest extends AbstractMonApiResourceTest {
expression, Arrays.asList("service", "instance_id"), "LOW", alarmActions, null, null)); expression, Arrays.asList("service", "instance_id"), "LOW", alarmActions, null, null));
ErrorMessages.assertThat(response.getEntity(String.class)).matches("unprocessable_entity", 422, ErrorMessages.assertThat(response.getEntity(String.class)).matches("unprocessable_entity", 422,
"Periods 0 must be greater than or equal to 1"); "Periods 0 must be greater than or equal to 1");
} }
public void shouldErrorOnCreateWithPeriodTimesPeriodsGT2Weeks() { public void shouldErrorOnCreateWithPeriodTimesPeriodsGT2Weeks() {
@ -246,10 +249,8 @@ public class AlarmDefinitionResourceTest extends AbstractMonApiResourceTest {
ErrorMessages ErrorMessages
.assertThat(response.getEntity(String.class)) .assertThat(response.getEntity(String.class))
.matches( .matches("unprocessable_entity", 422,
"unprocessable_entity", "Name 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 must be 255 characters or less");
422,
"Name 012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 must be 255 characters or less");
} }
public void shouldErrorOnCreateWithTooLongAlarmAction() { public void shouldErrorOnCreateWithTooLongAlarmAction() {
@ -262,14 +263,35 @@ public class AlarmDefinitionResourceTest extends AbstractMonApiResourceTest {
ErrorMessages ErrorMessages
.assertThat(response.getEntity(String.class)) .assertThat(response.getEntity(String.class))
.matches("unprocessable_entity", 422, .matches("unprocessable_entity", 422,
"Alarm action 012345678901234567890123456789012345678901234567890 must be 50 characters or less"); "Alarm action 012345678901234567890123456789012345678901234567890 must be 50 characters or less");
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void shouldList() { public void shouldList() {
List<AlarmDefinition> alarms =
client().resource("/v2.0/alarm-definitions").header("X-Tenant-Id", "abc") Map
.get(new GenericType<List<AlarmDefinition>>() {}); lhm =
(Map) client().resource("/v2.0/alarm-definitions").header("X-Tenant-Id", "abc")
.get(Paged.class).elements.get(0);
AlarmDefinition
ad =
new AlarmDefinition((String) lhm.get("id"), (String) lhm.get("name"),
(String) lhm.get("description"), (String) lhm.get("severity"),
(String) lhm.get("expression"), (List<String>) lhm.get("match_by"),
(boolean) lhm.get("actions_enabled"),
(List<String>) lhm.get("alarm_actions"),
(List<String>) lhm.get("ok_actions"),
(List<String>) lhm.get("undetermined_actions"));
List<Map<String, String>> links = (List<Map<String, String>>) lhm.get("links");
List<Link>
linksList =
Arrays.asList(new Link(links.get(0).get("rel"), links.get(0).get("href")));
ad.setLinks(linksList);
List<AlarmDefinition> alarms = Arrays.asList(ad);
assertEquals(alarms, Arrays.asList(alarmItem)); assertEquals(alarms, Arrays.asList(alarmItem));
verify(repo).find(eq("abc"), anyString(), (Map<String, String>) anyMap(), anyString()); verify(repo).find(eq("abc"), anyString(), (Map<String, String>) anyMap(), anyString());
@ -277,9 +299,31 @@ public class AlarmDefinitionResourceTest extends AbstractMonApiResourceTest {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void shouldListByName() throws Exception { public void shouldListByName() throws Exception {
List<AlarmDefinition> alarms =
client().resource("/v2.0/alarm-definitions?name=" + URLEncoder.encode("foo bar baz", "UTF-8")) Map
.header("X-Tenant-Id", "abc").get(new GenericType<List<AlarmDefinition>>() {}); lhm =
(Map) client()
.resource("/v2.0/alarm-definitions?name=" + URLEncoder.encode("foo bar baz", "UTF-8"))
.header("X-Tenant-Id", "abc").get(Paged.class).elements.get(0);
AlarmDefinition
ad =
new AlarmDefinition((String) lhm.get("id"), (String) lhm.get("name"),
(String) lhm.get("description"), (String) lhm.get("severity"),
(String) lhm.get("expression"), (List<String>) lhm.get("match_by"),
(boolean) lhm.get("actions_enabled"),
(List<String>) lhm.get("alarm_actions"),
(List<String>) lhm.get("ok_actions"),
(List<String>) lhm.get("undetermined_actions"));
List<Map<String, String>> links = (List<Map<String, String>>) lhm.get("links");
List<Link>
linksList =
Arrays.asList(new Link(links.get(0).get("rel"), links.get(0).get("href")));
ad.setLinks(linksList);
List<AlarmDefinition> alarms = Arrays.asList(ad);
assertEquals(alarms, Arrays.asList(alarmItem)); assertEquals(alarms, Arrays.asList(alarmItem));
verify(repo).find(eq("abc"), eq("foo bar baz"), (Map<String, String>) anyMap(), anyString()); verify(repo).find(eq("abc"), eq("foo bar baz"), (Map<String, String>) anyMap(), anyString());
@ -296,7 +340,8 @@ public class AlarmDefinitionResourceTest extends AbstractMonApiResourceTest {
doThrow(new EntityNotFoundException(null)).when(repo).findById(eq("abc"), eq("999")); doThrow(new EntityNotFoundException(null)).when(repo).findById(eq("abc"), eq("999"));
try { try {
client().resource("/v2.0/alarm-definitions/999").header("X-Tenant-Id", "abc").get(AlarmDefinition.class); client().resource("/v2.0/alarm-definitions/999").header("X-Tenant-Id", "abc").get(
AlarmDefinition.class);
fail(); fail();
} catch (Exception e) { } catch (Exception e) {
assertTrue(e.getMessage().contains("404")); assertTrue(e.getMessage().contains("404"));
@ -325,7 +370,8 @@ public class AlarmDefinitionResourceTest extends AbstractMonApiResourceTest {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void should500OnInternalException() { public void should500OnInternalException() {
doThrow(new RuntimeException("")).when(repo).find(anyString(), anyString(), doThrow(new RuntimeException("")).when(repo).find(anyString(), anyString(),
(Map<String, String>) anyObject(), anyString()); (Map<String, String>) anyObject(),
anyString());
try { try {
client().resource("/v2.0/alarm-definitions").header("X-Tenant-Id", "abc").get(List.class); client().resource("/v2.0/alarm-definitions").header("X-Tenant-Id", "abc").get(List.class);
@ -338,10 +384,16 @@ public class AlarmDefinitionResourceTest extends AbstractMonApiResourceTest {
public void shouldHydateLinksOnList() { public void shouldHydateLinksOnList() {
List<Link> expected = List<Link> expected =
Arrays.asList(new Link("self", "/v2.0/alarm-definitions/123")); Arrays.asList(new Link("self", "/v2.0/alarm-definitions/123"));
List<Link> links =
client().resource("/v2.0/alarm-definitions").header("X-Tenant-Id", "abc") Map
.get(new GenericType<List<AlarmDefinition>>() {}).get(0).getLinks(); lhm =
assertEquals(links, expected); (Map) client().resource("/v2.0/alarm-definitions").header("X-Tenant-Id", "abc")
.get(Paged.class).elements.get(0);
List<Map<String, String>> links = (List<Map<String, String>>) lhm.get("links");
List<Link> actual = Arrays.asList(new Link(links.get(0).get("rel"), links.get(0).get("href")));
assertEquals(actual, expected);
} }
public void shouldHydateLinksOnGet() { public void shouldHydateLinksOnGet() {

View File

@ -18,15 +18,20 @@ import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.GenericType; import com.sun.jersey.api.client.GenericType;
import monasca.api.app.command.CreateNotificationMethodCommand; import monasca.api.app.command.CreateNotificationMethodCommand;
import monasca.api.domain.exception.EntityNotFoundException; import monasca.api.domain.exception.EntityNotFoundException;
import monasca.api.domain.model.common.Link;
import monasca.api.domain.model.common.Paged;
import monasca.api.domain.model.notificationmethod.NotificationMethod; import monasca.api.domain.model.notificationmethod.NotificationMethod;
import monasca.api.domain.model.notificationmethod.NotificationMethodRepo; import monasca.api.domain.model.notificationmethod.NotificationMethodRepo;
import monasca.api.domain.model.notificationmethod.NotificationMethodType; import monasca.api.domain.model.notificationmethod.NotificationMethodType;
import monasca.api.resource.exception.ErrorMessages; import monasca.api.resource.exception.ErrorMessages;
import org.mockito.internal.matchers.Not;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.anyString;
@ -186,9 +191,27 @@ public class NotificationMethodResourceTest extends AbstractMonApiResourceTest {
} }
public void shouldList() { public void shouldList() {
List<NotificationMethod> notificationMethods =
client().resource("/v2.0/notification-methods").header("X-Tenant-Id", "abc") Map
.get(new GenericType<List<NotificationMethod>>() {}); lhm =
(Map) client().resource("/v2.0/notification-methods").header("X-Tenant-Id", "abc")
.get(Paged.class).elements.get(0);
NotificationMethod
nm =
new NotificationMethod((String) lhm.get("id"), (String) lhm.get("name"),
NotificationMethodType.fromJson((String) lhm.get("type")),
(String) lhm.get("address"));
List<Map<String, String>> links = (List<Map<String, String>>) lhm.get("links");
List<Link>
linksList =
Arrays.asList(new Link(links.get(0).get("rel"), links.get(0).get("href")));
nm.setLinks(linksList);
List<NotificationMethod> notificationMethods = Arrays.asList(nm);
assertEquals(notificationMethods, Arrays.asList(notificationMethod)); assertEquals(notificationMethods, Arrays.asList(notificationMethod));
verify(repo).find(eq("abc"), anyString()); verify(repo).find(eq("abc"), anyString());