Skip to content

Commit

Permalink
Merge branch 'release/2.3.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
seratch committed Jan 23, 2015
2 parents a3e1272 + 2e20ba5 commit ead7639
Show file tree
Hide file tree
Showing 10 changed files with 81 additions and 20 deletions.
9 changes: 8 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ jdk:
- oraclejdk8

scala:
- 2.11.4
- 2.11.5

addons:
postgresql: "9.3"
Expand All @@ -17,3 +17,10 @@ before_script:
script: "sbt clean coverage test"

after_success: "sbt coverageAggregate coveralls"

sudo: false

cache:
directories:
- $HOME/.sbt
- $HOME/.ivy2
8 changes: 3 additions & 5 deletions app/controllers/PartsController.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package controllers

import javax.ws.rs.QueryParam

import com.m3.octoparts.json.format.ConfigModel._
import com.m3.octoparts.json.format.ReqResp._
import com.m3.octoparts.aggregator.service.PartsService
Expand Down Expand Up @@ -67,11 +69,7 @@ class PartsController(
response = classOf[HttpPartConfig],
responseContainer = "List",
httpMethod = "GET")
@ApiParam(allowMultiple = true,
name = "partId",
value = "Optional filter for the partId"
)
def list(partIdParams: List[String] = Nil) = Action.async { implicit request =>
def list(@ApiParam(value = "Optional part ids to filter on. Note, this should be passed as multiple partIdParams=partId, e.g ?partIdParams=wut&partIdParams=wut3 ", allowMultiple = true)@QueryParam("partIdParams") partIdParams: List[String] = Nil) = Action.async { implicit request =>
debugRc
val fConfigs = partIdParams match {
case Nil => configsRepository.findAllConfigs()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.m3.octoparts.model.{ AggregateRequest, RequestMeta }
import com.ning.http.client.{ AsyncHttpClient, AsyncHttpClientConfig, ListenableFuture }
import org.slf4j.LoggerFactory

import scala.annotation.varargs
import scala.concurrent.duration._

private[client] object OctopartsApiBuilder {
Expand Down Expand Up @@ -110,9 +111,17 @@ class OctopartsApiBuilder(@Nonnull apiRootUrl: String, @Nullable serviceId: Stri
sendCachePost(uri)
}

@Nonnull def listEndpoints(): ListenableFuture[java.util.List[HttpPartConfig]] = {
/**
* @param partIds when specified, filters the endpoint list. Note: not specifying a filter will prevent Octoparts from using the part config cache.
*/
@varargs @Nonnull def listEndpoints(@Nonnull partIds: String*): ListenableFuture[java.util.List[HttpPartConfig]] = {
import scala.collection.convert.Wrappers._
val queryParams: java.util.Map[String, java.util.List[String]] = {
if (partIds.isEmpty) java.util.Collections.emptyMap() else MutableMapWrapper(scala.collection.mutable.Map("partIdParams" -> SeqWrapper(partIds)))
}
val request = asyncHttpClient.
prepareGet(s"$octopartsApiEndpointUrl/list").
setQueryParams(queryParams).
build
asyncHttpClient.executeRequest(request, EndpointListExtractor)
}
Expand Down
6 changes: 6 additions & 0 deletions java-client/src/test/java/com/m3/octoparts/Sample.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ public List<HttpPartConfig> listEndpoints() {
return FutureResponseHandler.awaitListEndpoints(apiBuilder.listEndpoints(), 10000L);
}

public HttpPartConfig showEndpoint(String partId) {
List<HttpPartConfig> results = FutureResponseHandler.awaitListEndpoints(apiBuilder.listEndpoints(partId), 10000L);
if (results.isEmpty()) return null;
else return results.get(0);
}

public Boolean invalidateCache(String cacheGroupName) {
return FutureResponseHandler.awaitCacheInvalidationResponse(apiBuilder.invalidateCacheGroup(cacheGroupName), 1000L);
}
Expand Down
35 changes: 35 additions & 0 deletions maintainers-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
## Octoparts Maintainers' Guide

### Versioning Policy

```
"{server-major}.{server-minor}.{client-minor}"
```

When the "{client-minor}" is zero, version should be "{server-major}.{server-minor}".

### Release

#### Required

- Sonatype release account
- $HOME/.sbt/0.13/sonatype.sbt

``` scala
credentials += Credentials("Sonatype Nexus Repository Manager", "oss.sonatype.org", "xxx", "yyy")
```

- $HOME/.sbt/0.13/plugins/gpg.sbt

```scala
// Use latest version
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0")
```

#### Operations

- Run `git flow release start/finish "{full-version}"`
- Run `./scripts/publish_libs.sh`
- Use `sbt sonatypeRelease` from `sbt-sonatype` plugin or access sonatype console (https://oss.sonatype.org/)
- Set version as "{next-version}-SNAPSHOT" on develop branch

2 changes: 1 addition & 1 deletion project/Version.scala
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

object Version {

val octopartsVersion = "2.3.1"
val octopartsVersion = "2.3.2"
val theScalaVersion = "2.11.5"

}
4 changes: 2 additions & 2 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.3.2")
addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "0.6.4")
// For publishing to Sonatype OSS
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0")

addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "0.2.1")
// For publishing coverage data to coveralls.io
addSbtPlugin("org.scoverage" %% "sbt-coveralls" % "1.0.0.BETA1")

addSbtPlugin("org.scoverage" %% "sbt-coveralls" % "1.0.0.BETA1")
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ trait OctoClientLike {
protected[ws] case object InvalidateCacheGroup extends PlaceHoldersUrl { val url = s"${cacheApiBaseUrl(baseUrl)}/invalidate/cache-group/%s" }
protected[ws] case object InvalidateCacheGroupFor extends PlaceHoldersUrl { val url = s"${cacheApiBaseUrl(baseUrl)}/invalidate/cache-group/%s/params/%s" }

private val partIdFilterName: String = "partIdParams"

/**
* Given an [[ApiUrl]] and path segments, returns the full URL for that operation, filling in
* path segments where appropriate
Expand Down Expand Up @@ -140,9 +142,13 @@ trait OctoClientLike {
/**
* Returns a Future Seq[[com.m3.octoparts.model.config.json.HttpPartConfig]], which
* describes all the endpoints registered to the Octoparts service.
*
* @param partIds a list of partIds in specific to retrieve endpoint info for.
*/
def listEndpoints()(implicit ec: ExecutionContext): Future[Seq[HttpPartConfig]] = {
wsHolderFor(urlFor(ListEndpoints), clientTimeout).get()
def listEndpoints(partIds: String*)(implicit ec: ExecutionContext): Future[Seq[HttpPartConfig]] = {
wsHolderFor(urlFor(ListEndpoints), clientTimeout)
.withQueryString(partIds.map(n => partIdFilterName -> n): _*)
.get()
.map(resp => resp.json.as[Seq[HttpPartConfig]])
.recover(rescuer(rescueHttpPartConfigs))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import org.mockito.Matchers._
import play.api.mvc.RequestHeader
import play.api.mvc.Results.EmptyContent
import play.api.test.FakeRequest
import scala.concurrent.duration._

import scala.language.postfixOps
import scala.concurrent.Future
Expand All @@ -43,6 +42,7 @@ class OctoClientSpec extends FunSpec with Matchers with ScalaFutures with Mockit

def mockWSHolder(fWSRespPost: Future[WSResponse], fWSRespGet: Future[WSResponse]): WSRequestHolder = {
val mockWS = mock[WSRequestHolder]
when(mockWS.withQueryString(anyVararg())).thenReturn(mockWS)
when(mockWS.get()).thenReturn(fWSRespGet)
when(mockWS.post(anyObject[JsValue])(anyObject(), anyObject())).thenReturn(fWSRespPost)
when(mockWS.post(anyObject[EmptyContent])(anyObject(), anyObject())).thenReturn(fWSRespPost)
Expand Down
14 changes: 7 additions & 7 deletions test/controllers/AdminControllerSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import com.m3.octoparts.support.mocks.ConfigDataMocks
import org.apache.http.entity.ContentType
import org.apache.http.entity.mime.MultipartEntityBuilder
import org.apache.http.entity.mime.content.FileBody
import org.mockito.ArgumentCaptor
import org.mockito.{ Mockito, ArgumentCaptor }
import org.mockito.Matchers._
import org.mockito.Mockito._
import org.scalatest._
Expand Down Expand Up @@ -189,9 +189,9 @@ class AdminControllerSpec extends FunSpec
def setupController: (AdminController, CacheOps, MutableConfigsRepository, HttpPartConfig) = {
val repository = mock[MutableConfigsRepository]
val cacheOps = mock[CacheOps]
when(cacheOps.increasePartVersion(anyString())).thenReturn(Future.successful(()))
val adminController = new AdminController(cacheOps = cacheOps, repository = repository)
val part2 = part.copy(hystrixConfig = Some(mockHystrixConfig))
doReturn(Future.successful(())).when(cacheOps).increasePartVersion(anyString())
doReturn(Future.successful(Some(part2))).when(repository).findConfigByPartId(part.partId)
doReturn(Future.successful(1)).when(repository).deleteConfigByPartId(part.partId)
doReturn(Future.successful(Seq.empty)).when(repository).findAllCacheGroupsByName(anyVararg[String]())
Expand All @@ -209,7 +209,7 @@ class AdminControllerSpec extends FunSpec
val result = controller.updatePart(part.partId).apply(FakeRequest().withFormUrlEncodedBody(validPartEditFormParams: _*))
status(result) should be(FOUND)
redirectLocation(result).get should include(routes.AdminController.showPart("aNewName").url)
verify(cacheOps).increasePartVersion(part.partId)
verify(cacheOps, Mockito.timeout(1000)).increasePartVersion(part.partId)
}
}

Expand Down Expand Up @@ -315,7 +315,7 @@ class AdminControllerSpec extends FunSpec

verify(repository).findConfigByPartId(part.partId)
verify(repository).deleteConfigByPartId(part.partId)
verify(cacheOps).increasePartVersion(part.partId)
verify(cacheOps, Mockito.timeout(1000)).increasePartVersion(part.partId)
}
}
}
Expand Down Expand Up @@ -441,7 +441,7 @@ class AdminControllerSpec extends FunSpec
val newCiCaptor = ArgumentCaptor.forClass(classOf[PartParam])
verify(repository).save(newCiCaptor.capture())(anyObject[ConfigMapper[PartParam]])
verify(repository).findAllCacheGroupsByName(Seq.empty: _*)
verify(cacheOps).increasePartVersion(part.partId)
verify(cacheOps, Mockito.timeout(1000)).increasePartVersion(part.partId)

newCiCaptor.getValue.outputName should be("someName")
newCiCaptor.getValue.paramType should be(ParamType.Cookie)
Expand Down Expand Up @@ -470,7 +470,7 @@ class AdminControllerSpec extends FunSpec
val newCiCaptor = ArgumentCaptor.forClass(classOf[PartParam])
verify(repository).save(newCiCaptor.capture())(anyObject[ConfigMapper[PartParam]])
verify(repository).findAllCacheGroupsByName(Seq.empty: _*)
verify(cacheOps).increasePartVersion(part.partId)
verify(cacheOps, Mockito.timeout(1000)).increasePartVersion(part.partId)

newCiCaptor.getValue.outputName should be("newName")
newCiCaptor.getValue.paramType should be(ParamType.Body)
Expand All @@ -494,7 +494,7 @@ class AdminControllerSpec extends FunSpec
verify(repository).findConfigByPartId(part.partId)
val newCiCaptor = ArgumentCaptor.forClass(classOf[Long])
verify(repository).deletePartParamById(newCiCaptor.capture())
verify(cacheOps).increasePartVersion(part.partId)
verify(cacheOps, Mockito.timeout(1000)).increasePartVersion(part.partId)
newCiCaptor.getValue should be(part.id.get)
}
}
Expand Down

0 comments on commit ead7639

Please sign in to comment.