From 84afe874990ac0efd220ff3013c360dcd1662001 Mon Sep 17 00:00:00 2001 From: Deklan Dieterly Date: Tue, 1 Apr 2014 13:41:49 -0600 Subject: [PATCH] Add Swagger infrastructure. --- pom.xml | 6 + .../com/hpcloud/mon/MonApiApplication.java | 239 ++++++------- .../hpcloud/mon/domain/model/alarm/Alarm.java | 320 +++++++++--------- .../hpcloud/mon/resource/AlarmResource.java | 10 +- 4 files changed, 304 insertions(+), 271 deletions(-) diff --git a/pom.xml b/pom.xml index b1f221b53..8299f2717 100644 --- a/pom.xml +++ b/pom.xml @@ -166,6 +166,7 @@ + com.hpcloud @@ -186,6 +187,11 @@ ${dropwizard.version} test + + com.wordnik + swagger-jaxrs_2.9.1 + 1.3.1 + diff --git a/src/main/java/com/hpcloud/mon/MonApiApplication.java b/src/main/java/com/hpcloud/mon/MonApiApplication.java index 7a09d761b..fb6ea6e96 100644 --- a/src/main/java/com/hpcloud/mon/MonApiApplication.java +++ b/src/main/java/com/hpcloud/mon/MonApiApplication.java @@ -1,133 +1,144 @@ package com.hpcloud.mon; -import io.dropwizard.Application; -import io.dropwizard.jdbi.bundles.DBIExceptionsBundle; -import io.dropwizard.setup.Bootstrap; -import io.dropwizard.setup.Environment; - -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; - -import javax.servlet.FilterRegistration.Dynamic; -import javax.ws.rs.ext.ExceptionMapper; - import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.PropertyNamingStrategy; import com.hp.csbu.cc.middleware.TokenAuth; import com.hpcloud.messaging.kafka.KafkaHealthCheck; import com.hpcloud.mon.infrastructure.servlet.PostAuthenticationFilter; import com.hpcloud.mon.infrastructure.servlet.PreAuthenticationFilter; -import com.hpcloud.mon.resource.AlarmResource; -import com.hpcloud.mon.resource.MeasurementResource; -import com.hpcloud.mon.resource.MetricResource; -import com.hpcloud.mon.resource.NotificationMethodResource; -import com.hpcloud.mon.resource.StatisticResource; -import com.hpcloud.mon.resource.VersionResource; -import com.hpcloud.mon.resource.exception.ConstraintViolationExceptionMapper; -import com.hpcloud.mon.resource.exception.EntityExistsExceptionMapper; -import com.hpcloud.mon.resource.exception.EntityNotFoundExceptionMapper; -import com.hpcloud.mon.resource.exception.IllegalArgumentExceptionMapper; -import com.hpcloud.mon.resource.exception.InvalidEntityExceptionMapper; -import com.hpcloud.mon.resource.exception.JsonMappingExceptionManager; -import com.hpcloud.mon.resource.exception.JsonProcessingExceptionMapper; -import com.hpcloud.mon.resource.exception.ResourceNotFoundExceptionMapper; -import com.hpcloud.mon.resource.exception.ThrowableExceptionMapper; +import com.hpcloud.mon.resource.*; +import com.hpcloud.mon.resource.exception.*; import com.hpcloud.util.Injector; +import com.wordnik.swagger.config.ConfigFactory; +import com.wordnik.swagger.config.ScannerFactory; +import com.wordnik.swagger.config.SwaggerConfig; +import com.wordnik.swagger.jaxrs.config.DefaultJaxrsScanner; +import com.wordnik.swagger.jaxrs.listing.ApiDeclarationProvider; +import com.wordnik.swagger.jaxrs.listing.ApiListingResourceJSON; +import com.wordnik.swagger.jaxrs.listing.ResourceListingProvider; +import com.wordnik.swagger.jaxrs.reader.DefaultJaxrsApiReader; +import com.wordnik.swagger.reader.ClassReaders; +import io.dropwizard.Application; +import io.dropwizard.jdbi.bundles.DBIExceptionsBundle; +import io.dropwizard.setup.Bootstrap; +import io.dropwizard.setup.Environment; + +import javax.servlet.FilterRegistration.Dynamic; +import javax.ws.rs.ext.ExceptionMapper; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; /** * Monitoring API application. - * + * * @author Jonathan Halterman */ public class MonApiApplication extends Application { - public static void main(String[] args) throws Exception { - new MonApiApplication().run(args); - } - - @Override - public void initialize(Bootstrap bootstrap) { - /** Configure bundles */ - bootstrap.addBundle(new DBIExceptionsBundle()); - } - - @Override - public String getName() { - return "HP Cloud Monitoring"; - } - - @Override - public void run(MonApiConfiguration config, Environment environment) throws Exception { - /** Wire services */ - Injector.registerModules(new MonApiModule(environment, config)); - - /** Configure resources */ - environment.jersey().register(Injector.getInstance(VersionResource.class)); - environment.jersey().register(Injector.getInstance(AlarmResource.class)); - environment.jersey().register(Injector.getInstance(MetricResource.class)); - environment.jersey().register(Injector.getInstance(MeasurementResource.class)); - environment.jersey().register(Injector.getInstance(StatisticResource.class)); - environment.jersey().register(Injector.getInstance(NotificationMethodResource.class)); - - /** Configure providers */ - removeExceptionMappers(environment.jersey().getResourceConfig().getSingletons()); - environment.jersey().register(new EntityExistsExceptionMapper()); - environment.jersey().register(new EntityNotFoundExceptionMapper()); - environment.jersey().register(new ResourceNotFoundExceptionMapper()); - environment.jersey().register(new IllegalArgumentExceptionMapper()); - environment.jersey().register(new InvalidEntityExceptionMapper()); - environment.jersey().register(new JsonProcessingExceptionMapper()); - environment.jersey().register(new JsonMappingExceptionManager()); - environment.jersey().register(new ConstraintViolationExceptionMapper()); - environment.jersey().register(new ThrowableExceptionMapper() { - }); - - /** Configure Jackson */ - environment.getObjectMapper().setPropertyNamingStrategy( - PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); - environment.getObjectMapper().enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY); - - /** Configure health checks */ - environment.healthChecks().register("kafka", new KafkaHealthCheck(config.kafka)); - - /** Configure auth filters */ - if (config.middleware.enabled) { - Map authInitParams = new HashMap(); - authInitParams.put("ServiceIds", config.middleware.serviceIds); - authInitParams.put("EndpointIds", config.middleware.endpointIds); - authInitParams.put("ServerVIP", config.middleware.serverVIP); - authInitParams.put("ServerPort", config.middleware.serverPort); - authInitParams.put("ConnTimeout", config.middleware.connTimeout); - authInitParams.put("ConnSSLClientAuth", config.middleware.connSSLClientAuth); - authInitParams.put("Keystore", config.middleware.keystore); - authInitParams.put("KeystorePass", config.middleware.keystorePass); - authInitParams.put("Truststore", config.middleware.truststore); - authInitParams.put("TruststorePass", config.middleware.truststorePass); - authInitParams.put("ConnPoolMaxActive", config.middleware.connPoolMaxActive); - authInitParams.put("ConnPoolMaxIdle", config.middleware.connPoolMaxActive); - authInitParams.put("ConnPoolEvictPeriod", config.middleware.connPoolEvictPeriod); - authInitParams.put("ConnPoolMinIdleTime", config.middleware.connPoolMinIdleTime); - authInitParams.put("ConnRetryTimes", config.middleware.connRetryTimes); - authInitParams.put("ConnRetryInterval", config.middleware.connRetryInterval); - - environment.servlets() - .addFilter("pre-auth", new PreAuthenticationFilter()) - .addMappingForUrlPatterns(null, true, "/*"); - Dynamic filter = environment.servlets().addFilter("token-auth", new TokenAuth()); - filter.addMappingForUrlPatterns(null, true, "/*"); - filter.setInitParameters(authInitParams); - environment.servlets() - .addFilter("post-auth", new PostAuthenticationFilter(config.middleware.rolesToMatch)) - .addMappingForUrlPatterns(null, true, "/*"); + public static void main(String[] args) throws Exception { + new MonApiApplication().run(args); } - } - private void removeExceptionMappers(Set items) { - for (Iterator i = items.iterator(); i.hasNext();) { - Object o = i.next(); - if (o instanceof ExceptionMapper) - i.remove(); + @Override + public void initialize(Bootstrap bootstrap) { + /** Configure bundles */ + bootstrap.addBundle(new DBIExceptionsBundle()); + } + + @Override + public String getName() { + return "HP Cloud Monitoring"; + } + + @Override + public void run(MonApiConfiguration config, Environment environment) throws Exception { + /** Wire services */ + Injector.registerModules(new MonApiModule(environment, config)); + + /** Configure resources */ + environment.jersey().register(Injector.getInstance(VersionResource.class)); + environment.jersey().register(Injector.getInstance(AlarmResource.class)); + environment.jersey().register(Injector.getInstance(MetricResource.class)); + environment.jersey().register(Injector.getInstance(MeasurementResource.class)); + environment.jersey().register(Injector.getInstance(StatisticResource.class)); + environment.jersey().register(Injector.getInstance(NotificationMethodResource.class)); + + /** Configure providers */ + removeExceptionMappers(environment.jersey().getResourceConfig().getSingletons()); + environment.jersey().register(new EntityExistsExceptionMapper()); + environment.jersey().register(new EntityNotFoundExceptionMapper()); + environment.jersey().register(new ResourceNotFoundExceptionMapper()); + environment.jersey().register(new IllegalArgumentExceptionMapper()); + environment.jersey().register(new InvalidEntityExceptionMapper()); + environment.jersey().register(new JsonProcessingExceptionMapper()); + environment.jersey().register(new JsonMappingExceptionManager()); + environment.jersey().register(new ConstraintViolationExceptionMapper()); + environment.jersey().register(new ThrowableExceptionMapper() { + }); + + /** Configure Jackson */ + environment.getObjectMapper().setPropertyNamingStrategy( + PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); + environment.getObjectMapper().enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY); + + /** Configure health checks */ + environment.healthChecks().register("kafka", new KafkaHealthCheck(config.kafka)); + + /** Configure auth filters */ + if (config.middleware.enabled) { + Map authInitParams = new HashMap(); + authInitParams.put("ServiceIds", config.middleware.serviceIds); + authInitParams.put("EndpointIds", config.middleware.endpointIds); + authInitParams.put("ServerVIP", config.middleware.serverVIP); + authInitParams.put("ServerPort", config.middleware.serverPort); + authInitParams.put("ConnTimeout", config.middleware.connTimeout); + authInitParams.put("ConnSSLClientAuth", config.middleware.connSSLClientAuth); + authInitParams.put("Keystore", config.middleware.keystore); + authInitParams.put("KeystorePass", config.middleware.keystorePass); + authInitParams.put("Truststore", config.middleware.truststore); + authInitParams.put("TruststorePass", config.middleware.truststorePass); + authInitParams.put("ConnPoolMaxActive", config.middleware.connPoolMaxActive); + authInitParams.put("ConnPoolMaxIdle", config.middleware.connPoolMaxActive); + authInitParams.put("ConnPoolEvictPeriod", config.middleware.connPoolEvictPeriod); + authInitParams.put("ConnPoolMinIdleTime", config.middleware.connPoolMinIdleTime); + authInitParams.put("ConnRetryTimes", config.middleware.connRetryTimes); + authInitParams.put("ConnRetryInterval", config.middleware.connRetryInterval); + + environment.servlets() + .addFilter("pre-auth", new PreAuthenticationFilter()) + .addMappingForUrlPatterns(null, true, "/*"); + Dynamic filter = environment.servlets().addFilter("token-auth", new TokenAuth()); + filter.addMappingForUrlPatterns(null, true, "/*"); + filter.setInitParameters(authInitParams); + environment.servlets() + .addFilter("post-auth", new PostAuthenticationFilter(config.middleware.rolesToMatch)) + .addMappingForUrlPatterns(null, true, "/*"); + } + + environment.jersey().register(new ApiListingResourceJSON()); + + // Swagger providers + environment.jersey().register(new ApiDeclarationProvider()); + environment.jersey().register(new ResourceListingProvider()); + + // Swagger Scanner, which finds all the resources for @Api Annotations + ScannerFactory.setScanner(new DefaultJaxrsScanner()); + + // Add the reader, which scans the resources and extracts the resource information + ClassReaders.setReader(new DefaultJaxrsApiReader()); + + // Set the swagger config options + SwaggerConfig swaggerConfig = ConfigFactory.config(); + swaggerConfig.setApiVersion("1.0.1"); + swaggerConfig.setBasePath("http://localhost:8000"); + } + + private void removeExceptionMappers(Set items) { + for (Iterator i = items.iterator(); i.hasNext(); ) { + Object o = i.next(); + if (o instanceof ExceptionMapper) + i.remove(); + } } - } } diff --git a/src/main/java/com/hpcloud/mon/domain/model/alarm/Alarm.java b/src/main/java/com/hpcloud/mon/domain/model/alarm/Alarm.java index 5be87c5f5..0f725d779 100644 --- a/src/main/java/com/hpcloud/mon/domain/model/alarm/Alarm.java +++ b/src/main/java/com/hpcloud/mon/domain/model/alarm/Alarm.java @@ -1,190 +1,198 @@ package com.hpcloud.mon.domain.model.alarm; -import java.util.List; - import com.hpcloud.mon.common.model.alarm.AlarmState; import com.hpcloud.mon.domain.common.AbstractEntity; import com.hpcloud.mon.domain.model.common.Link; import com.hpcloud.mon.domain.model.common.Linked; +import com.wordnik.swagger.annotations.ApiModel; +import com.wordnik.swagger.annotations.ApiModelProperty; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import java.util.List; + +@ApiModel(value = "An alarm is a devops's best friend") +@XmlRootElement(name = "Alarm") public class Alarm extends AbstractEntity implements Linked { - private List links; - private String name; - private String description = ""; - private String expression; - private AlarmState state; - private boolean enabled; - private List alarmActions; - private List okActions; - private List undeterminedActions; + private List links; + private String name; + private String description = ""; + private String expression; + private AlarmState state; + private boolean enabled; + private List alarmActions; + private List okActions; + private List undeterminedActions; - public Alarm() { - } + public Alarm() { + } - public Alarm(String id, String name, String description, String expression, AlarmState state, - boolean enabled, List alarmActions, List okActions, - List undeterminedActions) { - this.id = id; - this.name = name; - setDescription(description); - setExpression(expression); - setState(state); - setEnabled(enabled); - setAlarmActions(alarmActions); - setOkActions(okActions); - setUndeterminedActions(undeterminedActions); - } + public Alarm(String id, String name, String description, String expression, AlarmState state, + boolean enabled, List alarmActions, List okActions, + List undeterminedActions) { + this.id = id; + this.name = name; + setDescription(description); + setExpression(expression); + setState(state); + setEnabled(enabled); + setAlarmActions(alarmActions); + setOkActions(okActions); + setUndeterminedActions(undeterminedActions); + } - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!super.equals(obj)) - return false; - if (getClass() != obj.getClass()) - return false; - Alarm other = (Alarm) obj; - if (alarmActions == null) { - if (other.alarmActions != null) - return false; - } else if (!alarmActions.equals(other.alarmActions)) - return false; - if (description == null) { - if (other.description != null) - return false; - } else if (!description.equals(other.description)) - return false; - if (enabled != other.enabled) - return false; - if (expression == null) { - if (other.expression != null) - return false; - } else if (!expression.equals(other.expression)) - return false; - if (links == null) { - if (other.links != null) - return false; - } else if (!links.equals(other.links)) - return false; - if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - if (okActions == null) { - if (other.okActions != null) - return false; - } else if (!okActions.equals(other.okActions)) - return false; - if (state != other.state) - return false; - if (undeterminedActions == null) { - if (other.undeterminedActions != null) - return false; - } else if (!undeterminedActions.equals(other.undeterminedActions)) - return false; - return true; - } + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!super.equals(obj)) + return false; + if (getClass() != obj.getClass()) + return false; + Alarm other = (Alarm) obj; + if (alarmActions == null) { + if (other.alarmActions != null) + return false; + } else if (!alarmActions.equals(other.alarmActions)) + return false; + if (description == null) { + if (other.description != null) + return false; + } else if (!description.equals(other.description)) + return false; + if (enabled != other.enabled) + return false; + if (expression == null) { + if (other.expression != null) + return false; + } else if (!expression.equals(other.expression)) + return false; + if (links == null) { + if (other.links != null) + return false; + } else if (!links.equals(other.links)) + return false; + if (name == null) { + if (other.name != null) + return false; + } else if (!name.equals(other.name)) + return false; + if (okActions == null) { + if (other.okActions != null) + return false; + } else if (!okActions.equals(other.okActions)) + return false; + if (state != other.state) + return false; + if (undeterminedActions == null) { + if (other.undeterminedActions != null) + return false; + } else if (!undeterminedActions.equals(other.undeterminedActions)) + return false; + return true; + } - public List getAlarmActions() { - return alarmActions; - } + public List getAlarmActions() { + return alarmActions; + } - public String getDescription() { - return description; - } + public String getDescription() { + return description; + } - public String getExpression() { - return expression; - } + public String getExpression() { + return expression; + } - public String getId() { - return id; - } + public String getId() { + return id; + } - public List getLinks() { - return links; - } + public List getLinks() { + return links; + } - public String getName() { - return name; - } + public String getName() { + return name; + } - public List getOkActions() { - return okActions; - } + public List getOkActions() { + return okActions; + } - public AlarmState getState() { - return state; - } + public AlarmState getState() { + return state; + } - public List getUndeterminedActions() { - return undeterminedActions; - } + public List getUndeterminedActions() { + return undeterminedActions; + } - @Override - public int hashCode() { - final int prime = 31; - int result = super.hashCode(); - result = prime * result + ((alarmActions == null) ? 0 : alarmActions.hashCode()); - result = prime * result + ((description == null) ? 0 : description.hashCode()); - result = prime * result + (enabled ? 1231 : 1237); - result = prime * result + ((expression == null) ? 0 : expression.hashCode()); - result = prime * result + ((links == null) ? 0 : links.hashCode()); - result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + ((okActions == null) ? 0 : okActions.hashCode()); - result = prime * result + ((state == null) ? 0 : state.hashCode()); - result = prime * result + ((undeterminedActions == null) ? 0 : undeterminedActions.hashCode()); - return result; - } + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + ((alarmActions == null) ? 0 : alarmActions.hashCode()); + result = prime * result + ((description == null) ? 0 : description.hashCode()); + result = prime * result + (enabled ? 1231 : 1237); + result = prime * result + ((expression == null) ? 0 : expression.hashCode()); + result = prime * result + ((links == null) ? 0 : links.hashCode()); + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((okActions == null) ? 0 : okActions.hashCode()); + result = prime * result + ((state == null) ? 0 : state.hashCode()); + result = prime * result + ((undeterminedActions == null) ? 0 : undeterminedActions.hashCode()); + return result; + } - public boolean isEnabled() { - return enabled; - } + public boolean isEnabled() { + return enabled; + } - public void setAlarmActions(List alarmActions) { - this.alarmActions = alarmActions; - } + public void setAlarmActions(List alarmActions) { + this.alarmActions = alarmActions; + } - public void setDescription(String description) { - this.description = description == null ? "" : description; - } + public void setDescription(String description) { + this.description = description == null ? "" : description; + } - public void setEnabled(boolean enabled) { - this.enabled = enabled; - } + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } - public void setExpression(String expression) { - this.expression = expression; - } + public void setExpression(String expression) { + this.expression = expression; + } - public void setId(String id) { - this.id = id; - } + @XmlElement(name = "id") + @ApiModelProperty(value = "Alarm ID") + public void setId(String id) { + this.id = id; + } - @Override - public void setLinks(List links) { - this.links = links; - } + @Override + public void setLinks(List links) { + this.links = links; + } - public void setName(String name) { - this.name = name; - } + public void setName(String name) { + this.name = name; + } - public void setOkActions(List okActions) { - this.okActions = okActions; - } + public void setOkActions(List okActions) { + this.okActions = okActions; + } - public void setState(AlarmState state) { - this.state = state; - } + public void setState(AlarmState state) { + this.state = state; + } - public void setUndeterminedActions(List undeterminedActions) { - this.undeterminedActions = undeterminedActions; - } + public void setUndeterminedActions(List undeterminedActions) { + this.undeterminedActions = undeterminedActions; + } - @Override - public String toString() { - return String.format("Alarm [name=%s]", name); - } + @Override + public String toString() { + return String.format("Alarm [name=%s]", name); + } } diff --git a/src/main/java/com/hpcloud/mon/resource/AlarmResource.java b/src/main/java/com/hpcloud/mon/resource/AlarmResource.java index 9d8fd5697..eefb909e9 100644 --- a/src/main/java/com/hpcloud/mon/resource/AlarmResource.java +++ b/src/main/java/com/hpcloud/mon/resource/AlarmResource.java @@ -20,6 +20,7 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; +import com.wordnik.swagger.annotations.*; import org.hibernate.validator.constraints.NotEmpty; import com.codahale.metrics.annotation.Timed; @@ -43,6 +44,8 @@ import com.hpcloud.mon.resource.annotation.PATCH; * @author Jonathan Halterman */ @Path("/v2.0/alarms") +@Api(value = "/v2.0/alarms", description = "Operations about alarms") +@Produces({"application/json"}) public class AlarmResource { private final AlarmService service; private final AlarmRepository repo; @@ -81,7 +84,12 @@ public class AlarmResource { @Timed @Path("{alarm_id}") @Produces(MediaType.APPLICATION_JSON) - public Alarm get(@Context UriInfo uriInfo, @HeaderParam("X-Tenant-Id") String tenantId, + @ApiOperation(value = "Find by alarm ID", notes = "More notes about this method", response = Alarm.class) + @ApiResponses(value = { + @ApiResponse(code = 400, message = "Invalid ID supplied"), + @ApiResponse(code = 404, message = "Alarm not found") + }) + public Alarm get(@ApiParam(value = "ID of alarm to fetch", required = true) @Context UriInfo uriInfo, @HeaderParam("X-Tenant-Id") String tenantId, @PathParam("alarm_id") String alarmId) { return Links.hydrate(repo.findById(tenantId, alarmId), uriInfo, "history"); }