You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by ra...@apache.org on 2017/08/12 14:38:57 UTC
[incubator-openwhisk] branch master updated: Port Controller from
Spray to Akka (#2218)
This is an automated email from the ASF dual-hosted git repository.
rabbah pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk.git
The following commit(s) were added to refs/heads/master by this push:
new d564ea9 Port Controller from Spray to Akka (#2218)
d564ea9 is described below
commit d564ea98743625d56df5d8c060574ba5b10d7f3b
Author: James Dubee <jw...@us.ibm.com>
AuthorDate: Sat Aug 12 10:38:55 2017 -0400
Port Controller from Spray to Akka (#2218)
* Port Controller from Spray to Akka
* Increase max-connections and Update JSON Unmarshaller
---
common/scala/build.gradle | 7 +-
common/scala/src/main/resources/application.conf | 2 +-
.../src/main/scala/whisk/common/HttpClient.scala | 43 ---
.../scala/whisk/core/entity/ActivationResult.scala | 4 +-
.../main/scala/whisk/http/BasicHttpService.scala | 140 +++++----
.../main/scala/whisk/http/BasicRasService.scala | 2 +-
.../src/main/scala/whisk/http/ErrorResponse.scala | 33 +--
.../controller/src/main/resources/application.conf | 77 +++--
.../main/scala/whisk/core/controller/Actions.scala | 47 +--
.../scala/whisk/core/controller/Activations.scala | 47 ++-
.../scala/whisk/core/controller/ApiUtils.scala | 22 +-
.../scala/whisk/core/controller/Authenticate.scala | 22 +-
.../whisk/core/controller/AuthenticatedRoute.scala | 29 +-
.../controller/AuthorizedRouteDispatcher.scala | 22 +-
.../scala/whisk/core/controller/Controller.scala | 81 ++---
.../scala/whisk/core/controller/Entities.scala | 36 ++-
.../scala/whisk/core/controller/Namespaces.scala | 14 +-
.../scala/whisk/core/controller/Packages.scala | 14 +-
.../scala/whisk/core/controller/RestAPIs.scala | 327 +++++++++++----------
.../main/scala/whisk/core/controller/Rules.scala | 15 +-
.../scala/whisk/core/controller/Triggers.scala | 74 ++---
.../scala/whisk/core/controller/WebActions.scala | 115 ++++----
.../controller/actions/PostActionActivation.scala | 4 +-
.../core/controller/actions/SequenceActions.scala | 1 +
.../whisk/core/entitlement/ActionCollection.scala | 3 +-
.../scala/whisk/core/entitlement/Collection.scala | 14 +-
.../scala/whisk/core/entitlement/Entitlement.scala | 11 +-
.../whisk/core/entitlement/LocalEntitlement.scala | 3 +-
.../whisk/core/entitlement/PackageCollection.scala | 5 +-
.../main/scala/whisk/core/invoker/Invoker.scala | 7 +-
.../scala/whisk/core/invoker/InvokerServer.scala | 15 +-
tests/build.gradle | 5 +-
tests/src/test/scala/services/HeadersTests.scala | 106 +++----
.../test/scala/system/basic/WskSequenceTests.scala | 5 +-
.../whisk/core/cli/test/WskWebActionsTests.scala | 2 +-
.../core/controller/test/ActionsApiTests.scala | 139 ++++-----
.../core/controller/test/ActivationsApiTests.scala | 58 ++--
.../core/controller/test/AuthenticateTests.scala | 62 +---
.../core/controller/test/AuthenticateV2Tests.scala | 5 +-
.../controller/test/ControllerTestCommon.scala | 9 +-
.../controller/test/EntitlementProviderTests.scala | 3 +-
.../core/controller/test/NamespacesApiTests.scala | 28 +-
.../controller/test/PackageActionsApiTests.scala | 92 +++---
.../core/controller/test/PackagesApiTests.scala | 106 +++----
.../controller/test/RespondWithHeadersTests.scala | 18 +-
.../whisk/core/controller/test/RulesApiTests.scala | 114 +++----
.../core/controller/test/SequenceApiTests.scala | 47 +--
.../core/controller/test/SwaggerRoutesTests.scala | 14 +-
.../core/controller/test/TriggersApiTests.scala | 64 ++--
.../core/controller/test/WebActionsApiTests.scala | 181 ++++++------
.../SequenceActionApiMigrationTests.scala | 20 +-
51 files changed, 1155 insertions(+), 1159 deletions(-)
diff --git a/common/scala/build.gradle b/common/scala/build.gradle
index fe17c58..e1d0535 100644
--- a/common/scala/build.gradle
+++ b/common/scala/build.gradle
@@ -13,15 +13,10 @@ dependencies {
compile 'io.spray:spray-caching_2.11:1.3.4'
compile 'io.spray:spray-json_2.11:1.3.3'
- compile 'io.spray:spray-can_2.11:1.3.4'
- compile 'io.spray:spray-client_2.11:1.3.4'
- compile 'io.spray:spray-httpx_2.11:1.3.4'
- compile 'io.spray:spray-io_2.11:1.3.4'
- compile 'io.spray:spray-routing_2.11:1.3.4'
compile 'com.typesafe.akka:akka-actor_2.11:2.4.16'
compile 'com.typesafe.akka:akka-slf4j_2.11:2.4.16'
- compile 'com.typesafe.akka:akka-http-core_2.11:10.0.2'
+ compile 'com.typesafe.akka:akka-http-core_2.11:10.0.9'
compile 'com.typesafe.akka:akka-http-spray-json_2.11:10.0.2'
compile 'log4j:log4j:1.2.16'
diff --git a/common/scala/src/main/resources/application.conf b/common/scala/src/main/resources/application.conf
index c3d8686..d704334 100644
--- a/common/scala/src/main/resources/application.conf
+++ b/common/scala/src/main/resources/application.conf
@@ -1,4 +1,4 @@
-# default application configuration file for spray/akka
+# default application configuration file for akka
include "logging"
akka.http {
diff --git a/common/scala/src/main/scala/whisk/common/HttpClient.scala b/common/scala/src/main/scala/whisk/common/HttpClient.scala
deleted file mode 100644
index f7cd2a9..0000000
--- a/common/scala/src/main/scala/whisk/common/HttpClient.scala
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package whisk.common
-
-import scala.concurrent.ExecutionContext
-import scala.concurrent.Future
-
-import akka.actor.ActorSystem
-import akka.io.IO
-import akka.pattern.ask
-import akka.util.Timeout
-import spray.can.Http
-import spray.client.pipelining.SendReceive
-import spray.client.pipelining.sendReceive
-
-/**
- * Trait which implements a method to make an HTTP Request.
- */
-trait HttpClient {
- /** Creates HTTP request client. */
- protected def httpRequest(host: String, port: Int, timeout: Timeout)(
- implicit as: ActorSystem, ec: ExecutionContext): Future[SendReceive] = {
- implicit val duration = timeout
- for (
- Http.HostConnectorInfo(connector, _) <- IO(Http) ? Http.HostConnectorSetup(host, port)
- ) yield sendReceive(connector)
- }
-}
diff --git a/common/scala/src/main/scala/whisk/core/entity/ActivationResult.scala b/common/scala/src/main/scala/whisk/core/entity/ActivationResult.scala
index aef644e..705e722 100644
--- a/common/scala/src/main/scala/whisk/core/entity/ActivationResult.scala
+++ b/common/scala/src/main/scala/whisk/core/entity/ActivationResult.scala
@@ -19,9 +19,11 @@ package whisk.core.entity
import scala.util.Try
-import spray.http.StatusCodes.OK
+import akka.http.scaladsl.model.StatusCodes.OK
+
import spray.json._
import spray.json.DefaultJsonProtocol
+
import whisk.common.Logging
import whisk.http.Messages._
diff --git a/common/scala/src/main/scala/whisk/http/BasicHttpService.scala b/common/scala/src/main/scala/whisk/http/BasicHttpService.scala
index 7b1ee7d..6ca0fe5 100644
--- a/common/scala/src/main/scala/whisk/http/BasicHttpService.scala
+++ b/common/scala/src/main/scala/whisk/http/BasicHttpService.scala
@@ -19,56 +19,56 @@ package whisk.http
import scala.concurrent.duration.DurationInt
import scala.language.postfixOps
+import scala.collection.immutable.Seq
+import scala.concurrent.Future
import akka.actor.Actor
-import akka.actor.ActorContext
import akka.actor.ActorSystem
import akka.actor.Props
import akka.event.Logging
-import akka.io.IO
import akka.japi.Creator
-import akka.pattern.ask
import akka.util.Timeout
-import spray.can.Http
-import spray.http.ContentType
-import spray.http.HttpEntity
-import spray.http.HttpRequest
-import spray.http.HttpResponse
-import spray.http.MediaTypes.`text/plain`
-import spray.httpx.SprayJsonSupport.sprayJsonMarshaller
-import spray.httpx.marshalling
-import spray.httpx.marshalling.ToResponseMarshallable.isMarshallable
-import spray.routing.AuthenticationFailedRejection
-import spray.routing.Directive.pimpApply
-import spray.routing.Directives
-import spray.routing.HttpService
-import spray.routing.RejectionHandler
-import spray.routing.Route
-import spray.routing.directives.DebuggingDirectives
-import spray.routing.directives.LogEntry
-import spray.routing.directives.LoggingMagnet.forMessageFromFullShow
+import akka.http.scaladsl.server.Directives
+import akka.http.scaladsl.server.directives.DebuggingDirectives
+import akka.http.scaladsl.server.directives.LogEntry
+import akka.http.scaladsl.server.Route
+import akka.http.scaladsl.model.HttpRequest
+import akka.http.scaladsl.model._
+import akka.http.scaladsl.server.RejectionHandler
+import akka.http.scaladsl.server.UnacceptedResponseContentTypeRejection
+import akka.http.scaladsl.server.RouteResult.Rejected
+import akka.http.scaladsl.Http
+
+import spray.json._
+
import whisk.common.LogMarker
import whisk.common.LogMarkerToken
import whisk.common.Logging
import whisk.common.LoggingMarkers
import whisk.common.TransactionCounter
import whisk.common.TransactionId
+import akka.stream.ActorMaterializer
/**
- * This trait extends the spray HttpService trait with logging and transaction counting
+ * This trait extends the Akka Directives and Actor with logging and transaction counting
* facilities common to all OpenWhisk REST services.
*/
-trait BasicHttpService extends HttpService with TransactionCounter {
-
- /**
- * Gets the actor context.
- */
- implicit def actorRefFactory: ActorContext
-
- /**
- * Gets the logging
- */
+trait BasicHttpService extends Directives with Actor with TransactionCounter {
implicit def logging: Logging
+ implicit val materializer = ActorMaterializer()
+ implicit val actorSystem = context.system
+ implicit val executionContext = actorSystem.dispatcher
+
+ val port: Int
+
+ /** Rejection handler to terminate connection on a bad request. Delegates to Akka handler. */
+ implicit def customRejectionHandler(implicit transid: TransactionId) =
+ RejectionHandler.default.mapRejectionResponse {
+ case res @ HttpResponse(_, _, ent: HttpEntity.Strict, _) =>
+ val error = ErrorResponse(ent.data.utf8String, transid).toJson
+ res.copy(entity = HttpEntity(ContentTypes.`application/json`, error.compactPrint))
+ case x => x
+ }
/**
* Gets the routes implemented by the HTTP service.
@@ -86,39 +86,47 @@ trait BasicHttpService extends HttpService with TransactionCounter {
*/
def loglevelForRoute(route: String): Logging.LogLevel = Logging.InfoLevel
+ /** Rejection handler to terminate connection on a bad request. Delegates to Akka handler. */
+ val prioritizeRejections = recoverRejections { rejections =>
+ val priorityRejection = rejections.find {
+ case rejection: UnacceptedResponseContentTypeRejection => true
+ case _ => false
+ }
+
+ priorityRejection.map(rejection => Rejected(Seq(rejection))).getOrElse(Rejected(rejections))
+ }
+
/**
* Receives a message and runs the router.
*/
- def receive = runRoute(
+ def route: Route = {
assignId { implicit transid =>
- DebuggingDirectives.logRequest(logRequestInfo _) {
- DebuggingDirectives.logRequestResponse(logResponseInfo _) {
- routes
+ handleRejections(customRejectionHandler) {
+ prioritizeRejections {
+ DebuggingDirectives.logRequest(logRequestInfo _) {
+ DebuggingDirectives.logRequestResult(logResponseInfo _) {
+ toStrictEntity(1.second) {
+ routes
+ }
+ }
+ }
}
}
- })
+ }
+ }
+
+ def receive = {
+ case _ =>
+ }
/** Assigns transaction id to every request. */
protected val assignId = extract(_ => transid())
- /** Rejection handler to terminate connection on a bad request. Delegates to Spray handler. */
-
- protected def customRejectionHandler(implicit transid: TransactionId) = RejectionHandler {
- case rejections => {
- logging.info(this, s"[REJECT] $rejections")
- rejections match {
- case AuthenticationFailedRejection(cause, challengeHeaders) :: _ =>
- BasicHttpService.customRejectionHandler.apply(rejections.takeRight(1))
- case _ => BasicHttpService.customRejectionHandler.apply(rejections)
- }
- }
- }
-
/** Generates log entry for every request. */
protected def logRequestInfo(req: HttpRequest)(implicit tid: TransactionId): LogEntry = {
- val m = req.method.toString
+ val m = req.method.name.toString
val p = req.uri.path.toString
- val q = req.uri.query.toString
+ val q = req.uri.query().toString
val l = loglevelForRoute(p)
LogEntry(s"[$tid] $m $p $q", l)
}
@@ -137,29 +145,19 @@ trait BasicHttpService extends HttpService with TransactionCounter {
Some(LogEntry(s"[$tid] [$name] $marker", l))
case _ => None // other kind of responses
}
+
+ val bindingFuture = {
+ Http().bindAndHandle(route, "0.0.0.0", port)
+ }
+
+ def shutdown(): Future[Unit] = {
+ bindingFuture.flatMap(_.unbind()).map(_ => ())
+ }
}
object BasicHttpService extends Directives {
- def startService[T <: Actor](system: ActorSystem, name: String, interface: String, port: Integer, service: Creator[T]) = {
+ def startService[T <: Actor](system: ActorSystem, name: String, interface: String, service: Creator[T]) = {
val actor = system.actorOf(Props.create(service), s"$name-service")
-
implicit val timeout = Timeout(5 seconds)
- IO(Http)(system) ? Http.Bind(actor, interface, port)
- }
-
- /** Rejection handler to terminate connection on a bad request. Delegates to Spray handler. */
- def customRejectionHandler(implicit transid: TransactionId) = RejectionHandler {
- // get default rejection message, package it as an ErrorResponse instance
- // which gets serialized into a Json object
- case r if RejectionHandler.Default.isDefinedAt(r) => {
- ctx =>
- RejectionHandler.Default(r) {
- ctx.withHttpResponseMapped {
- case resp @ HttpResponse(_, HttpEntity.NonEmpty(ContentType(`text/plain`, _), msg), _, _) =>
- resp.withEntity(marshalling.marshalUnsafe(ErrorResponse(msg.asString, transid)))
- }
- }
- }
- case CustomRejection(status, cause) :: _ => complete(status, ErrorResponse(cause, transid))
}
}
diff --git a/common/scala/src/main/scala/whisk/http/BasicRasService.scala b/common/scala/src/main/scala/whisk/http/BasicRasService.scala
index f7d0034..4c773d0 100644
--- a/common/scala/src/main/scala/whisk/http/BasicRasService.scala
+++ b/common/scala/src/main/scala/whisk/http/BasicRasService.scala
@@ -18,7 +18,7 @@
package whisk.http
import akka.event.Logging
-import spray.httpx.SprayJsonSupport._
+
import whisk.common.Logging
import whisk.common.TransactionId
diff --git a/common/scala/src/main/scala/whisk/http/ErrorResponse.scala b/common/scala/src/main/scala/whisk/http/ErrorResponse.scala
index 525fdeb..1687630 100644
--- a/common/scala/src/main/scala/whisk/http/ErrorResponse.scala
+++ b/common/scala/src/main/scala/whisk/http/ErrorResponse.scala
@@ -21,17 +21,16 @@ import scala.concurrent.duration.Duration
import scala.concurrent.duration.FiniteDuration
import scala.util.Try
-import spray.http.MediaType
-import spray.http.StatusCode
-import spray.http.StatusCodes.Forbidden
-import spray.http.StatusCodes.NotFound
-import spray.httpx.SprayJsonSupport.sprayJsonMarshaller
-import spray.httpx.marshalling.ToResponseMarshallable.isMarshallable
+import akka.http.scaladsl.model.StatusCode
+import akka.http.scaladsl.model.StatusCodes.Forbidden
+import akka.http.scaladsl.model.StatusCodes.NotFound
+import akka.http.scaladsl.model.MediaType
+import akka.http.scaladsl.server.Directives
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport.sprayJsonMarshaller
+import akka.http.scaladsl.server.StandardRoute
+
import spray.json._
-import spray.json.DefaultJsonProtocol._
-import spray.routing.Directives
-import spray.routing.Rejection
-import spray.routing.StandardRoute
+
import whisk.common.TransactionId
import whisk.core.entity.SizeError
import whisk.core.entity.ByteSize
@@ -107,6 +106,9 @@ object Messages {
/** Error messages for activations. */
val abnormalInitialization = "The action did not initialize and exited unexpectedly."
val abnormalRun = "The action did not produce a valid response and exited unexpectedly."
+ def badEntityName(value: String) = s"Parameter is not a valid value for a entity name: $value"
+ def badNamespace(value: String) = s"Parameter is not a valid value for a namespace: $value"
+ def badEpoch(value: String) = s"Parameter is not a valid value for epoch seconds: $value"
/** Error message for size conformance. */
def entityTooBig(error: SizeError) = {
@@ -165,10 +167,7 @@ object Messages {
/** Replaces rejections with Json object containing cause and transaction id. */
case class ErrorResponse(error: String, code: TransactionId)
-/** Custom rejection, wraps status code for response and a cause. */
-case class CustomRejection private (status: StatusCode, cause: String) extends Rejection
-
-object ErrorResponse extends Directives {
+object ErrorResponse extends Directives with DefaultJsonProtocol {
def terminate(status: StatusCode, error: String)(implicit transid: TransactionId): StandardRoute = {
terminate(status, Option(error) filter { _.trim.nonEmpty } map {
@@ -207,9 +206,3 @@ object ErrorResponse extends Directives {
}
}
-
-object CustomRejection {
- def apply(status: StatusCode): CustomRejection = {
- CustomRejection(status, status.defaultMessage)
- }
-}
diff --git a/core/controller/src/main/resources/application.conf b/core/controller/src/main/resources/application.conf
index 74afb48..d783df4 100644
--- a/core/controller/src/main/resources/application.conf
+++ b/core/controller/src/main/resources/application.conf
@@ -1,40 +1,57 @@
# common logging configuration see common scala
include "logging"
+include "akka-http-version"
-# see http://spray.io/documentation/spray-can/configuration/
+# http://doc.akka.io/docs/akka-http/current/scala/http/configuration.html
# descriptions inlined below for convenience
-spray.can.server {
- # Description:
- # If a request hasn't been responded to after the time period set here
- # a `spray.http.Timedout` message will be sent to the timeout handler.
- # Set to `infinite` to completely disable request timeouts.
- #
- # Explaining the set value:
- # The controller holds connections up to 60s for blocking invokes, and
- # all other operations are expected to complete quickly. We allow a grace
- # period in addition to the blocking invoke timeout.
- request-timeout = 90s
+akka.http {
+ server {
+ # Description:
+ # If a request hasn't been responded to after the time period set here
+ # a `akka.http.Timedout` message will be sent to the timeout handler.
+ # Set to `infinite` to completely disable request timeouts.
+ #
+ # Explaining the set value:
+ # The controller holds connections up to 60s for blocking invokes, and
+ # all other operations are expected to complete quickly. We allow a grace
+ # period in addition to the blocking invoke timeout.
+ request-timeout = 90s
- # Description:
- # Enables/disables support for statistics collection and querying.
- # Even though stats keeping overhead is small,
- # for maximum performance switch off when not needed.
- stats-support = off
+ # The maximum number of concurrently accepted connections when using the
+ # `Http().bindAndHandle` methods.
+ #
+ # This setting doesn't apply to the `Http().bind` method which will still
+ # deliver an unlimited backpressured stream of incoming connections.
+ #
+ # Note, that this setting limits the number of the connections on a best-effort basis.
+ # It does *not* strictly guarantee that the number of established TCP connections will never
+ # exceed the limit (but it will be approximately correct) because connection termination happens
+ # asynchronously. It also does *not* guarantee that the number of concurrently active handler
+ # flow materializations will never exceed the limit for the reason that it is impossible to reliably
+ # detect when a materialization has ended.
+ max-connections = 8192
- # Description:
- # The time after which an idle connection will be automatically closed.
- # Set to `infinite` to completely disable idle connection timeouts.
- #
- # Explaining the set value:
- # This must be greater than the request timeout.
- idle-timeout = 120s
+ # Description:
+ # Enables/disables support for statistics collection and querying.
+ # Even though stats keeping overhead is small,
+ # for maximum performance switch off when not needed.
+ stats-support = off
- parsing {
- # This indirectly puts a bound on the name of entities
- # 8k matches nginx default
- max-uri-length = 8k
+ # Description:
+ # The time after which an idle connection will be automatically closed.
+ # Set to `infinite` to completely disable idle connection timeouts.
+ #
+ # Explaining the set value:
+ # This must be greater than the request timeout.
+ idle-timeout = 120s
- # This is 50MB to allow action attachments
- max-content-length = 50m
+ parsing {
+ # This indirectly puts a bound on the name of entities
+ # 8k matches nginx default
+ max-uri-length = 8k
+
+ # This is 50MB to allow action attachments
+ max-content-length = 50m
+ }
}
}
diff --git a/core/controller/src/main/scala/whisk/core/controller/Actions.scala b/core/controller/src/main/scala/whisk/core/controller/Actions.scala
index eeb0b6a..e7d812c 100644
--- a/core/controller/src/main/scala/whisk/core/controller/Actions.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/Actions.scala
@@ -20,32 +20,37 @@ package whisk.core.controller
import scala.concurrent.Future
import scala.concurrent.duration._
import scala.language.postfixOps
-import scala.util.Failure
-import scala.util.Success
-import scala.util.Try
+import scala.util.{ Failure, Success, Try }
import org.apache.kafka.common.errors.RecordTooLargeException
import akka.actor.ActorSystem
-import spray.http.HttpMethod
-import spray.http.StatusCodes._
-import spray.httpx.SprayJsonSupport._
-import spray.httpx.unmarshalling._
+import akka.http.scaladsl.model.HttpMethod
+import akka.http.scaladsl.model.StatusCodes._
+import akka.http.scaladsl.server.RequestContext
+import akka.http.scaladsl.server.RouteResult
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport.sprayJsonMarshaller
+import akka.http.scaladsl.unmarshalling._
+
import spray.json._
import spray.json.DefaultJsonProtocol._
-import spray.routing.RequestContext
+
import whisk.common.TransactionId
import whisk.core.WhiskConfig
import whisk.core.controller.actions.PostActionActivation
import whisk.core.database.NoDocumentException
import whisk.core.entitlement._
-import whisk.core.entitlement.Privilege._
import whisk.core.entity._
import whisk.core.entity.types.ActivationStore
import whisk.core.entity.types.EntityStore
import whisk.http.ErrorResponse.terminate
import whisk.http.Messages
import whisk.http.Messages._
+import whisk.core.entitlement.Resource
+import whisk.core.entitlement.Collection
+import whisk.core.entitlement.Privilege.Privilege
+import whisk.core.entitlement.Privilege._
/**
* A singleton object which defines the properties that must be present in a configuration
@@ -82,6 +87,8 @@ trait WhiskActionsApi
/** Database service to get activations. */
protected val activationStore: ActivationStore
+ import RestApiCommons.emptyEntityToJsObject
+
/**
* Handles operations on action resources, which encompass these cases:
*
@@ -208,7 +215,7 @@ trait WhiskActionsApi
* - 500 Internal Server Error
*/
override def activate(user: Identity, entityName: FullyQualifiedEntityName, env: Option[Parameters])(implicit transid: TransactionId) = {
- parameter('blocking ? false, 'result ? false, 'timeout ? WhiskActionsApi.maxWaitForBlockingActivation) { (blocking, result, waitOverride) =>
+ parameter('blocking ? false, 'result ? false, 'timeout.as[FiniteDuration] ? WhiskActionsApi.maxWaitForBlockingActivation) { (blocking, result, waitOverride) =>
entity(as[Option[JsObject]]) { payload =>
getEntity(WhiskAction, entityStore, entityName.toDocId, Some {
act: WhiskAction =>
@@ -499,7 +506,7 @@ trait WhiskActionsApi
* namespace.
*/
private def mergeActionWithPackageAndDispatch(method: HttpMethod, user: Identity, action: EntityName, ref: Option[WhiskPackage] = None)(wp: WhiskPackage)(
- implicit transid: TransactionId): RequestContext => Unit = {
+ implicit transid: TransactionId): RequestContext => Future[RouteResult] = {
wp.binding map {
case b: Binding =>
val docid = b.fullyQualifiedName.toDocId
@@ -616,18 +623,16 @@ trait WhiskActionsApi
Parameters(WhiskAction.execFieldName, exec.kind)
}
- /** Max atomic action count allowed for sequences */
+ /** Max atomic action count allowed for sequences. */
private lazy val actionSequenceLimit = whiskConfig.actionSequenceLimit.toInt
- /** Custom deserializer for timeout query parameter. */
- private implicit val stringToTimeoutDeserializer = new FromStringDeserializer[FiniteDuration] {
- val max = WhiskActionsApi.maxWaitForBlockingActivation.toMillis
- def apply(msecs: String): Either[DeserializationError, FiniteDuration] = {
- Try { msecs.toInt } match {
- case Success(i) if i > 0 && i <= max => Right(i.milliseconds)
- case _ => Left {
- MalformedContent(Messages.invalidTimeout(WhiskActionsApi.maxWaitForBlockingActivation))
- }
+ implicit val stringToFiniteDuration: Unmarshaller[String, FiniteDuration] = {
+ Unmarshaller.strict[String, FiniteDuration] { value =>
+ val max = WhiskActionsApi.maxWaitForBlockingActivation.toMillis
+
+ Try { value.toInt } match {
+ case Success(i) if i > 0 && i <= max => i.milliseconds
+ case _ => throw new IllegalArgumentException(Messages.invalidTimeout(WhiskActionsApi.maxWaitForBlockingActivation))
}
}
}
diff --git a/core/controller/src/main/scala/whisk/core/controller/Activations.scala b/core/controller/src/main/scala/whisk/core/controller/Activations.scala
index 9c46853..e643b13 100644
--- a/core/controller/src/main/scala/whisk/core/controller/Activations.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/Activations.scala
@@ -24,14 +24,14 @@ import scala.util.Failure
import scala.util.Success
import scala.util.Try
-import spray.httpx.SprayJsonSupport.sprayJsonMarshaller
-import spray.httpx.unmarshalling.DeserializationError
-import spray.httpx.unmarshalling.FromStringDeserializer
-import spray.httpx.unmarshalling.MalformedContent
-import spray.routing.Directives
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport.sprayJsonMarshaller
+import akka.http.scaladsl.server.Directives
+import akka.http.scaladsl.unmarshalling._
+import akka.http.scaladsl.model.StatusCodes.BadRequest
+
+import spray.json.DeserializationException
import spray.json.DefaultJsonProtocol.RootJsObjectFormat
import spray.json._
-import spray.http.StatusCodes.BadRequest
import whisk.common.TransactionId
import whisk.core.entitlement.Collection
@@ -184,33 +184,30 @@ trait WhiskActivationsApi
(activation: WhiskActivation) => activation.logs.toJsonObject)
}
- /** Custom deserializer for query parameters "name" into valid entity name. */
- private implicit val stringToEntityName = new FromStringDeserializer[EntityName] {
- def apply(value: String): Either[DeserializationError, EntityName] = {
+ /** Custom unmarshaller for query parameters "name" into valid entity name. */
+ private implicit val stringToEntityName: Unmarshaller[String, EntityName] =
+ Unmarshaller.strict[String, EntityName] { value =>
Try { EntityName(value) } match {
- case Success(e) => Right(e)
- case Failure(t) => Left(MalformedContent(t.getMessage))
+ case Success(e) => e
+ case Failure(t) => throw new IllegalArgumentException(Messages.badEntityName(value))
}
}
- }
- /** Custom deserializer for query parameters "name" into valid namespace. */
- private implicit val stringToNamespace = new FromStringDeserializer[EntityPath] {
- def apply(value: String): Either[DeserializationError, EntityPath] = {
+ /** Custom unmarshaller for query parameters "name" into valid namespace. */
+ private implicit val stringToNamespace: Unmarshaller[String, EntityPath] =
+ Unmarshaller.strict[String, EntityPath] { value =>
Try { EntityPath(value) } match {
- case Success(e) => Right(e)
- case Failure(t) => Left(MalformedContent(t.getMessage))
+ case Success(e) => e
+ case Failure(t) => throw new IllegalArgumentException(Messages.badNamespace(value))
}
}
- }
- /** Custom deserializer for query parameters "since" and "upto" into a valid Instant. */
- private implicit val stringToInstantDeserializer = new FromStringDeserializer[Instant] {
- def apply(secs: String): Either[DeserializationError, Instant] = {
- Try { Instant.ofEpochMilli(secs.toLong) } match {
- case Success(i) => Right(i)
- case Failure(t) => Left(MalformedContent(s"Parameter is not a valid value for epoch seconds: $secs", Some(t)))
+ /** Custom unmarshaller for query parameters "since" and "upto" into a valid Instant. */
+ private implicit val stringToInstantDeserializer: Unmarshaller[String, Instant] =
+ Unmarshaller.strict[String, Instant] { value =>
+ Try { Instant.ofEpochMilli(value.toLong) } match {
+ case Success(e) => e
+ case Failure(t) => throw new IllegalArgumentException(Messages.badEpoch(value))
}
}
- }
}
diff --git a/core/controller/src/main/scala/whisk/core/controller/ApiUtils.scala b/core/controller/src/main/scala/whisk/core/controller/ApiUtils.scala
index ba692b6..54f424c 100644
--- a/core/controller/src/main/scala/whisk/core/controller/ApiUtils.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/ApiUtils.scala
@@ -22,20 +22,22 @@ import scala.concurrent.Future
import scala.util.Failure
import scala.util.Success
-import spray.http.StatusCode
-import spray.http.StatusCodes.Conflict
-import spray.http.StatusCodes.InternalServerError
-import spray.http.StatusCodes.NotFound
-import spray.http.StatusCodes.OK
-import spray.httpx.SprayJsonSupport._
-import spray.httpx.marshalling.ToResponseMarshallable.isMarshallable
+import akka.http.scaladsl.model.StatusCode
+import akka.http.scaladsl.model.StatusCodes.Conflict
+import akka.http.scaladsl.model.StatusCodes.InternalServerError
+import akka.http.scaladsl.model.StatusCodes.NotFound
+import akka.http.scaladsl.model.StatusCodes.OK
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
+import akka.http.scaladsl.server.Directives
+import akka.http.scaladsl.server.RequestContext
+import akka.http.scaladsl.server.RouteResult
+
import spray.json.DefaultJsonProtocol._
import spray.json.JsBoolean
import spray.json.JsObject
import spray.json.JsValue
import spray.json.RootJsonFormat
-import spray.routing.Directives
-import spray.routing.RequestContext
+
import whisk.common.Logging
import whisk.common.TransactionId
import whisk.core.controller.PostProcess.PostProcessEntity
@@ -105,7 +107,7 @@ protected[controller] object FilterEntityList {
* on an operation and terminate the HTTP request.
*/
package object PostProcess {
- type PostProcessEntity[A] = A => RequestContext => Unit
+ type PostProcessEntity[A] = A => RequestContext => Future[RouteResult]
}
/** A trait for REST APIs that read entities from a datastore */
diff --git a/core/controller/src/main/scala/whisk/core/controller/Authenticate.scala b/core/controller/src/main/scala/whisk/core/controller/Authenticate.scala
index 34d7161..ea3db36 100644
--- a/core/controller/src/main/scala/whisk/core/controller/Authenticate.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/Authenticate.scala
@@ -17,20 +17,23 @@
package whisk.core.controller
+import akka.http.scaladsl.model.headers.BasicHttpCredentials
+import akka.http.scaladsl.model.headers._
+
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import scala.util.Try
-import spray.routing.authentication.UserPass
import whisk.common.Logging
import whisk.common.TransactionId
import whisk.core.database.NoDocumentException
+import whisk.core.entity.UUID
+import whisk.core.entity.types.AuthStore
+import whisk.core.entity.WhiskAuthStore
import whisk.core.entity.AuthKey
import whisk.core.entity.Identity
import whisk.core.entity.Secret
import whisk.core.entity.UUID
-import whisk.core.entity.WhiskAuthStore
-import whisk.core.entity.types.AuthStore
object Authenticate {
/** Required properties for this component */
@@ -39,24 +42,21 @@ object Authenticate {
/** A trait to validate basic auth credentials */
trait Authenticate {
-
- /** An execution context for futures */
protected implicit val executionContext: ExecutionContext
+ protected implicit val logging: Logging
/** Database service to lookup credentials */
protected val authStore: AuthStore
- protected implicit val logging: Logging
-
/**
* Validates credentials against the authentication database; may be used in
* authentication directive.
*/
- def validateCredentials(userpass: Option[UserPass])(implicit transid: TransactionId): Future[Option[Identity]] = {
- userpass flatMap { pw =>
+ def validateCredentials(credentials: Option[BasicHttpCredentials])(implicit transid: TransactionId): Future[Option[Identity]] = {
+ credentials flatMap { pw =>
Try {
// authkey deserialization is wrapped in a try to guard against malformed values
- val authkey = AuthKey(UUID(pw.user), Secret(pw.pass))
+ val authkey = AuthKey(UUID(pw.username), Secret(pw.password))
logging.info(this, s"authenticate: ${authkey.uuid}")
val future = Identity.get(authStore, authkey) map { result =>
if (authkey == result.authkey) {
@@ -75,7 +75,7 @@ trait Authenticate {
future
}.toOption
} getOrElse {
- userpass.foreach(_ => logging.info(this, s"credentials are malformed"))
+ credentials.foreach(_ => logging.info(this, s"credentials are malformed"))
Future.successful(None)
}
}
diff --git a/core/controller/src/main/scala/whisk/core/controller/AuthenticatedRoute.scala b/core/controller/src/main/scala/whisk/core/controller/AuthenticatedRoute.scala
index fad7060..e9b481f 100644
--- a/core/controller/src/main/scala/whisk/core/controller/AuthenticatedRoute.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/AuthenticatedRoute.scala
@@ -17,19 +17,18 @@
package whisk.core.controller
-import scala.Left
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
-import spray.http.StatusCodes.InternalServerError
-import spray.http.StatusCodes.ServiceUnavailable
-import spray.routing.RequestContext
-import spray.routing.Route
-import spray.routing.authentication.BasicHttpAuthenticator
-import spray.routing.authentication.UserPass
+import akka.http.scaladsl.server.Route
+import akka.http.scaladsl.server.Directives._
+import akka.http.scaladsl.model.headers.BasicHttpCredentials
+import akka.http.scaladsl.server.directives._
+import akka.http.scaladsl.server.directives.AuthenticationResult
+import akka.http.scaladsl.model.headers._
+
import whisk.common.TransactionId
import whisk.core.entity.Identity
-import whisk.http.CustomRejection
/** A common trait for secured routes */
trait AuthenticatedRoute {
@@ -38,19 +37,17 @@ trait AuthenticatedRoute {
protected implicit val executionContext: ExecutionContext
/** Creates HTTP BasicAuth handler */
- protected def basicauth(implicit transid: TransactionId) = {
- new BasicHttpAuthenticator[Identity](realm = "whisk rest service", validateCredentials _) {
- override def apply(ctx: RequestContext) = {
- super.apply(ctx) recover {
- case t: IllegalStateException => Left(CustomRejection(InternalServerError))
- case t => Left(CustomRejection(ServiceUnavailable))
- }
+ def basicAuth[A](verify: Option[BasicHttpCredentials] => Future[Option[A]]) = {
+ authenticateOrRejectWithChallenge[BasicHttpCredentials, A] { creds =>
+ verify(creds).map {
+ case Some(t) => AuthenticationResult.success(t)
+ case None => AuthenticationResult.failWithChallenge(HttpChallenges.basic("OpenWhisk secure realm"))
}
}
}
/** Validates credentials against database of subjects */
- protected def validateCredentials(userpass: Option[UserPass])(implicit transid: TransactionId): Future[Option[Identity]]
+ protected def validateCredentials(credentials: Option[BasicHttpCredentials])(implicit transid: TransactionId): Future[Option[Identity]]
}
/** A trait for authenticated routes. */
diff --git a/core/controller/src/main/scala/whisk/core/controller/AuthorizedRouteDispatcher.scala b/core/controller/src/main/scala/whisk/core/controller/AuthorizedRouteDispatcher.scala
index 33a49fa..d82f9e3 100644
--- a/core/controller/src/main/scala/whisk/core/controller/AuthorizedRouteDispatcher.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/AuthorizedRouteDispatcher.scala
@@ -22,15 +22,19 @@ import scala.language.postfixOps
import scala.util.Failure
import scala.util.Success
import scala.util.Try
+import scala.concurrent.Future
-import spray.http.HttpMethod
-import spray.http.StatusCodes.InternalServerError
-import spray.routing.Directive1
-import spray.routing.Directives
-import spray.routing.RequestContext
+import akka.http.scaladsl.server.Directives
+import akka.http.scaladsl.model.HttpMethod
+import akka.http.scaladsl.server.RequestContext
+import akka.http.scaladsl.server.RouteResult
+import akka.http.scaladsl.model.StatusCodes.InternalServerError
+import akka.http.scaladsl.server.Directive1
+
+import whisk.core.entitlement.Privilege.Privilege
+import whisk.core.entitlement.Collection
import whisk.common.TransactionId
import whisk.core.entitlement._
-import whisk.core.entitlement.Privilege.Privilege
import whisk.core.entitlement.Resource
import whisk.core.entity._
import whisk.core.entity.size._
@@ -62,7 +66,7 @@ trait BasicAuthorizedRouteProvider extends Directives {
method: HttpMethod,
user: Identity,
resource: Resource)(
- implicit transid: TransactionId): RequestContext => Unit = {
+ implicit transid: TransactionId): RequestContext => Future[RouteResult] = {
val right = collection.determineRight(method, resource.entity)
onComplete(entitlementProvider.check(user, right, resource)) {
@@ -72,7 +76,7 @@ trait BasicAuthorizedRouteProvider extends Directives {
}
protected def handleEntitlementFailure(failure: Throwable)(
- implicit transid: TransactionId): RequestContext => Unit = {
+ implicit transid: TransactionId): RequestContext => Future[RouteResult] = {
failure match {
case (r: RejectRequest) => terminate(r.code, r.message)
case t => terminate(InternalServerError)
@@ -84,7 +88,7 @@ trait BasicAuthorizedRouteProvider extends Directives {
user: Identity,
op: Privilege,
resource: Resource)(
- implicit transid: TransactionId): RequestContext => Unit
+ implicit transid: TransactionId): RequestContext => Future[RouteResult]
/** Extracts namespace for user from the matched path segment. */
protected def namespace(user: Identity, ns: String) = {
diff --git a/core/controller/src/main/scala/whisk/core/controller/Controller.scala b/core/controller/src/main/scala/whisk/core/controller/Controller.scala
index 12a1086..27a63bf 100644
--- a/core/controller/src/main/scala/whisk/core/controller/Controller.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/Controller.scala
@@ -19,39 +19,37 @@ package whisk.core.controller
import scala.concurrent.Await
import scala.concurrent.duration.DurationInt
-import akka.actor.Actor
-import akka.actor.ActorContext
+import scala.util.{Failure, Success}
+
+import akka.actor._
import akka.actor.ActorSystem
import akka.japi.Creator
-import spray.http.StatusCodes._
-import spray.http.Uri
-import spray.httpx.SprayJsonSupport._
-import spray.json.DefaultJsonProtocol._
+import akka.http.scaladsl.server.Route
+import akka.http.scaladsl.model.Uri
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
+
import spray.json._
-import spray.routing.Directive.pimpApply
-import spray.routing.Route
+import spray.json.DefaultJsonProtocol._
+
import whisk.common.AkkaLogging
import whisk.common.Logging
import whisk.common.LoggingMarkers
import whisk.common.TransactionId
import whisk.core.WhiskConfig
import whisk.core.entitlement._
-import whisk.core.entitlement.EntitlementProvider
import whisk.core.entity._
import whisk.core.entity.ActivationId.ActivationIdGenerator
import whisk.core.entity.ExecManifest.Runtimes
import whisk.core.loadBalancer.LoadBalancerService
import whisk.http.BasicHttpService
import whisk.http.BasicRasService
-import scala.util.{Failure, Success}
-
/**
* The Controller is the service that provides the REST API for OpenWhisk.
*
* It extends the BasicRasService so it includes a ping endpoint for monitoring.
*
- * Spray sends messages to akka Actors -- the Controller is an Actor, ready to receive messages.
+ * Akka sends messages to akka Actors -- the Controller is an Actor, ready to receive messages.
*
* It is possible to deploy a hot-standby controller. Each controller needs its own instance. This instance is a
* consecutive numbering, starting with 0.
@@ -62,8 +60,7 @@ import scala.util.{Failure, Success}
* back to the base controller, there could be an inconsistency in the cache (e.g. if a user has updated an action). This
* inconsistency will be resolved by its own after removing the cached item, 5 minutes after it has been generated.
*
- * @Idioglossia uses the spray-routing DSL
- * http://spray.io/documentation/1.1.3/spray-routing/advanced-topics/understanding-dsl-structure/
+ * Uses the Akka routing DSL: http://doc.akka.io/docs/akka-http/current/scala/http/routing-dsl/overview.html
*
* @param config A set of properties needed to run an instance of the controller service
* @param instance if running in scale-out, a unique identifier for this instance in the group
@@ -72,46 +69,31 @@ import scala.util.{Failure, Success}
*/
class Controller(
override val instance: InstanceId,
+ override val port: Int,
runtimes: Runtimes,
implicit val whiskConfig: WhiskConfig,
implicit val logging: Logging)
- extends BasicRasService
- with Actor {
-
- // each akka Actor has an implicit context
- override def actorRefFactory: ActorContext = context
+ extends BasicRasService {
override val numberOfInstances = whiskConfig.controllerInstances.toInt
+ TransactionId.controller.mark(this, LoggingMarkers.CONTROLLER_STARTUP(instance.toInt), s"starting controller instance ${instance.toInt}")
+
/**
- * A Route in spray is technically a function taking a RequestContext as a parameter.
- *
- * @Idioglossia The ~ spray DSL operator composes two independent Routes, building a routing
- * tree structure.
- * @see http://spray.io/documentation/1.2.3/spray-routing/key-concepts/routes/#composing-routes
- */
+ * A Route in Akka is technically a function taking a RequestContext as a parameter.
+ *
+ * The "~" Akka DSL operator composes two independent Routes, building a routing tree structure.
+ * @see http://doc.akka.io/docs/akka-http/current/scala/http/routing-dsl/routes.html#composing-routes
+ */
override def routes(implicit transid: TransactionId): Route = {
- // handleRejections wraps the inner Route with a logical error-handler for unmatched paths
- handleRejections(customRejectionHandler) {
- super.routes ~ {
- (pathEndOrSingleSlash & get) {
- complete(OK, info)
- }
- } ~ {
- apiv1.routes
- } ~ {
- swagger.swaggerRoutes
- } ~ {
- internalInvokerHealth
+ super.routes ~ {
+ (pathEndOrSingleSlash & get) {
+ complete(info)
}
- }
+ } ~ apiV1.routes ~ swagger.swaggerRoutes ~ internalInvokerHealth
}
- TransactionId.controller.mark(this, LoggingMarkers.CONTROLLER_STARTUP(instance.toInt), s"starting controller instance ${instance.toInt}")
-
// initialize datastores
- private implicit val actorSystem = context.system
- private implicit val executionContext = actorSystem.dispatcher
private implicit val authStore = WhiskAuthStore.datastore(whiskConfig)
private implicit val entityStore = WhiskEntityStore.datastore(whiskConfig)
private implicit val activationStore = WhiskActivationStore.datastore(whiskConfig)
@@ -126,7 +108,7 @@ class Controller(
/** The REST APIs. */
implicit val controllerInstance = instance
- private val apiv1 = new RestAPIVersion("api", "v1")
+ private val apiV1 = new RestAPIVersion(whiskConfig, "api", "v1")
private val swagger = new SwaggerDocs(Uri.Path.Empty, "infoswagger.json")
/**
@@ -145,7 +127,7 @@ class Controller(
}
// controller top level info
- private val info = Controller.info(whiskConfig, runtimes, List(apiv1.basepath()))
+ private val info = Controller.info(whiskConfig, runtimes, List(apiV1.basepath()))
}
/**
@@ -156,8 +138,7 @@ object Controller {
// requiredProperties is a Map whose keys define properties that must be bound to
// a value, and whose values are default values. A null value in the Map means there is
// no default value specified, so it must appear in the properties file
- def requiredProperties = Map(WhiskConfig.servicePort -> 8080.toString) ++
- Map(WhiskConfig.controllerInstances -> null) ++
+ def requiredProperties = Map(WhiskConfig.controllerInstances -> null) ++
ExecManifest.requiredProperties ++
RestApiCommons.requiredProperties ++
LoadBalancerService.requiredProperties ++
@@ -178,9 +159,9 @@ object Controller {
"runtimes" -> runtimes.toJson)
// akka-style factory to create a Controller object
- private class ServiceBuilder(config: WhiskConfig, instance: InstanceId, logging: Logging) extends Creator[Controller] {
+ private class ServiceBuilder(config: WhiskConfig, instance: InstanceId, logging: Logging, port: Int) extends Creator[Controller] {
// this method is not reached unless ExecManifest was initialized successfully
- def create = new Controller(instance, ExecManifest.runtimesManifest, config, logging)
+ def create = new Controller(instance, port, ExecManifest.runtimesManifest, config, logging)
}
def main(args: Array[String]): Unit = {
@@ -189,6 +170,7 @@ object Controller {
// extract configuration data from the environment
val config = new WhiskConfig(requiredProperties, optionalProperties)
+ val port = config.servicePort.toInt
// if deploying multiple instances (scale out), must pass the instance number as the
require(args.length >= 1, "controller instance required")
@@ -207,8 +189,7 @@ object Controller {
ExecManifest.initialize(config) match {
case Success(_) =>
- val port = config.servicePort.toInt
- BasicHttpService.startService(actorSystem, "controller", "0.0.0.0", port, new ServiceBuilder(config, InstanceId(instance), logger))
+ BasicHttpService.startService(actorSystem, "controller", "0.0.0.0", new ServiceBuilder(config, InstanceId(instance), logger, port))
case Failure(t) =>
logger.error(this, s"Invalid runtimes manifest: $t")
diff --git a/core/controller/src/main/scala/whisk/core/controller/Entities.scala b/core/controller/src/main/scala/whisk/core/controller/Entities.scala
index df8f45f..ebafac5 100644
--- a/core/controller/src/main/scala/whisk/core/controller/Entities.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/Entities.scala
@@ -19,16 +19,20 @@ package whisk.core.controller
import scala.language.postfixOps
import scala.util.Try
+import scala.concurrent.Future
+
+import akka.http.scaladsl.model.StatusCodes.RequestEntityTooLarge
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
+import akka.http.scaladsl.server.Directive0
+import akka.http.scaladsl.server.Directives
+import akka.http.scaladsl.server.RequestContext
+import akka.http.scaladsl.server.RouteResult
+import akka.http.scaladsl.server.Route
-import shapeless.HNil
-import spray.http.StatusCodes.RequestEntityTooLarge
-import spray.httpx.SprayJsonSupport._
-import spray.routing.Directive0
-import spray.routing.Directives
-import spray.routing.RequestContext
-import spray.routing.Route
import whisk.common.TransactionId
import whisk.core.entitlement.Privilege._
+import whisk.core.entitlement.Privilege.Privilege
+import whisk.core.entitlement.Privilege.READ
import whisk.core.entitlement.Resource
import whisk.core.entity._
import whisk.core.entity.ActivationEntityLimit
@@ -39,10 +43,10 @@ import whisk.http.Messages
protected[controller] trait ValidateRequestSize extends Directives {
protected def validateSize(check: => Option[SizeError])(
implicit tid: TransactionId) = new Directive0 {
- def happly(f: HNil => Route) = {
+ def tapply(f: Unit => Route) = {
check map {
case e: SizeError => terminate(RequestEntityTooLarge, Messages.entityTooBig(e))
- } getOrElse f(HNil)
+ } getOrElse f(None)
}
}
@@ -72,19 +76,19 @@ trait WhiskCollectionAPI
services: WhiskServices =>
/** Creates an entity, or updates an existing one, in namespace. Terminates HTTP request. */
- protected def create(user: Identity, entityName: FullyQualifiedEntityName)(implicit transid: TransactionId): RequestContext => Unit
+ protected def create(user: Identity, entityName: FullyQualifiedEntityName)(implicit transid: TransactionId): RequestContext => Future[RouteResult]
/** Activates entity. Examples include invoking an action, firing a trigger, enabling/disabling a rule. */
- protected def activate(user: Identity, entityName: FullyQualifiedEntityName, env: Option[Parameters])(implicit transid: TransactionId): RequestContext => Unit
+ protected def activate(user: Identity, entityName: FullyQualifiedEntityName, env: Option[Parameters])(implicit transid: TransactionId): RequestContext => Future[RouteResult]
/** Removes entity from namespace. Terminates HTTP request. */
- protected def remove(user: Identity, entityName: FullyQualifiedEntityName)(implicit transid: TransactionId): RequestContext => Unit
+ protected def remove(user: Identity, entityName: FullyQualifiedEntityName)(implicit transid: TransactionId): RequestContext => Future[RouteResult]
/** Gets entity from namespace. Terminates HTTP request. */
- protected def fetch(user: Identity, entityName: FullyQualifiedEntityName, env: Option[Parameters])(implicit transid: TransactionId): RequestContext => Unit
+ protected def fetch(user: Identity, entityName: FullyQualifiedEntityName, env: Option[Parameters])(implicit transid: TransactionId): RequestContext => Future[RouteResult]
/** Gets all entities from namespace. If necessary filter only entities that are shared. Terminates HTTP request. */
- protected def list(user: Identity, path: EntityPath, excludePrivate: Boolean)(implicit transid: TransactionId): RequestContext => Unit
+ protected def list(user: Identity, path: EntityPath, excludePrivate: Boolean)(implicit transid: TransactionId): RequestContext => Future[RouteResult]
/** Indicates if listing entities in collection requires filtering out private entities. */
protected val listRequiresPrivateEntityFilter = false // currently supported on PACKAGES only
@@ -101,8 +105,8 @@ trait WhiskCollectionAPI
}
}
case ACTIVATE =>
- extract(_.request.entity.data.length) { length =>
- validateSize(isWhithinRange(length))(transid) {
+ extract(_.request.entity.contentLengthOption) { length =>
+ validateSize(isWhithinRange(length.getOrElse(0)))(transid) {
activate(user, FullyQualifiedEntityName(resource.namespace, name), resource.env)
}
}
diff --git a/core/controller/src/main/scala/whisk/core/controller/Namespaces.scala b/core/controller/src/main/scala/whisk/core/controller/Namespaces.scala
index 0b3c144..86dbb8b 100644
--- a/core/controller/src/main/scala/whisk/core/controller/Namespaces.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/Namespaces.scala
@@ -17,14 +17,18 @@
package whisk.core.controller
+import scala.concurrent.Future
import scala.util.Failure
import scala.util.Success
-import spray.http.StatusCodes.InternalServerError
-import spray.http.StatusCodes.OK
-import spray.httpx.SprayJsonSupport._
+import akka.http.scaladsl.model.StatusCodes._
+import akka.http.scaladsl.server.Directives
+import akka.http.scaladsl.server.RequestContext
+import akka.http.scaladsl.server.RouteResult
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
+
import spray.json.DefaultJsonProtocol._
-import spray.routing.Directives
+
import whisk.common.TransactionId
import whisk.core.entitlement.Collection
import whisk.core.entitlement.Privilege.Privilege
@@ -95,7 +99,7 @@ trait WhiskNamespacesApi
* - 200 Map [ String (collection name), List[EntitySummary] ] as JSON
* - 500 Internal Server Error
*/
- private def getAllInNamespace(namespace: EntityPath)(implicit transid: TransactionId) = {
+ private def getAllInNamespace(namespace: EntityPath)(implicit transid: TransactionId): RequestContext => Future[RouteResult] = {
onComplete(listEntitiesInNamespace(entityStore, namespace, false)) {
case Success(entities) => {
complete(OK, Namespaces.emptyNamespace ++ entities - WhiskActivation.collectionName)
diff --git a/core/controller/src/main/scala/whisk/core/controller/Packages.scala b/core/controller/src/main/scala/whisk/core/controller/Packages.scala
index 9ed59da..ce6f4cf 100644
--- a/core/controller/src/main/scala/whisk/core/controller/Packages.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/Packages.scala
@@ -22,11 +22,13 @@ import scala.util.Failure
import scala.util.Success
import scala.util.Try
-import spray.http.StatusCodes._
-import spray.httpx.SprayJsonSupport._
+import akka.http.scaladsl.model.StatusCodes._
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
+import akka.http.scaladsl.server.RequestContext
+import akka.http.scaladsl.server.RouteResult
+
import spray.json._
-import spray.routing.Directive.pimpApply
-import spray.routing.RequestContext
+
import whisk.common.TransactionId
import whisk.core.database.DocumentTypeMismatchException
import whisk.core.database.NoDocumentException
@@ -252,7 +254,7 @@ trait WhiskPackagesApi extends WhiskCollectionAPI with ReferencedEntities {
}
private def rewriteEntitlementFailure(failure: Throwable)(
- implicit transid: TransactionId): RequestContext => Unit = {
+ implicit transid: TransactionId): RequestContext => Future[RouteResult] = {
logging.info(this, s"rewriting failure $failure")
failure match {
case RejectRequest(NotFound, _) => terminate(BadRequest, Messages.bindingDoesNotExist)
@@ -279,7 +281,7 @@ trait WhiskPackagesApi extends WhiskCollectionAPI with ReferencedEntities {
* If this is a binding, fetch package for binding, merge parameters then emit.
* Otherwise this is a package, emit it.
*/
- private def mergePackageWithBinding(ref: Option[WhiskPackage] = None)(wp: WhiskPackage)(implicit transid: TransactionId): RequestContext => Unit = {
+ private def mergePackageWithBinding(ref: Option[WhiskPackage] = None)(wp: WhiskPackage)(implicit transid: TransactionId): RequestContext => Future[RouteResult] = {
wp.binding map {
case b: Binding =>
val docid = b.fullyQualifiedName.toDocId
diff --git a/core/controller/src/main/scala/whisk/core/controller/RestAPIs.scala b/core/controller/src/main/scala/whisk/core/controller/RestAPIs.scala
index 2088831..1d060d8 100644
--- a/core/controller/src/main/scala/whisk/core/controller/RestAPIs.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/RestAPIs.scala
@@ -17,39 +17,37 @@
package whisk.core.controller
-import scala.concurrent.ExecutionContext
-
-import RestApiCommons._
import akka.actor.ActorSystem
-import spray.http.AllOrigins
-import spray.http.HttpHeaders._
-import spray.http.StatusCodes._
-import spray.http.Uri
-import spray.httpx.SprayJsonSupport._
+import akka.stream.ActorMaterializer
+import akka.http.scaladsl.model.StatusCodes._
+import akka.http.scaladsl.model.Uri
+import akka.http.scaladsl.server.Directives
+import akka.http.scaladsl.server.Route
+import akka.http.scaladsl.model.headers._
+
import spray.json._
import spray.json.DefaultJsonProtocol._
-import spray.routing.Directive.pimpApply
-import spray.routing.Directives
-import spray.routing.Route
-import whisk.common.Logging
+
+import scala.concurrent.ExecutionContext
+
import whisk.common.TransactionId
import whisk.core.WhiskConfig
import whisk.core.WhiskConfig.whiskVersionBuildno
import whisk.core.WhiskConfig.whiskVersionDate
-import whisk.core.entitlement._
+import whisk.core.entity.WhiskAuthStore
+import whisk.common.Logging
+import whisk.common.TransactionId
import whisk.core.entity._
-import whisk.core.entity.ActivationId.ActivationIdGenerator
import whisk.core.entity.types._
+import whisk.core.entitlement._
+import whisk.core.entity.ActivationId.ActivationIdGenerator
import whisk.core.loadBalancer.LoadBalancerService
/**
* Abstract class which provides basic Directives which are used to construct route structures
* which are common to all versions of the Rest API.
*/
-protected[controller] class SwaggerDocs(
- apipath: Uri.Path,
- doc: String)(
- implicit actorSystem: ActorSystem)
+protected[controller] class SwaggerDocs(apipath: Uri.Path, doc: String)(implicit actorSystem: ActorSystem)
extends Directives {
/** Swagger end points. */
@@ -79,40 +77,41 @@ protected[controller] class SwaggerDocs(
private def apiDocsUrl = basepath(apipath / swaggerdocpath)
}
-/**
- * A singleton object which defines properties needed to instantiate a service for v1 or v2
- * of the REST API.
- */
protected[controller] object RestApiCommons {
- def requiredProperties =
+ def requiredProperties = Map(WhiskConfig.servicePort -> 8080.toString) ++
WhiskConfig.whiskVersion ++
- WhiskAuthStore.requiredProperties ++
- WhiskEntityStore.requiredProperties ++
- WhiskActivationStore.requiredProperties ++
- EntitlementProvider.requiredProperties ++
- WhiskActionsApi.requiredProperties ++
- Authenticate.requiredProperties ++
- Collection.requiredProperties
+ WhiskAuthStore.requiredProperties ++
+ WhiskEntityStore.requiredProperties ++
+ WhiskActivationStore.requiredProperties ++
+ EntitlementProvider.requiredProperties ++
+ WhiskActionsApi.requiredProperties ++
+ Authenticate.requiredProperties ++
+ Collection.requiredProperties
+
+ import akka.http.scaladsl.unmarshalling.FromEntityUnmarshaller
+ import akka.http.scaladsl.unmarshalling.Unmarshaller
+ import akka.http.scaladsl.model.MediaTypes.`application/json`
+ import akka.http.scaladsl.model.HttpCharsets
/**
- * The web actions API is available in both v1 and v2.
- * It handles web actions.
+ * Extract an empty entity into a JSON object. This is useful for the
+ * main APIs which accept JSON content type by default but may accept
+ * no entity in the request.
*/
- protected[controller] class WebActionsApi(
- override val webInvokePathSegments: Seq[String],
- override val webApiDirectives: WebApiDirectives)(
- implicit override val authStore: AuthStore,
- implicit val entityStore: EntityStore,
- override val activeAckTopicIndex: InstanceId,
- override val activationStore: ActivationStore,
- override val entitlementProvider: EntitlementProvider,
- override val activationIdFactory: ActivationIdGenerator,
- override val loadBalancer: LoadBalancerService,
- override val actorSystem: ActorSystem,
- override val executionContext: ExecutionContext,
- override val logging: Logging,
- override val whiskConfig: WhiskConfig)
- extends WhiskWebActionsApi with WhiskServices
+ implicit val emptyEntityToJsObject: FromEntityUnmarshaller[JsObject] = {
+ Unmarshaller.byteStringUnmarshaller.forContentTypes(`application/json`).mapWithCharset { (data, charset) =>
+ if (data.size == 0) {
+ JsObject()
+ } else {
+ val input = {
+ if (charset == HttpCharsets.`UTF-8`) ParserInput(data.toArray)
+ else ParserInput(data.decodeString(charset.nioCharset))
+ }
+
+ JsonParser(input).asJsObject
+ }
+ }
+ }
}
/**
@@ -120,60 +119,65 @@ protected[controller] object RestApiCommons {
* Useful for CORS.
*/
protected[controller] trait RespondWithHeaders extends Directives {
- val allowOrigin = `Access-Control-Allow-Origin`(AllOrigins)
+ val allowOrigin = `Access-Control-Allow-Origin`.*
val allowHeaders = `Access-Control-Allow-Headers`("Authorization", "Content-Type")
-
val sendCorsHeaders = respondWithHeaders(allowOrigin, allowHeaders)
}
-/**
- * An object which creates the Routes that define v1 of the whisk REST API.
- */
-protected[controller] class RestAPIVersion(apipath: String, apiversion: String)(
+class RestAPIVersion(config: WhiskConfig, apiPath: String, apiVersion: String)(
implicit val activeAckTopicIndex: InstanceId,
- implicit val authStore: AuthStore,
+ implicit val actorSystem: ActorSystem,
+ implicit val logging: Logging,
implicit val entityStore: EntityStore,
- implicit val activationStore: ActivationStore,
implicit val entitlementProvider: EntitlementProvider,
implicit val activationIdFactory: ActivationIdGenerator,
implicit val loadBalancer: LoadBalancerService,
- implicit val actorSystem: ActorSystem,
- implicit val executionContext: ExecutionContext,
- implicit val logging: Logging,
+ implicit val activationStore: ActivationStore,
implicit val whiskConfig: WhiskConfig)
- extends SwaggerDocs(Uri.Path(apipath) / apiversion, "apiv1swagger.json")
+ extends SwaggerDocs(Uri.Path(apiPath) / apiVersion, "apiv1swagger.json")
with Authenticate
with AuthenticatedRoute
with RespondWithHeaders {
+ implicit val materializer = ActorMaterializer()
+ implicit val executionContext = actorSystem.dispatcher
+ implicit val authStore = WhiskAuthStore.datastore(config)
+
+ def prefix = pathPrefix(apiPath / apiVersion)
/**
- * Here is the key method: it defines the Route (route tree) which implement v1 of the REST API.
- *
- * @Idioglossia This relies on the spray routing DSL.
- * @see http://spray.io/documentation/1.2.2/spray-routing/
+ * Describes details of a particular API path.
*/
+ val info = (pathEndOrSingleSlash & get) {
+ complete(OK, JsObject(
+ "description" -> "OpenWhisk API".toJson,
+ "api_version" -> SemVer(1, 0, 0).toJson,
+ "api_version_path" -> apiVersion.toJson,
+ "build" -> whiskConfig(whiskVersionDate).toJson,
+ "buildno" -> whiskConfig(whiskVersionBuildno).toJson,
+ "swagger_paths" -> JsObject(
+ "ui" -> s"/$swaggeruipath".toJson,
+ "api-docs" -> s"/$swaggerdocpath".toJson)).toString)
+ }
+
def routes(implicit transid: TransactionId): Route = {
- pathPrefix(apipath / apiversion) {
+ prefix {
sendCorsHeaders {
- (pathEndOrSingleSlash & get) {
- complete(OK, info)
- } ~ authenticate(basicauth) {
- user =>
- namespaces.routes(user) ~
- pathPrefix(Collection.NAMESPACES) {
- actions.routes(user) ~
- triggers.routes(user) ~
- rules.routes(user) ~
- activations.routes(user) ~
- packages.routes(user)
- }
+ info ~ basicAuth(validateCredentials) { user =>
+ namespaces.routes(user) ~
+ pathPrefix(Collection.NAMESPACES) {
+ actions.routes(user) ~
+ triggers.routes(user) ~
+ rules.routes(user) ~
+ activations.routes(user) ~
+ packages.routes(user)
+ }
} ~ {
swaggerRoutes
}
} ~ {
// web actions are distinct to separate the cors header
// and allow the actions themselves to respond to options
- authenticate(basicauth) { user =>
+ basicAuth(validateCredentials) { user =>
web.routes(user) ~ webexp.routes(user)
} ~ {
web.routes() ~ webexp.routes()
@@ -184,102 +188,107 @@ protected[controller] class RestAPIVersion(apipath: String, apiversion: String)(
}
}
}
+
}
- private val namespaces = new NamespacesApi(apipath, apiversion)
- private val actions = new ActionsApi(apipath, apiversion)
- private val triggers = new TriggersApi(apipath, apiversion)
- private val rules = new RulesApi(apipath, apiversion)
- private val activations = new ActivationsApi(apipath, apiversion)
- private val packages = new PackagesApi(apipath, apiversion)
+ private val namespaces = new NamespacesApi(apiPath, apiVersion)
+ private val actions = new ActionsApi(apiPath, apiVersion)
+ private val packages = new PackagesApi(apiPath, apiVersion)
+ private val triggers = new TriggersApi(apiPath, apiVersion)
+ private val activations = new ActivationsApi(apiPath, apiVersion)
+ private val rules = new RulesApi(apiPath, apiVersion)
private val webexp = new WebActionsApi(Seq("experimental", "web"), WebApiDirectives.exp)
private val web = new WebActionsApi(Seq("web"), WebApiDirectives.web)
- /**
- * Describes details of a particular API path.
- */
- private val info = JsObject(
- "description" -> "OpenWhisk API".toJson,
- "api_version" -> SemVer(1, 0, 0).toJson,
- "api_version_path" -> apiversion.toJson,
- "build" -> whiskConfig(whiskVersionDate).toJson,
- "buildno" -> whiskConfig(whiskVersionBuildno).toJson,
- "swagger_paths" -> JsObject(
- "ui" -> s"/$swaggeruipath".toJson,
- "api-docs" -> s"/$swaggerdocpath".toJson))
-
class NamespacesApi(
- val apipath: String,
- val apiversion: String)(
- implicit override val entityStore: EntityStore,
- override val entitlementProvider: EntitlementProvider,
- override val executionContext: ExecutionContext,
- override val logging: Logging)
- extends WhiskNamespacesApi
+ val apiPath: String,
+ val apiVersion: String)(
+ implicit override val entityStore: EntityStore,
+ override val entitlementProvider: EntitlementProvider,
+ override val executionContext: ExecutionContext,
+ override val logging: Logging)
+ extends WhiskNamespacesApi
class ActionsApi(
- val apipath: String,
- val apiversion: String)(
- implicit override val actorSystem: ActorSystem,
- override val activeAckTopicIndex: InstanceId,
- override val entityStore: EntityStore,
- override val activationStore: ActivationStore,
- override val entitlementProvider: EntitlementProvider,
- override val activationIdFactory: ActivationIdGenerator,
- override val loadBalancer: LoadBalancerService,
- override val executionContext: ExecutionContext,
- override val logging: Logging,
- override val whiskConfig: WhiskConfig)
- extends WhiskActionsApi with WhiskServices {
+ val apiPath: String,
+ val apiVersion: String)(
+ implicit override val actorSystem: ActorSystem,
+ override val activeAckTopicIndex: InstanceId,
+ override val entityStore: EntityStore,
+ override val activationStore: ActivationStore,
+ override val entitlementProvider: EntitlementProvider,
+ override val activationIdFactory: ActivationIdGenerator,
+ override val loadBalancer: LoadBalancerService,
+ override val executionContext: ExecutionContext,
+ override val logging: Logging,
+ override val whiskConfig: WhiskConfig)
+ extends WhiskActionsApi with WhiskServices {
logging.info(this, s"actionSequenceLimit '${whiskConfig.actionSequenceLimit}'")
assert(whiskConfig.actionSequenceLimit.toInt > 0)
}
- class TriggersApi(
- val apipath: String,
- val apiversion: String)(
- implicit override val actorSystem: ActorSystem,
- implicit override val entityStore: EntityStore,
- override val entitlementProvider: EntitlementProvider,
- override val activationStore: ActivationStore,
- override val activationIdFactory: ActivationIdGenerator,
- override val loadBalancer: LoadBalancerService,
- override val executionContext: ExecutionContext,
- override val logging: Logging,
- override val whiskConfig: WhiskConfig)
- extends WhiskTriggersApi with WhiskServices
+ class ActivationsApi(
+ val apiPath: String,
+ val apiVersion: String)(
+ implicit override val activationStore: ActivationStore,
+ override val entitlementProvider: EntitlementProvider,
+ override val executionContext: ExecutionContext,
+ override val logging: Logging)
+ extends WhiskActivationsApi
+
+ class PackagesApi(
+ val apiPath: String,
+ val apiVersion: String)(
+ implicit override val entityStore: EntityStore,
+ override val entitlementProvider: EntitlementProvider,
+ override val activationIdFactory: ActivationIdGenerator,
+ override val loadBalancer: LoadBalancerService,
+ override val executionContext: ExecutionContext,
+ override val logging: Logging,
+ override val whiskConfig: WhiskConfig)
+ extends WhiskPackagesApi with WhiskServices
class RulesApi(
- val apipath: String,
- val apiversion: String)(
- implicit override val actorSystem: ActorSystem,
- override val entityStore: EntityStore,
- override val entitlementProvider: EntitlementProvider,
- override val activationIdFactory: ActivationIdGenerator,
- override val loadBalancer: LoadBalancerService,
- override val executionContext: ExecutionContext,
- override val logging: Logging,
- override val whiskConfig: WhiskConfig)
- extends WhiskRulesApi with WhiskServices
+ val apiPath: String,
+ val apiVersion: String)(
+ implicit override val actorSystem: ActorSystem,
+ override val entityStore: EntityStore,
+ override val entitlementProvider: EntitlementProvider,
+ override val activationIdFactory: ActivationIdGenerator,
+ override val loadBalancer: LoadBalancerService,
+ override val executionContext: ExecutionContext,
+ override val logging: Logging,
+ override val whiskConfig: WhiskConfig)
+ extends WhiskRulesApi with WhiskServices
- class ActivationsApi(
- val apipath: String,
- val apiversion: String)(
- implicit override val activationStore: ActivationStore,
- override val entitlementProvider: EntitlementProvider,
- override val executionContext: ExecutionContext,
- override val logging: Logging)
- extends WhiskActivationsApi
+ class TriggersApi(
+ val apiPath: String,
+ val apiVersion: String)(
+ implicit override val actorSystem: ActorSystem,
+ implicit override val entityStore: EntityStore,
+ override val entitlementProvider: EntitlementProvider,
+ override val activationStore: ActivationStore,
+ override val activationIdFactory: ActivationIdGenerator,
+ override val loadBalancer: LoadBalancerService,
+ override val executionContext: ExecutionContext,
+ override val logging: Logging,
+ override val whiskConfig: WhiskConfig,
+ override val materializer: ActorMaterializer)
+ extends WhiskTriggersApi with WhiskServices
- class PackagesApi(
- val apipath: String,
- val apiversion: String)(
- implicit override val entityStore: EntityStore,
- override val entitlementProvider: EntitlementProvider,
- override val activationIdFactory: ActivationIdGenerator,
- override val loadBalancer: LoadBalancerService,
- override val executionContext: ExecutionContext,
- override val logging: Logging,
- override val whiskConfig: WhiskConfig)
- extends WhiskPackagesApi with WhiskServices
+ protected[controller] class WebActionsApi(
+ override val webInvokePathSegments: Seq[String],
+ override val webApiDirectives: WebApiDirectives)(
+ implicit override val authStore: AuthStore,
+ implicit val entityStore: EntityStore,
+ override val activeAckTopicIndex: InstanceId,
+ override val activationStore: ActivationStore,
+ override val entitlementProvider: EntitlementProvider,
+ override val activationIdFactory: ActivationIdGenerator,
+ override val loadBalancer: LoadBalancerService,
+ override val actorSystem: ActorSystem,
+ override val executionContext: ExecutionContext,
+ override val logging: Logging,
+ override val whiskConfig: WhiskConfig)
+ extends WhiskWebActionsApi with WhiskServices
}
diff --git a/core/controller/src/main/scala/whisk/core/controller/Rules.scala b/core/controller/src/main/scala/whisk/core/controller/Rules.scala
index c3882fa..be0e6eb 100644
--- a/core/controller/src/main/scala/whisk/core/controller/Rules.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/Rules.scala
@@ -22,19 +22,22 @@ import scala.util.Failure
import scala.util.Success
import akka.actor.ActorSystem
-import spray.http.StatusCodes._
-import spray.httpx.SprayJsonSupport._
+import akka.http.scaladsl.model.StatusCodes._
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
+import akka.http.scaladsl.server.StandardRoute
+
import spray.json.DeserializationException
-import spray.routing.Directive.pimpApply
-import spray.routing.RequestContext
+
import whisk.common.TransactionId
import whisk.core.database.DocumentConflictException
import whisk.core.database.NoDocumentException
-import whisk.core.entitlement._
import whisk.core.entity._
import whisk.core.entity.types.EntityStore
import whisk.http.ErrorResponse.terminate
import whisk.http.Messages._
+import whisk.core.entitlement.Collection
+import whisk.core.entitlement.Privilege
+import whisk.core.entitlement.ReferencedEntities
/** A trait implementing the rules API */
trait WhiskRulesApi extends WhiskCollectionAPI with ReferencedEntities {
@@ -338,7 +341,7 @@ trait WhiskRulesApi extends WhiskCollectionAPI with ReferencedEntities {
* @param rule the rule to send
* @param status the status to include in the response
*/
- private def completeAsRuleResponse(rule: WhiskRule, status: Status = Status.INACTIVE): RequestContext => Unit = {
+ private def completeAsRuleResponse(rule: WhiskRule, status: Status = Status.INACTIVE): StandardRoute = {
complete(OK, rule.withStatus(status))
}
diff --git a/core/controller/src/main/scala/whisk/core/controller/Triggers.scala b/core/controller/src/main/scala/whisk/core/controller/Triggers.scala
index c2dba80..6e0028c 100644
--- a/core/controller/src/main/scala/whisk/core/controller/Triggers.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/Triggers.scala
@@ -21,29 +21,32 @@ import java.time.Clock
import java.time.Instant
import scala.concurrent.Future
-import scala.util.Failure
-import scala.util.Success
-import spray.client.pipelining.Post
+import scala.util.{ Failure, Success }
import akka.actor.ActorSystem
-import spray.client.pipelining._
-import spray.http.BasicHttpCredentials
-import spray.http.HttpRequest
-import spray.http.StatusCodes.BadRequest
-import spray.http.StatusCodes.InternalServerError
-import spray.http.StatusCodes.OK
-import spray.http.Uri
-import spray.http.Uri.Path
-import spray.httpx.SprayJsonSupport.sprayJsonMarshaller
-import spray.httpx.SprayJsonSupport.sprayJsonUnmarshaller
-import spray.httpx.marshalling.ToResponseMarshallable.isMarshallable
-import spray.json.JsObject
-import spray.json.JsString
+import akka.http.scaladsl.model.headers.BasicHttpCredentials
+import akka.http.scaladsl.model.HttpRequest
+import akka.http.scaladsl.model.StatusCodes
+import akka.http.scaladsl.model.StatusCodes.BadRequest
+import akka.http.scaladsl.model.StatusCodes.InternalServerError
+import akka.http.scaladsl.model.StatusCodes.OK
+import akka.http.scaladsl.model.Uri
+import akka.http.scaladsl.model.Uri.Path
+import akka.http.scaladsl.server.RouteResult
+import akka.http.scaladsl.model.HttpMethods.POST
+import akka.http.scaladsl.model.headers.Authorization
+import akka.http.scaladsl.model.HttpMethods._
+import akka.http.scaladsl.model.MediaTypes
+import akka.http.scaladsl.model.HttpEntity
+import akka.http.scaladsl.server.RequestContext
+import akka.http.scaladsl.Http
+import akka.http.scaladsl.model.HttpResponse
+import akka.stream.ActorMaterializer
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
+
+import spray.json._
import spray.json.DefaultJsonProtocol.RootJsObjectFormat
-import spray.routing.Directive.pimpApply
-import spray.routing.directives.OnCompleteFutureMagnet.apply
-import spray.routing.directives.ParamDefMagnet.apply
-import spray.routing.RequestContext
+
import whisk.common.TransactionId
import whisk.core.entitlement.Collection
import whisk.core.entity.ActivationResponse
@@ -58,8 +61,6 @@ import whisk.core.entity.WhiskTriggerPut
import whisk.core.entity.types.ActivationStore
import whisk.core.entity.types.EntityStore
import whisk.http.ErrorResponse.terminate
-import spray.httpx.UnsuccessfulResponseException
-import spray.http.StatusCodes
import whisk.core.entity.Identity
import whisk.core.entity.FullyQualifiedEntityName
@@ -81,6 +82,10 @@ trait WhiskTriggersApi extends WhiskCollectionAPI {
/** Path to Triggers REST API. */
protected val triggersPath = "triggers"
+ protected implicit val materializer: ActorMaterializer
+
+ import RestApiCommons.emptyEntityToJsObject
+
/**
* Creates or updates trigger if it already exists. The PUT content is deserialized into a WhiskTriggerPut
* which is a subset of WhiskTrigger (it eschews the namespace and entity name since the former is derived
@@ -139,12 +144,7 @@ trait WhiskTriggersApi extends WhiskCollectionAPI {
val saveTriggerActivation = WhiskActivation.put(activationStore, triggerActivation) map {
_ => triggerActivationId
}
-
val url = Uri(s"http://localhost:${whiskConfig.servicePort}")
- val pipeline: HttpRequest => Future[JsObject] = (
- addCredentials(BasicHttpCredentials(user.authkey.uuid.toString, user.authkey.key.toString))
- ~> sendReceive
- ~> unmarshal[JsObject])
trigger.rules.map {
_.filter {
@@ -173,16 +173,20 @@ trait WhiskTriggersApi extends WhiskCollectionAPI {
Path.SingleSlash + rule.action.name.asString
}
}.toString
-
val actionUrl = Path("/api/v1") / "namespaces" / actionNamespace / "actions"
+ val request = HttpRequest(
+ method = POST,
+ uri = url.withPath(actionUrl + actionPath),
+ headers = List(Authorization(BasicHttpCredentials(user.authkey.uuid.asString, user.authkey.key.asString))),
+ entity = HttpEntity(MediaTypes.`application/json`, args.getOrElse(JsObject()).compactPrint))
- pipeline(Post(url.withPath(actionUrl + actionPath), args)) onComplete {
- case Success(o) =>
- logging.info(this, s"successfully invoked ${rule.action} -> ${o.fields("activationId")}")
- case Failure(usr: UnsuccessfulResponseException) if usr.response.status == StatusCodes.NotFound =>
+ Http().singleRequest(request).map {
+ case HttpResponse(StatusCodes.OK, headers, entity, _) =>
+ logging.info(this, s"successfully invoked ${rule.action} -> ")
+ case HttpResponse(StatusCodes.NotFound, _, _, _) =>
logging.info(this, s"action ${rule.action} could not be found")
- case Failure(t) =>
- logging.warn(this, s"action ${rule.action} could not be invoked due to ${t.getMessage}")
+ case HttpResponse(code, _, entity, _) =>
+ logging.warn(this, s"action ${rule.action} could not be invoked due to ${entity.getDataBytes.toString}")
}
}
}
@@ -321,7 +325,7 @@ trait WhiskTriggersApi extends WhiskCollectionAPI {
* @param rule the rule to send
* @param status the status to include in the response
*/
- private def completeAsTriggerResponse(trigger: WhiskTrigger): RequestContext => Unit = {
+ private def completeAsTriggerResponse(trigger: WhiskTrigger): RequestContext => Future[RouteResult] = {
complete(OK, trigger.withoutRules)
}
}
diff --git a/core/controller/src/main/scala/whisk/core/controller/WebActions.scala b/core/controller/src/main/scala/whisk/core/controller/WebActions.scala
index 138bea9..1c9ec8e 100644
--- a/core/controller/src/main/scala/whisk/core/controller/WebActions.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/WebActions.scala
@@ -17,31 +17,39 @@
package whisk.core.controller
-import java.util.Base64
-
import java.nio.charset.StandardCharsets
+import java.util.Base64
import scala.concurrent.Future
-import scala.util.Failure
-import scala.util.Success
-import scala.util.Try
+import scala.util.{ Failure, Success, Try }
+
+import akka.http.scaladsl.model.HttpEntity.Empty
+import akka.http.scaladsl.server.Directives
+import akka.http.scaladsl.model.HttpMethod
+import akka.http.scaladsl.model.HttpHeader
+import akka.http.scaladsl.model.MediaType
+import akka.http.scaladsl.model.MediaTypes
+import akka.http.scaladsl.model.MediaTypes._
+import akka.http.scaladsl.model.StatusCodes._
+import akka.http.scaladsl.model.StatusCode
+import akka.http.scaladsl.model.headers.RawHeader
+import akka.http.scaladsl.model.headers._
+import akka.http.scaladsl.model.Uri.Query
+import akka.http.scaladsl.model.HttpEntity
+import akka.http.scaladsl.server.Route
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
+import akka.http.scaladsl.model.headers.`Content-Type`
+import akka.http.scaladsl.model.ContentType
+import akka.http.scaladsl.model.ContentTypes
+import akka.http.scaladsl.model.FormData
+import akka.http.scaladsl.model.HttpMethods.{ OPTIONS, GET, DELETE, POST, PUT, HEAD, PATCH}
+import akka.http.scaladsl.model.HttpCharsets
-import WhiskWebActionsApi.MediaExtension
-import spray.http._
-import spray.http.HttpEntity.Empty
-import spray.http.HttpEntity.NonEmpty
-import spray.http.HttpHeaders._
-import spray.http.MediaTypes._
-import spray.http.StatusCodes._
-import spray.http.Uri.Query
-import spray.http.parser.HttpParser
-import spray.httpx.SprayJsonSupport._
import spray.json._
import spray.json.DefaultJsonProtocol._
-import spray.routing.Directives
-import spray.routing.RequestContext
-import spray.routing.Route
-import spray.http.HttpMethods.{ OPTIONS, GET, DELETE, POST, PUT, HEAD, PATCH }
+
+import WhiskWebActionsApi.MediaExtension
+
import whisk.common.TransactionId
import whisk.core.controller.actions.PostActionActivation
import whisk.core.database._
@@ -87,7 +95,7 @@ protected[controller] object WebApiDirectives {
private case class Context(
propertyMap: WebApiDirectives,
method: HttpMethod,
- headers: List[HttpHeader],
+ headers: Seq[HttpHeader],
path: String,
query: Query,
body: Option[JsValue] = None) {
@@ -106,7 +114,7 @@ private case class Context(
(queryParams ++ bodyParams) intersect reservedParams
}
- // attach the body to the context
+ // attach the body to the Context
def withBody(b: Option[JsValue]) = Context(propertyMap, method, headers, path, query, b)
def metadata(user: Option[Identity]): Map[String, JsValue] = {
@@ -118,7 +126,7 @@ private case class Context(
def toActionArgument(user: Option[Identity], boxQueryAndBody: Boolean): Map[String, JsValue] = {
val queryParams = if (boxQueryAndBody) {
- Map(propertyMap.query -> JsString(query.render(new StringRendering, StandardCharsets.UTF_8).get))
+ Map(propertyMap.query -> JsString(query.toString))
} else {
queryAsMap.map(kv => kv._1 -> JsString(kv._2))
}
@@ -178,21 +186,21 @@ protected[core] object WhiskWebActionsApi extends Directives {
extension: String,
defaultProjection: Option[List[String]],
projectionAllowed: Boolean,
- transcoder: (JsValue, TransactionId, WebApiDirectives) => RequestContext => Unit) {
+ transcoder: (JsValue, TransactionId, WebApiDirectives) => Route) {
val extensionLength = extension.length
}
- private def resultAsHtml(result: JsValue, transid: TransactionId, rp: WebApiDirectives): RequestContext => Unit = result match {
- case JsString(html) => respondWithMediaType(`text/html`) { complete(OK, html) }
+ private def resultAsHtml(result: JsValue, transid: TransactionId, rp: WebApiDirectives) = result match {
+ case JsString(html) => complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, html))
case _ => terminate(BadRequest, Messages.invalidMedia(`text/html`))(transid)
}
- private def resultAsSvg(result: JsValue, transid: TransactionId, rp: WebApiDirectives): RequestContext => Unit = result match {
- case JsString(svg) => respondWithMediaType(`image/svg+xml`) { complete(OK, svg) }
+ private def resultAsSvg(result: JsValue, transid: TransactionId, rp: WebApiDirectives) = result match {
+ case JsString(svg) => complete(HttpEntity(`image/svg+xml`, svg.getBytes))
case _ => terminate(BadRequest, Messages.invalidMedia(`image/svg+xml`))(transid)
}
- private def resultAsText(result: JsValue, transid: TransactionId, rp: WebApiDirectives): RequestContext => Unit = {
+ private def resultAsText(result: JsValue, transid: TransactionId, rp: WebApiDirectives) = {
result match {
case r: JsObject => complete(OK, r.prettyPrint)
case r: JsArray => complete(OK, r.prettyPrint)
@@ -203,7 +211,7 @@ protected[core] object WhiskWebActionsApi extends Directives {
}
}
- private def resultAsJson(result: JsValue, transid: TransactionId, rp: WebApiDirectives): RequestContext => Unit = {
+ private def resultAsJson(result: JsValue, transid: TransactionId, rp: WebApiDirectives) = {
result match {
case r: JsObject => complete(OK, r)
case r: JsArray => complete(OK, r)
@@ -211,7 +219,7 @@ protected[core] object WhiskWebActionsApi extends Directives {
}
}
- private def resultAsHttp(result: JsValue, transid: TransactionId, rp: WebApiDirectives): RequestContext => Unit = {
+ private def resultAsHttp(result: JsValue, transid: TransactionId, rp: WebApiDirectives) = {
Try {
val JsObject(fields) = result
val headers = fields.get("headers").map {
@@ -256,36 +264,31 @@ protected[core] object WhiskWebActionsApi extends Directives {
case _ => throw new Throwable("Invalid header")
}
- private def interpretHttpResponse(code: StatusCode, headers: List[RawHeader], str: String, transid: TransactionId): RequestContext => Unit = {
+ private def interpretHttpResponse(code: StatusCode, headers: List[RawHeader], str: String, transid: TransactionId) = {
val parsedHeader: Try[MediaType] = headers.find(_.lowercaseName == `Content-Type`.lowercaseName) match {
case Some(header) =>
- HttpParser.parseHeader(header) match {
- case Right(header: `Content-Type`) =>
- val mediaType = header.contentType.mediaType
+ MediaType.parse(header.value) match {
+ case Right(mediaType: MediaType) =>
// lookup the media type specified in the content header to see if it is a recognized type
MediaTypes.getForKey(mediaType.mainType -> mediaType.subType).map(Success(_)).getOrElse {
// this is a content-type that is not recognized, reject it
Failure(RejectRequest(BadRequest, Messages.httpUnknownContentType)(transid))
}
-
- case _ =>
- Failure(RejectRequest(BadRequest, Messages.httpUnknownContentType)(transid))
+ case _ => Failure(RejectRequest(BadRequest, Messages.httpUnknownContentType)(transid))
}
case None => Success(`text/html`)
}
parsedHeader.flatMap { mediaType =>
- if (mediaType.binary) {
- Try(HttpData(Base64.getDecoder().decode(str))).map((mediaType, _))
+ if (mediaType.binary || mediaType == `application/json`) {
+ Try(new String(Base64.getDecoder().decode(str), StandardCharsets.UTF_8)).map((mediaType, _))
} else {
- Success(mediaType, HttpData(str))
+ Success(mediaType, str)
}
} match {
- case Success((mediaType, data)) =>
+ case Success((mediaType, data: String)) =>
respondWithHeaders(headers) {
- respondWithMediaType(mediaType) {
- complete(code, data)
- }
+ complete(code, HttpEntity(ContentType(MediaType.customWithFixedCharset(mediaType.mainType, mediaType.subType, HttpCharsets.`UTF-8`)), data))
}
case Failure(RejectRequest(code, message)) =>
@@ -314,7 +317,7 @@ trait WhiskWebActionsApi
/** The prefix for web invokes e.g., /web. */
private lazy val webRoutePrefix = {
- pathPrefix(webInvokePathSegments.map(segmentStringToPathMatcher(_)).reduceLeft(_ / _))
+ pathPrefix(webInvokePathSegments.map(_segmentStringToPathMatcher(_)).reduceLeft(_ / _))
}
/** Allowed verbs. */
@@ -324,7 +327,7 @@ trait WhiskWebActionsApi
private lazy val packagePrefix = pathPrefix("default".r | EntityName.REGEX.r)
private val defaultCorsResponse = List(
- `Access-Control-Allow-Origin`(AllOrigins),
+ `Access-Control-Allow-Origin`.*,
`Access-Control-Allow-Methods`(OPTIONS, GET, DELETE, POST, PUT, HEAD, PATCH),
`Access-Control-Allow-Headers`(`Authorization`.name, `Content-Type`.name))
@@ -332,7 +335,7 @@ trait WhiskWebActionsApi
private val requestMethodParamsAndPath = {
extract { ctx =>
val method = ctx.request.method
- val query = ctx.request.message.uri.query
+ val query = ctx.request.uri.query()
val path = ctx.unmatchedPath.toString
val headers = ctx.request.headers
Context(webApiDirectives, method, headers, path, query)
@@ -415,7 +418,7 @@ trait WhiskWebActionsApi
// as the context body which may be the incoming request when the content type is JSON or formdata, or
// the raw body as __ow_body (and query parameters as __ow_query) otherwise
extract(_.request.entity) { e =>
- validateSize(isWhithinRange(e.data.length))(transid) {
+ validateSize(isWhithinRange(e.contentLengthOption.getOrElse(0)))(transid) {
requestMethodParamsAndPath { context =>
provide(fullyQualifiedActionName(actionName)) { fullActionName =>
onComplete(verifyWebAction(fullActionName, onBehalfOf.isDefined)) {
@@ -502,25 +505,26 @@ trait WhiskWebActionsApi
case Empty =>
process(None, isRawHttpAction)
- case NonEmpty(ContentType(`application/json`, _), json) if !isRawHttpAction =>
+ case HttpEntity.Strict(ContentTypes.`application/json`, _) if !isRawHttpAction =>
entity(as[JsObject]) { body =>
process(Some(body), isRawHttpAction)
}
- case NonEmpty(ContentType(`application/x-www-form-urlencoded`, _), form) if !isRawHttpAction =>
+ case HttpEntity.Strict(ContentType(MediaTypes.`application/x-www-form-urlencoded`, Some(HttpCharsets.`UTF-8`)), _) if !isRawHttpAction =>
entity(as[FormData]) { form =>
val body = form.fields.toMap.toJson.asJsObject
process(Some(body), isRawHttpAction)
}
- case NonEmpty(contentType, data) =>
- if (contentType.mediaType.binary) {
- Try(JsString(Base64.getEncoder.encodeToString(data.toByteArray))) match {
+ case HttpEntity.Strict(contentType, data) =>
+ // application/json is not a binary type in Akka, but is binary in Spray
+ if (contentType.mediaType.binary || contentType.mediaType == `application/json`) {
+ Try(JsString(Base64.getEncoder.encodeToString(data.toArray))) match {
case Success(bytes) => process(Some(bytes), isRawHttpAction)
case Failure(t) => terminate(BadRequest, Messages.unsupportedContentType(contentType.mediaType))
}
} else {
- val str = JsString(data.asString(HttpCharsets.`UTF-8`))
+ val str = JsString(data.utf8String)
process(Some(str), isRawHttpAction)
}
@@ -596,8 +600,7 @@ trait WhiskWebActionsApi
logging.info(this, "activation waiting period expired")
terminate(Accepted, Messages.responseNotReady)
- case Failure(t: RejectRequest) =>
- terminate(t.code, t.message)
+ case Failure(t: RejectRequest) => terminate(t.code, t.message)
case Failure(t) =>
logging.error(this, s"exception in completeRequest: $t")
diff --git a/core/controller/src/main/scala/whisk/core/controller/actions/PostActionActivation.scala b/core/controller/src/main/scala/whisk/core/controller/actions/PostActionActivation.scala
index abd294a..03fc8be 100644
--- a/core/controller/src/main/scala/whisk/core/controller/actions/PostActionActivation.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/actions/PostActionActivation.scala
@@ -20,8 +20,10 @@ package whisk.core.controller.actions
import scala.concurrent.Future
import scala.concurrent.duration.FiniteDuration
-import spray.http.StatusCodes.BadRequest
+import akka.http.scaladsl.model.StatusCodes.BadRequest
+
import spray.json._
+
import whisk.common.TransactionId
import whisk.core.controller.RejectRequest
import whisk.core.controller.WhiskServices
diff --git a/core/controller/src/main/scala/whisk/core/controller/actions/SequenceActions.scala b/core/controller/src/main/scala/whisk/core/controller/actions/SequenceActions.scala
index 9efaf17..55bfac4 100644
--- a/core/controller/src/main/scala/whisk/core/controller/actions/SequenceActions.scala
+++ b/core/controller/src/main/scala/whisk/core/controller/actions/SequenceActions.scala
@@ -32,6 +32,7 @@ import scala.util.Success
import akka.actor.ActorSystem
import spray.json._
+
import whisk.common.Logging
import whisk.common.TransactionId
import whisk.core.controller.WhiskServices
diff --git a/core/controller/src/main/scala/whisk/core/entitlement/ActionCollection.scala b/core/controller/src/main/scala/whisk/core/entitlement/ActionCollection.scala
index 3656085..1691f4a 100644
--- a/core/controller/src/main/scala/whisk/core/entitlement/ActionCollection.scala
+++ b/core/controller/src/main/scala/whisk/core/entitlement/ActionCollection.scala
@@ -17,10 +17,11 @@
package whisk.core.entitlement
+import whisk.core.entitlement.Privilege._
+
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
-import Privilege.Privilege
import whisk.common.TransactionId
import whisk.core.entity.Identity
import whisk.core.entity.types.EntityStore
diff --git a/core/controller/src/main/scala/whisk/core/entitlement/Collection.scala b/core/controller/src/main/scala/whisk/core/entitlement/Collection.scala
index 2cb1c7c..be406a6 100644
--- a/core/controller/src/main/scala/whisk/core/entitlement/Collection.scala
+++ b/core/controller/src/main/scala/whisk/core/entitlement/Collection.scala
@@ -17,15 +17,17 @@
package whisk.core.entitlement
+import whisk.core.entitlement.Privilege._
+
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
-import Privilege.Privilege
-import spray.http.HttpMethod
-import spray.http.HttpMethods.DELETE
-import spray.http.HttpMethods.GET
-import spray.http.HttpMethods.POST
-import spray.http.HttpMethods.PUT
+import akka.http.scaladsl.model.HttpMethod
+import akka.http.scaladsl.model.HttpMethods.DELETE
+import akka.http.scaladsl.model.HttpMethods.GET
+import akka.http.scaladsl.model.HttpMethods.POST
+import akka.http.scaladsl.model.HttpMethods.PUT
+
import whisk.common.Logging
import whisk.common.TransactionId
import whisk.core.entity.Identity
diff --git a/core/controller/src/main/scala/whisk/core/entitlement/Entitlement.scala b/core/controller/src/main/scala/whisk/core/entitlement/Entitlement.scala
index e6b6d19..aa5d634 100644
--- a/core/controller/src/main/scala/whisk/core/entitlement/Entitlement.scala
+++ b/core/controller/src/main/scala/whisk/core/entitlement/Entitlement.scala
@@ -22,12 +22,13 @@ import scala.concurrent.Future
import scala.util.Failure
import scala.util.Success
-import Privilege.ACTIVATE
-import Privilege.Privilege
-import Privilege.REJECT
import akka.actor.ActorSystem
-import spray.http.StatusCodes.Forbidden
-import spray.http.StatusCodes.TooManyRequests
+import akka.http.scaladsl.model.StatusCodes.Forbidden
+import akka.http.scaladsl.model.StatusCodes.TooManyRequests
+
+import whisk.core.entitlement.Privilege.ACTIVATE
+import whisk.core.entitlement.Privilege._
+import whisk.core.entitlement.Privilege.REJECT
import whisk.common.Logging
import whisk.common.TransactionId
import whisk.core.WhiskConfig
diff --git a/core/controller/src/main/scala/whisk/core/entitlement/LocalEntitlement.scala b/core/controller/src/main/scala/whisk/core/entitlement/LocalEntitlement.scala
index 0f9f854..740d60a 100644
--- a/core/controller/src/main/scala/whisk/core/entitlement/LocalEntitlement.scala
+++ b/core/controller/src/main/scala/whisk/core/entitlement/LocalEntitlement.scala
@@ -20,8 +20,9 @@ package whisk.core.entitlement
import scala.collection.concurrent.TrieMap
import scala.concurrent.Future
-import Privilege.Privilege
import akka.actor.ActorSystem
+
+import whisk.core.entitlement.Privilege._
import whisk.common.Logging
import whisk.common.TransactionId
import whisk.core.WhiskConfig
diff --git a/core/controller/src/main/scala/whisk/core/entitlement/PackageCollection.scala b/core/controller/src/main/scala/whisk/core/entitlement/PackageCollection.scala
index 170aaaa..ce4f6ea 100644
--- a/core/controller/src/main/scala/whisk/core/entitlement/PackageCollection.scala
+++ b/core/controller/src/main/scala/whisk/core/entitlement/PackageCollection.scala
@@ -20,8 +20,9 @@ package whisk.core.entitlement
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
-import Privilege.Privilege
-import spray.http.StatusCodes._
+import akka.http.scaladsl.model.StatusCodes._
+
+import whisk.core.entitlement.Privilege._
import whisk.common.Logging
import whisk.common.TransactionId
import whisk.core.controller.RejectRequest
diff --git a/core/invoker/src/main/scala/whisk/core/invoker/Invoker.scala b/core/invoker/src/main/scala/whisk/core/invoker/Invoker.scala
index e5dc5dc..57e7110 100644
--- a/core/invoker/src/main/scala/whisk/core/invoker/Invoker.scala
+++ b/core/invoker/src/main/scala/whisk/core/invoker/Invoker.scala
@@ -454,7 +454,7 @@ object Invoker {
implicit val logger = new AkkaLogging(akka.event.Logging.getLogger(actorSystem, this))
// load values for the required properties from the environment
- val config = new WhiskConfig(requiredProperties)
+ implicit val config = new WhiskConfig(requiredProperties)
def abort() = {
logger.error(this, "Bad configuration, cannot start.")
@@ -497,8 +497,9 @@ object Invoker {
})
val port = config.servicePort.toInt
- BasicHttpService.startService(actorSystem, "invoker", "0.0.0.0", port, new Creator[InvokerServer] {
- def create = new InvokerServer(invokerInstance, invokerInstance.toInt)
+
+ BasicHttpService.startService(actorSystem, "invoker", "0.0.0.0", new Creator[InvokerServer] {
+ def create = new InvokerServer(invokerInstance, invokerInstance.toInt, port)
})
}
}
diff --git a/core/invoker/src/main/scala/whisk/core/invoker/InvokerServer.scala b/core/invoker/src/main/scala/whisk/core/invoker/InvokerServer.scala
index cd083cb..56e28ad 100644
--- a/core/invoker/src/main/scala/whisk/core/invoker/InvokerServer.scala
+++ b/core/invoker/src/main/scala/whisk/core/invoker/InvokerServer.scala
@@ -17,10 +17,10 @@
package whisk.core.invoker
-import akka.actor.Actor
+import whisk.http.BasicRasService
+import whisk.core.WhiskConfig
import whisk.common.Logging
import whisk.core.entity.InstanceId
-import whisk.http.BasicRasService
/**
* Implements web server to handle certain REST API calls.
@@ -28,10 +28,9 @@ import whisk.http.BasicRasService
*/
class InvokerServer(
override val instance: InstanceId,
- override val numberOfInstances: Int)(
- override implicit val logging: Logging)
- extends BasicRasService
- with Actor {
-
- override def actorRefFactory = context
+ override val numberOfInstances: Int,
+ override val port: Int)(
+ override implicit val logging: Logging,
+ implicit val whiskConfig: WhiskConfig)
+ extends BasicRasService {
}
diff --git a/tests/build.gradle b/tests/build.gradle
index b33e2c6..979a2f8 100644
--- a/tests/build.gradle
+++ b/tests/build.gradle
@@ -48,11 +48,10 @@ dependencies {
compile 'junit:junit:4.11'
compile 'com.jayway.restassured:rest-assured:2.6.0'
compile 'org.scalatest:scalatest_2.11:3.0.1'
- compile 'io.spray:spray-testkit_2.11:1.3.3'
- compile 'com.typesafe.akka:akka-testkit_2.11:2.4.16'
compile 'com.google.code.gson:gson:2.3.1'
compile 'org.scalamock:scalamock-scalatest-support_2.11:3.4.2'
-
+ compile 'com.typesafe.akka:akka-testkit_2.11:2.4.16'
+ compile 'com.typesafe.akka:akka-http-testkit_2.11:10.0.9'
compile project(':common:scala')
compile project(':core:controller')
compile project(':core:invoker')
diff --git a/tests/src/test/scala/services/HeadersTests.scala b/tests/src/test/scala/services/HeadersTests.scala
index 82a85d6..4316956 100644
--- a/tests/src/test/scala/services/HeadersTests.scala
+++ b/tests/src/test/scala/services/HeadersTests.scala
@@ -20,6 +20,7 @@ package services
import scala.concurrent.Future
import scala.concurrent.duration.DurationInt
import scala.language.postfixOps
+import scala.collection.immutable.Seq
import org.junit.runner.RunWith
import org.scalatest.FlatSpec
@@ -33,29 +34,24 @@ import common.WhiskProperties
import common.Wsk
import common.WskProps
import common.WskTestHelpers
-import spray.client.pipelining.Get
-import spray.client.pipelining.Options
-import spray.client.pipelining.Post
-import spray.client.pipelining.WithTransformation
-import spray.client.pipelining.WithTransformerConcatenation
-import spray.client.pipelining.addCredentials
-import spray.client.pipelining.sendReceive
-import spray.client.pipelining.unmarshal
-import spray.http.AllOrigins
-import spray.http.BasicHttpCredentials
-import spray.http.HttpHeader
-import spray.http.HttpHeaders.`Access-Control-Allow-Headers`
-import spray.http.HttpHeaders.`Access-Control-Allow-Origin`
-import spray.http.HttpMethods.DELETE
-import spray.http.HttpMethods.GET
-import spray.http.HttpMethods.POST
-import spray.http.HttpMethods.PUT
-import spray.http.HttpRequest
-import spray.http.HttpResponse
-import spray.http.StatusCodes.Accepted
-import spray.http.StatusCodes.OK
-import spray.http.Uri
-import spray.http.Uri.Path
+
+import akka.http.scaladsl.model.Uri
+import akka.http.scaladsl.model.Uri.Path
+import akka.http.scaladsl.model.headers.BasicHttpCredentials
+import akka.http.scaladsl.model.HttpRequest
+import akka.http.scaladsl.model.StatusCodes.Accepted
+import akka.http.scaladsl.model.StatusCodes.OK
+import akka.http.scaladsl.model.HttpMethods.DELETE
+import akka.http.scaladsl.model.HttpMethods.GET
+import akka.http.scaladsl.model.HttpMethods.POST
+import akka.http.scaladsl.model.HttpMethods.PUT
+import akka.http.scaladsl.model.HttpMethods._
+import akka.http.scaladsl.Http
+import akka.http.scaladsl.model.HttpResponse
+import akka.http.scaladsl.model.headers._
+import akka.http.scaladsl.model.HttpMethod
+import akka.http.scaladsl.model.HttpHeader
+import akka.stream.ActorMaterializer
import common.WskActorSystem
@@ -68,17 +64,23 @@ class HeadersTests extends FlatSpec
behavior of "Headers at general API"
+ implicit val materializer = ActorMaterializer()
+
val whiskAuth = WhiskProperties.getBasicAuth
val creds = BasicHttpCredentials(whiskAuth.fst, whiskAuth.snd)
-
val allMethods = Some(Set(DELETE.name, GET.name, POST.name, PUT.name))
- val allowOrigin = `Access-Control-Allow-Origin`(AllOrigins)
+ val allowOrigin = `Access-Control-Allow-Origin`.*
val allowHeaders = `Access-Control-Allow-Headers`("Authorization", "Content-Type")
-
val url = Uri(s"http://${WhiskProperties.getBaseControllerAddress()}")
- val pipeline: HttpRequest => Future[HttpResponse] = (
- sendReceive
- ~> unmarshal[HttpResponse])
+
+ def request(method: HttpMethod, uri: Uri, headers: Option[Seq[HttpHeader]] = None): Future[HttpResponse] = {
+ val httpRequest = headers match {
+ case Some(headers) => HttpRequest(method, uri, headers)
+ case None => HttpRequest(method, uri)
+ }
+
+ Http().singleRequest(httpRequest)
+ }
implicit val config = PatienceConfig(10 seconds, 0 milliseconds)
@@ -90,7 +92,7 @@ class HeadersTests extends FlatSpec
* Checks, if the required headers are in the list of all headers.
* For the allowed method, it checks, if only the allowed methods are in the response headers.
*/
- def containsHeaders(headers: List[HttpHeader], allowedMethods: Option[Set[String]] = None) = {
+ def containsHeaders(headers: Seq[HttpHeader], allowedMethods: Option[Set[String]] = None) = {
headers should contain allOf (allowOrigin, allowHeaders)
// TODO: commented out for now as allowed methods are not supported currently
@@ -104,19 +106,19 @@ class HeadersTests extends FlatSpec
}
it should "respond to OPTIONS with all headers" in {
- pipeline(Options(url.withPath(basePath))).futureValue.headers should contain allOf (allowOrigin, allowHeaders)
+ request(OPTIONS, url.withPath(basePath)).futureValue.headers should contain allOf (allowOrigin, allowHeaders)
}
ignore should "not respond to OPTIONS for non existing path" in {
val path = basePath / "foo" / "bar"
- pipeline(Options(url.withPath(path))).futureValue.status should not be OK
+ request(OPTIONS, url.withPath(path)).futureValue.status should not be OK
}
// Actions
it should "respond to OPTIONS for listing actions" in {
val path = basePath / "namespaces" / "barfoo" / "actions"
- val response = pipeline(Options(url.withPath(path))) futureValue
+ val response = request(OPTIONS, url.withPath(path)).futureValue
response.status shouldBe OK
containsHeaders(response.headers, Some(Set("GET")))
@@ -124,7 +126,7 @@ class HeadersTests extends FlatSpec
it should "respond to OPTIONS for actions path" in {
val path = basePath / "namespaces" / "barfoo" / "actions" / "foobar"
- val response = pipeline(Options(url.withPath(path))) futureValue
+ val response = request(OPTIONS, url.withPath(path)).futureValue
response.status shouldBe OK
containsHeaders(response.headers, allMethods)
@@ -143,7 +145,7 @@ class HeadersTests extends FlatSpec
(action, _) => action.create(fullActionName, Some(TestUtils.getTestActionFilename("hello.js")))
}
val path = basePath / "namespaces" / "_" / "actions" / packageName / actionName
- val response = pipeline(Post(url.withPath(path)) ~> addCredentials(creds)) futureValue
+ val response = request(POST, url.withPath(path), Some(List(Authorization(creds)))).futureValue
response.status shouldBe Accepted
containsHeaders(response.headers)
@@ -152,7 +154,7 @@ class HeadersTests extends FlatSpec
// Activations
it should "respond to OPTIONS for listing activations" in {
val path = basePath / "namespaces" / "barfoo" / "activations"
- val response = pipeline(Options(url.withPath(path))) futureValue
+ val response = request(OPTIONS, url.withPath(path)).futureValue
response.status shouldBe OK
containsHeaders(response.headers, Some(Set("GET")))
@@ -160,7 +162,7 @@ class HeadersTests extends FlatSpec
it should "respond to OPTIONS for activations get" in {
val path = basePath / "namespaces" / "barfoo" / "activations" / "foobar"
- val response = pipeline(Options(url.withPath(path))) futureValue
+ val response = request(OPTIONS, url.withPath(path)).futureValue
response.status shouldBe OK
containsHeaders(response.headers, Some(Set("GET")))
@@ -168,7 +170,7 @@ class HeadersTests extends FlatSpec
it should "respond to OPTIONS for activations logs" in {
val path = basePath / "namespaces" / "barfoo" / "activations" / "foobar" / "logs"
- val response = pipeline(Options(url.withPath(path))) futureValue
+ val response = request(OPTIONS, url.withPath(path)).futureValue
response.status shouldBe OK
containsHeaders(response.headers, Some(Set("GET")))
@@ -176,7 +178,7 @@ class HeadersTests extends FlatSpec
it should "respond to OPTIONS for activations results" in {
val path = basePath / "namespaces" / "barfoo" / "activations" / "foobar" / "result"
- val response = pipeline(Options(url.withPath(path))) futureValue
+ val response = request(OPTIONS, url.withPath(path)).futureValue
response.status shouldBe OK
containsHeaders(response.headers, Some(Set("GET")))
@@ -184,7 +186,7 @@ class HeadersTests extends FlatSpec
it should "respond to GET for listing activations with Headers" in {
val path = basePath / "namespaces" / "_" / "activations"
- val response = pipeline(Get(url.withPath(path)) ~> addCredentials(creds)) futureValue
+ val response = request(GET, url.withPath(path), Some(List(Authorization(creds)))).futureValue
response.status shouldBe OK
containsHeaders(response.headers)
@@ -193,7 +195,7 @@ class HeadersTests extends FlatSpec
// Namespaces
it should "respond to OPTIONS for listing namespaces" in {
val path = basePath / "namespaces"
- val response = pipeline(Options(url.withPath(path))) futureValue
+ val response = request(OPTIONS, url.withPath(path)).futureValue
response.status shouldBe OK
containsHeaders(response.headers, Some(Set("GET")))
@@ -201,7 +203,7 @@ class HeadersTests extends FlatSpec
it should "respond to OPTIONS for namespaces getEntities" in {
val path = basePath / "namespaces" / "barfoo"
- val response = pipeline(Options(url.withPath(path))) futureValue
+ val response = request(OPTIONS, url.withPath(path)).futureValue
response.status shouldBe OK
containsHeaders(response.headers, Some(Set("GET")))
@@ -209,7 +211,7 @@ class HeadersTests extends FlatSpec
it should "respond to GET for namespaces getEntities with Headers" in {
val path = basePath / "namespaces" / "_"
- val response = pipeline(Get(url.withPath(path)) ~> addCredentials(creds)) futureValue
+ val response = request(GET, url.withPath(path), Some(List(Authorization(creds)))).futureValue
response.status shouldBe OK
containsHeaders(response.headers)
@@ -218,7 +220,7 @@ class HeadersTests extends FlatSpec
// Packages
it should "respond to OPTIONS for listing packages" in {
val path = basePath / "namespaces" / "barfoo" / "packages"
- val response = pipeline(Options(url.withPath(path))) futureValue
+ val response = request(OPTIONS, url.withPath(path)).futureValue
response.status shouldBe OK
containsHeaders(response.headers, Some(Set("GET")))
@@ -226,7 +228,7 @@ class HeadersTests extends FlatSpec
it should "respond to OPTIONS for packages path" in {
val path = basePath / "namespaces" / "barfoo" / "packages" / "foobar"
- val response = pipeline(Options(url.withPath(path))) futureValue
+ val response = request(OPTIONS, url.withPath(path)).futureValue
response.status shouldBe OK
containsHeaders(response.headers, Some(Set("DELETE", "GET", "PUT")))
@@ -234,7 +236,7 @@ class HeadersTests extends FlatSpec
it should "respond to GET for listing packages with headers" in {
val path = basePath / "namespaces" / "_" / "packages"
- val response = pipeline(Get(url.withPath(path)) ~> addCredentials(creds)) futureValue
+ val response = request(GET, url.withPath(path), Some(List(Authorization(creds)))).futureValue
response.status shouldBe OK
containsHeaders(response.headers)
@@ -243,7 +245,7 @@ class HeadersTests extends FlatSpec
// Rules
it should "respond to OPTIONS for listing rules" in {
val path = basePath / "namespaces" / "barfoo" / "rules"
- val response = pipeline(Options(url.withPath(path))) futureValue
+ val response = request(OPTIONS, url.withPath(path)).futureValue
response.status shouldBe OK
containsHeaders(response.headers, Some(Set("GET")))
@@ -251,7 +253,7 @@ class HeadersTests extends FlatSpec
it should "respond to OPTIONS for rules path" in {
val path = basePath / "namespaces" / "barfoo" / "rules" / "foobar"
- val response = pipeline(Options(url.withPath(path))) futureValue
+ val response = request(OPTIONS, url.withPath(path)).futureValue
response.status shouldBe OK
containsHeaders(response.headers, allMethods)
@@ -259,7 +261,7 @@ class HeadersTests extends FlatSpec
it should "respond to GET for listing rules with headers" in {
val path = basePath / "namespaces" / "_" / "rules"
- val response = pipeline(Get(url.withPath(path)) ~> addCredentials(creds)) futureValue
+ val response = request(GET, url.withPath(path), Some(List(Authorization(creds)))).futureValue
response.status shouldBe OK
containsHeaders(response.headers)
@@ -268,7 +270,7 @@ class HeadersTests extends FlatSpec
// Triggers
it should "respond to OPTIONS for listing triggers" in {
val path = basePath / "namespaces" / "barfoo" / "triggers"
- val response = pipeline(Options(url.withPath(path))) futureValue
+ val response = request(OPTIONS, url.withPath(path)).futureValue
response.status shouldBe OK
containsHeaders(response.headers, Some(Set("GET")))
@@ -276,7 +278,7 @@ class HeadersTests extends FlatSpec
it should "respond to OPTIONS for triggers path" in {
val path = basePath / "namespaces" / "barfoo" / "triggers" / "foobar"
- val response = pipeline(Options(url.withPath(path))) futureValue
+ val response = request(OPTIONS, url.withPath(path)).futureValue
response.status shouldBe OK
containsHeaders(response.headers, allMethods)
@@ -284,7 +286,7 @@ class HeadersTests extends FlatSpec
it should "respond to GET for listing triggers with headers" in {
val path = basePath / "namespaces" / "_" / "triggers"
- val response = pipeline(Get(url.withPath(path)) ~> addCredentials(creds)) futureValue
+ val response = request(GET, url.withPath(path), Some(List(Authorization(creds)))).futureValue
response.status shouldBe OK
containsHeaders(response.headers)
diff --git a/tests/src/test/scala/system/basic/WskSequenceTests.scala b/tests/src/test/scala/system/basic/WskSequenceTests.scala
index 726c897..906bfbb 100644
--- a/tests/src/test/scala/system/basic/WskSequenceTests.scala
+++ b/tests/src/test/scala/system/basic/WskSequenceTests.scala
@@ -34,9 +34,12 @@ import common.TestUtils._
import common.Wsk
import common.WskProps
import common.WskTestHelpers
+
+import akka.http.scaladsl.testkit.ScalatestRouteTest
+
import spray.json._
import spray.json.DefaultJsonProtocol._
-import spray.testkit.ScalatestRouteTest
+
import whisk.core.WhiskConfig
import whisk.http.Messages.sequenceIsTooLong
diff --git a/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala b/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala
index 517371c..d6712d5 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala
@@ -295,7 +295,7 @@ trait WskWebActionsTests
val url = host + s"$testRoutePath/$namespace/default/webaction.http"
val response = RestAssured.given().header("accept", "application/json").config(sslconfig).get(url)
response.statusCode shouldBe 406
- response.body.asString should include("Resource representation is only available with these Content-Types:\\ntext/html")
+ response.body.asString should include("Resource representation is only available with these types:\\ntext/html")
}
it should "support multiple response header values" in withAssetCleaner(wskprops) {
diff --git a/tests/src/test/scala/whisk/core/controller/test/ActionsApiTests.scala b/tests/src/test/scala/whisk/core/controller/test/ActionsApiTests.scala
index bdd9a31..150a04e 100644
--- a/tests/src/test/scala/whisk/core/controller/test/ActionsApiTests.scala
+++ b/tests/src/test/scala/whisk/core/controller/test/ActionsApiTests.scala
@@ -25,11 +25,14 @@ import scala.language.postfixOps
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
-import spray.http.StatusCodes._
-import spray.httpx.SprayJsonSupport.sprayJsonMarshaller
-import spray.httpx.SprayJsonSupport.sprayJsonUnmarshaller
+import akka.http.scaladsl.model.StatusCodes._
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport.sprayJsonMarshaller
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport.sprayJsonUnmarshaller
+import akka.http.scaladsl.server.Route
+
import spray.json._
import spray.json.DefaultJsonProtocol._
+
import whisk.core.controller.WhiskActionsApi
import whisk.core.entity._
import whisk.core.entity.size._
@@ -69,7 +72,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
}.toList
actions foreach { put(entityStore, _) }
waitOnView(entityStore, WhiskAction, namespace, 2)
- Get(s"$collectionPath") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[JsObject]]
actions.length should be(response.length)
@@ -85,7 +88,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
}.toList
actions foreach { put(entityStore, _) }
waitOnView(entityStore, WhiskAction, namespace, 2)
- Get(s"$collectionPath?docs=true") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath?docs=true") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[WhiskAction]]
actions.length should be(response.length)
@@ -100,7 +103,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
}.toList
actions foreach { put(entityStore, _) }
waitOnView(entityStore, WhiskAction, namespace, 2)
- Get(s"/$namespace/${collection.path}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"/$namespace/${collection.path}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[JsObject]]
actions.length should be(response.length)
@@ -109,14 +112,14 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
// it should "reject list action with explicit namespace not owned by subject" in {
val auser = WhiskAuthHelpers.newIdentity()
- Get(s"/$namespace/${collection.path}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"/$namespace/${collection.path}") ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
}
it should "list should reject request with post" in {
implicit val tid = transid()
- Post(s"$collectionPath") ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath") ~> Route.seal(routes(creds)) ~> check {
status should be(MethodNotAllowed)
}
}
@@ -126,7 +129,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
implicit val tid = transid()
val action = WhiskAction(namespace, aname, jsDefault("??"), Parameters("x", "b"))
put(entityStore, action)
- Get(s"$collectionPath/${action.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${action.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskAction]
response should be(action)
@@ -137,7 +140,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
implicit val tid = transid()
val action = WhiskAction(namespace, aname, jsDefault("??"), Parameters("x", "b"))
put(entityStore, action)
- Get(s"/$namespace/${collection.path}/${action.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"/$namespace/${collection.path}/${action.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskAction]
response should be(action)
@@ -145,14 +148,14 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
// it should "reject get action by name in explicit namespace not owned by subject" in
val auser = WhiskAuthHelpers.newIdentity()
- Get(s"/$namespace/${collection.path}/${action.name}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"/$namespace/${collection.path}/${action.name}") ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
}
it should "report NotFound for get non existent action" in {
implicit val tid = transid()
- Get(s"$collectionPath/xyz") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/xyz") ~> Route.seal(routes(creds)) ~> check {
status should be(NotFound)
}
}
@@ -161,7 +164,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
implicit val tid = transid()
val trigger = WhiskTrigger(namespace, aname)
put(entityStore, trigger)
- Get(s"/$namespace/${collection.path}/${trigger.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"/$namespace/${collection.path}/${trigger.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(Conflict)
}
}
@@ -169,7 +172,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
it should "reject long entity names" in {
implicit val tid = transid()
val longName = "a" * (EntityName.ENTITY_NAME_MAX_LENGTH + 1)
- Get(s"/$longName/${collection.path}/$longName") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"/$longName/${collection.path}/$longName") ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[String] shouldBe {
Messages.entityNameTooLong(
@@ -182,7 +185,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
s"/$namespace/${collection.path}/$longName/a",
s"/$namespace/${collection.path}/$longName/$longName").
foreach { p =>
- Get(p) ~> sealRoute(routes(creds)) ~> check {
+ Get(p) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[String] shouldBe {
Messages.entityNameTooLong(
@@ -200,11 +203,11 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
// it should "reject delete action by name not owned by subject" in
val auser = WhiskAuthHelpers.newIdentity()
- Get(s"/$namespace/${collection.path}/${action.name}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"/$namespace/${collection.path}/${action.name}") ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
- Delete(s"$collectionPath/${action.name}") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${action.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskAction]
response should be(action)
@@ -213,7 +216,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
it should "report NotFound for delete non existent action" in {
implicit val tid = transid()
- Delete(s"$collectionPath/xyz") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/xyz") ~> Route.seal(routes(creds)) ~> check {
status should be(NotFound)
}
}
@@ -221,16 +224,16 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
//// PUT /actions/name
it should "put should reject request missing json content" in {
implicit val tid = transid()
- Put(s"$collectionPath/xxx", "") ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/xxx", "") ~> Route.seal(routes(creds)) ~> check {
val response = responseAs[String]
- status should be(BadRequest)
+ status should be(UnsupportedMediaType)
}
}
it should "put should reject request missing property exec" in {
implicit val tid = transid()
val content = """|{"name":"name","publish":true}""".stripMargin.parseJson.asJsObject
- Put(s"$collectionPath/xxx", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/xxx", content) ~> Route.seal(routes(creds)) ~> check {
val response = responseAs[String]
status should be(BadRequest)
}
@@ -241,7 +244,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val content = """|{"name":"name",
|"publish":true,
|"exec":""}""".stripMargin.parseJson.asJsObject
- Put(s"$collectionPath/xxx", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/xxx", content) ~> Route.seal(routes(creds)) ~> check {
val response = responseAs[String]
status should be(BadRequest)
}
@@ -252,7 +255,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val code = "a" * (actionLimit.toBytes.toInt + 1)
val exec: Exec = jsDefault(code)
val content = JsObject("exec" -> exec.toJson)
- Put(s"$collectionPath/${aname}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${aname}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(RequestEntityTooLarge)
responseAs[String] should include {
Messages.entityTooBig(SizeError(WhiskAction.execFieldName, exec.size, Exec.sizeLimit))
@@ -268,7 +271,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val exec: Exec = jsDefault(code)
val content = JsObject("exec" -> exec.toJson)
put(entityStore, action)
- Put(s"$collectionPath/${action.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${action.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
status should be(RequestEntityTooLarge)
responseAs[String] should include {
Messages.entityTooBig(SizeError(WhiskAction.execFieldName, exec.size, Exec.sizeLimit))
@@ -283,7 +286,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
Parameters(key.toString, "a" * 10)
} reduce (_ ++ _)
val content = s"""{"exec":{"kind":"nodejs","code":"??"},"parameters":$parameters}""".stripMargin
- Put(s"$collectionPath/${aname}", content.parseJson.asJsObject) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${aname}", content.parseJson.asJsObject) ~> Route.seal(routes(creds)) ~> check {
status should be(RequestEntityTooLarge)
responseAs[String] should include {
Messages.entityTooBig(SizeError(WhiskEntity.paramsFieldName, parameters.size, Parameters.sizeLimit))
@@ -298,7 +301,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
Parameters(key.toString, "a" * 10)
} reduce (_ ++ _)
val content = s"""{"exec":{"kind":"nodejs","code":"??"},"annotations":$annotations}""".stripMargin
- Put(s"$collectionPath/${aname}", content.parseJson.asJsObject) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${aname}", content.parseJson.asJsObject) ~> Route.seal(routes(creds)) ~> check {
status should be(RequestEntityTooLarge)
responseAs[String] should include {
Messages.entityTooBig(SizeError(WhiskEntity.annotationsFieldName, annotations.size, Parameters.sizeLimit))
@@ -310,10 +313,10 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
implicit val tid = transid()
val code = "a" * (allowedActivationEntitySize.toInt + 1)
val content = s"""{"a":"$code"}""".stripMargin
- Post(s"$collectionPath/${aname}", content.parseJson.asJsObject) ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${aname}", content.parseJson.asJsObject) ~> Route.seal(routes(creds)) ~> check {
status should be(RequestEntityTooLarge)
responseAs[String] should include {
- Messages.entityTooBig(SizeError(fieldDescriptionForSizeError, (content.length + 5).B, allowedActivationEntitySize.B))
+ Messages.entityTooBig(SizeError(fieldDescriptionForSizeError, (content.length).B, allowedActivationEntitySize.B))
}
}
}
@@ -322,7 +325,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
implicit val tid = transid()
val action = WhiskAction(namespace, aname, jsDefault("??"))
val content = WhiskActionPut(Some(action.exec))
- Put(s"$collectionPath/${action.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${action.name}", content) ~> Route.seal(routes(creds)) ~> check {
deleteAction(action.docid)
status should be(OK)
val response = responseAs[WhiskAction]
@@ -336,7 +339,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
implicit val tid = transid()
val action = WhiskAction(namespace, aname, bb("bb"))
val content = Map("exec" -> Map("kind" -> "blackbox", "code" -> "", "image" -> "bb")).toJson.asJsObject
- Put(s"$collectionPath/${action.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${action.name}", content) ~> Route.seal(routes(creds)) ~> check {
deleteAction(action.docid)
status should be(OK)
val response = responseAs[WhiskAction]
@@ -352,7 +355,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
implicit val tid = transid()
val action = WhiskAction(namespace, aname, bb("bb", "cc"))
val content = Map("exec" -> Map("kind" -> "blackbox", "code" -> "cc", "image" -> "bb")).toJson.asJsObject
- Put(s"$collectionPath/${action.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${action.name}", content) ~> Route.seal(routes(creds)) ~> check {
deleteAction(action.docid)
status should be(OK)
val response = responseAs[WhiskAction]
@@ -379,7 +382,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
put(entityStore, action, false)
// create an action sequence
- Put(s"$collectionPath/${action.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${action.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
deleteAction(action.docid)
status should be(OK)
val response = responseAs[WhiskAction]
@@ -398,7 +401,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
put(entityStore, action, false)
// create an action sequence
- Put(s"$collectionPath/${action.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${action.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
deleteAction(action.docid)
status should be(OK)
val response = responseAs[WhiskAction]
@@ -414,11 +417,11 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
// it should "reject put action in namespace not owned by subject" in
val auser = WhiskAuthHelpers.newIdentity()
- Put(s"/$namespace/${collection.path}/${action.name}", content) ~> sealRoute(routes(auser)) ~> check {
+ Put(s"/$namespace/${collection.path}/${action.name}", content) ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
- Put(s"$collectionPath/${action.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${action.name}", content) ~> Route.seal(routes(creds)) ~> check {
deleteAction(action.docid)
status should be(OK)
val response = responseAs[WhiskAction]
@@ -434,7 +437,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val content = WhiskActionPut(Some(action.exec), Some(action.parameters))
val params = """{ "parameters": { "a": "b" } }""".parseJson.asJsObject
val json = JsObject(WhiskActionPut.serdes.write(content).asJsObject.fields ++ params.fields)
- Put(s"$collectionPath/${action.name}", json) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${action.name}", json) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
}
}
@@ -443,7 +446,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
implicit val tid = transid()
val action = WhiskAction(namespace, aname, jsDefault("??"), Parameters("x", "b"))
val content = WhiskActionPut(Some(action.exec), Some(action.parameters), Some(ActionLimitsOption(Some(action.limits.timeout), Some(action.limits.memory), Some(action.limits.logs))))
- Put(s"$collectionPath/${action.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${action.name}", content) ~> Route.seal(routes(creds)) ~> check {
deleteAction(action.docid)
status should be(OK)
val response = responseAs[WhiskAction]
@@ -459,7 +462,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val name = action.name
// first request invalidates any previous entries and caches new result
- Put(s"$collectionPath/$name", content) ~> sealRoute(routes(creds)(transid())) ~> check {
+ Put(s"$collectionPath/$name", content) ~> Route.seal(routes(creds)(transid())) ~> check {
status should be(OK)
val response = responseAs[WhiskAction]
response should be(WhiskAction(action.namespace, action.name, action.exec,
@@ -470,7 +473,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
stream.reset()
// second request should fetch from cache
- Get(s"$collectionPath/$name") ~> sealRoute(routes(creds)(transid())) ~> check {
+ Get(s"$collectionPath/$name") ~> Route.seal(routes(creds)(transid())) ~> check {
status should be(OK)
val response = responseAs[WhiskAction]
response should be(WhiskAction(action.namespace, action.name, action.exec,
@@ -482,7 +485,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
stream.reset()
// delete should invalidate cache
- Delete(s"$collectionPath/$name") ~> sealRoute(routes(creds)(transid())) ~> check {
+ Delete(s"$collectionPath/$name") ~> Route.seal(routes(creds)(transid())) ~> check {
status should be(OK)
val response = responseAs[WhiskAction]
response should be(WhiskAction(action.namespace, action.name, action.exec,
@@ -498,7 +501,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val action = WhiskAction(namespace, aname, jsDefault("??"), Parameters("x", "b"))
val content = WhiskActionPut(Some(action.exec))
put(entityStore, action)
- Put(s"$collectionPath/${action.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${action.name}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(Conflict)
}
}
@@ -508,7 +511,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val action = WhiskAction(namespace, aname, jsDefault("??"), Parameters("x", "b"))
val content = WhiskActionPut(Some(jsDefault("_")), Some(Parameters("x", "X")))
put(entityStore, action)
- Put(s"$collectionPath/${action.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${action.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
deleteAction(action.docid)
status should be(OK)
val response = responseAs[WhiskAction]
@@ -524,7 +527,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val action = WhiskAction(namespace, aname, jsDefault("??"), Parameters("x", "b"))
val content = WhiskActionPut(parameters = Some(Parameters("x", "X")))
put(entityStore, action)
- Put(s"$collectionPath/${action.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${action.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
deleteAction(action.docid)
status should be(OK)
val response = responseAs[WhiskAction]
@@ -544,18 +547,18 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
// it should "reject post to action in namespace not owned by subject"
val auser = WhiskAuthHelpers.newIdentity()
- Post(s"/$namespace/${collection.path}/${action.name}", args) ~> sealRoute(routes(auser)) ~> check {
+ Post(s"/$namespace/${collection.path}/${action.name}", args) ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
- Post(s"$collectionPath/${action.name}", args) ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${action.name}", args) ~> Route.seal(routes(creds)) ~> check {
status should be(Accepted)
val response = responseAs[JsObject]
response.fields("activationId") should not be None
}
// it should "ignore &result when invoking nonblocking action"
- Post(s"$collectionPath/${action.name}?result=true", args) ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${action.name}?result=true", args) ~> Route.seal(routes(creds)) ~> check {
status should be(Accepted)
val response = responseAs[JsObject]
response.fields("activationId") should not be None
@@ -566,7 +569,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
implicit val tid = transid()
val action = WhiskAction(namespace, aname, jsDefault("??"))
put(entityStore, action)
- Post(s"$collectionPath/${action.name}") ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${action.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(Accepted)
val response = responseAs[JsObject]
response.fields("activationId") should not be None
@@ -577,7 +580,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
implicit val tid = transid()
val action = WhiskAction(namespace, aname, jsDefault("??"), limits = ActionLimits(TimeLimit(1 second), MemoryLimit(), LogLimit()))
put(entityStore, action)
- Post(s"$collectionPath/${action.name}?blocking=true") ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${action.name}?blocking=true") ~> Route.seal(routes(creds)) ~> check {
// status should be accepted because there is no active ack response and
// db polling will fail since there is no record of the activation
status should be(Accepted)
@@ -599,14 +602,14 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
// the one generated by the api handler
put(activationStore, activation)
try {
- Post(s"$collectionPath/${action.name}?blocking=true") ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${action.name}?blocking=true") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[JsObject]
response should be(activation.withoutLogs.toExtendedJson)
}
// repeat invoke, get only result back
- Post(s"$collectionPath/${action.name}?blocking=true&result=true") ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${action.name}?blocking=true&result=true") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[JsObject]
response should be(activation.resultAsJson)
@@ -629,14 +632,14 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
// do not store the activation in the db, instead register it as the response to generate on active ack
loadBalancer.whiskActivationStub = Some((1.milliseconds, activation))
- Post(s"$collectionPath/${action.name}?blocking=true") ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${action.name}?blocking=true") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[JsObject]
response should be(activation.withoutLogs.toExtendedJson)
}
// repeat invoke, get only result back
- Post(s"$collectionPath/${action.name}?blocking=true&result=true") ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${action.name}?blocking=true&result=true") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[JsObject]
response should be(activation.resultAsJson)
@@ -659,23 +662,23 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
// do not store the activation in the db, instead register it as the response to generate on active ack
loadBalancer.whiskActivationStub = Some((300.milliseconds, activation))
- Post(s"$collectionPath/${action.name}?blocking=true&timeout=0") ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${action.name}?blocking=true&timeout=0") ~> Route.seal(routes(creds)) ~> check {
status shouldBe BadRequest
responseAs[String] should include(Messages.invalidTimeout(WhiskActionsApi.maxWaitForBlockingActivation))
}
- Post(s"$collectionPath/${action.name}?blocking=true&timeout=65000") ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${action.name}?blocking=true&timeout=65000") ~> Route.seal(routes(creds)) ~> check {
status shouldBe BadRequest
responseAs[String] should include(Messages.invalidTimeout(WhiskActionsApi.maxWaitForBlockingActivation))
}
// will not wait long enough should get accepted status
- Post(s"$collectionPath/${action.name}?blocking=true&timeout=100") ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${action.name}?blocking=true&timeout=100") ~> Route.seal(routes(creds)) ~> check {
status shouldBe Accepted
}
// repeat this time wait longer than active ack delay
- Post(s"$collectionPath/${action.name}?blocking=true&timeout=500") ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${action.name}?blocking=true&timeout=500") ~> Route.seal(routes(creds)) ~> check {
status shouldBe OK
val response = responseAs[JsObject]
response shouldBe activation.withoutLogs.toExtendedJson
@@ -698,7 +701,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
// the one generated by the api handler
put(activationStore, activation)
try {
- Post(s"$collectionPath/${action.name}?blocking=true") ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${action.name}?blocking=true") ~> Route.seal(routes(creds)) ~> check {
status should be(InternalServerError)
val response = responseAs[JsObject]
response should be(activation.withoutLogs.toExtendedJson)
@@ -713,7 +716,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val entity = BadEntity(namespace, aname)
put(entityStore, entity)
- Delete(s"$collectionPath/${entity.name}") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${entity.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(InternalServerError)
responseAs[ErrorResponse].error shouldBe Messages.corruptedEntity
}
@@ -724,7 +727,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val entity = BadEntity(namespace, aname)
put(entityStore, entity)
- Get(s"$collectionPath/${entity.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${entity.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(InternalServerError)
responseAs[ErrorResponse].error shouldBe Messages.corruptedEntity
}
@@ -738,7 +741,7 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val components = Vector(stringToFullyQualifiedName(s"$namespace/${entity.name}"))
val content = WhiskActionPut(Some(sequence(components)))
- Put(s"$collectionPath/$aname", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/$aname", content) ~> Route.seal(routes(creds)) ~> check {
status should be(InternalServerError)
responseAs[ErrorResponse].error shouldBe Messages.corruptedEntity
}
@@ -751,44 +754,44 @@ class ActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val okUpdate = WhiskActionPut(Some(swift3("_")))
val badUpdate = WhiskActionPut(Some(swift("_")))
- Put(s"$collectionPath/${action.name}", WhiskActionPut(Some(action.exec))) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${action.name}", WhiskActionPut(Some(action.exec))) ~> Route.seal(routes(creds)) ~> check {
status shouldBe BadRequest
responseAs[ErrorResponse].error shouldBe Messages.runtimeDeprecated(action.exec)
}
- Put(s"$collectionPath/${action.name}?overwrite=true", WhiskActionPut(Some(action.exec))) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${action.name}?overwrite=true", WhiskActionPut(Some(action.exec))) ~> Route.seal(routes(creds)) ~> check {
status shouldBe BadRequest
responseAs[ErrorResponse].error shouldBe Messages.runtimeDeprecated(action.exec)
}
put(entityStore, action)
- Put(s"$collectionPath/${action.name}?overwrite=true", JsObject()) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${action.name}?overwrite=true", JsObject()) ~> Route.seal(routes(creds)) ~> check {
status shouldBe BadRequest
responseAs[ErrorResponse].error shouldBe Messages.runtimeDeprecated(action.exec)
}
- Put(s"$collectionPath/${action.name}?overwrite=true", badUpdate) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${action.name}?overwrite=true", badUpdate) ~> Route.seal(routes(creds)) ~> check {
status shouldBe BadRequest
responseAs[ErrorResponse].error shouldBe Messages.runtimeDeprecated(action.exec)
}
- Post(s"$collectionPath/${action.name}") ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${action.name}") ~> Route.seal(routes(creds)) ~> check {
status shouldBe BadRequest
responseAs[ErrorResponse].error shouldBe Messages.runtimeDeprecated(action.exec)
}
- Get(s"$collectionPath/${action.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${action.name}") ~> Route.seal(routes(creds)) ~> check {
status shouldBe OK
}
- Delete(s"$collectionPath/${action.name}") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${action.name}") ~> Route.seal(routes(creds)) ~> check {
status shouldBe OK
}
put(entityStore, action)
- Put(s"$collectionPath/${action.name}?overwrite=true", okUpdate) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${action.name}?overwrite=true", okUpdate) ~> Route.seal(routes(creds)) ~> check {
deleteAction(action.docid)
status shouldBe OK
}
diff --git a/tests/src/test/scala/whisk/core/controller/test/ActivationsApiTests.scala b/tests/src/test/scala/whisk/core/controller/test/ActivationsApiTests.scala
index 66209d2..c205856 100644
--- a/tests/src/test/scala/whisk/core/controller/test/ActivationsApiTests.scala
+++ b/tests/src/test/scala/whisk/core/controller/test/ActivationsApiTests.scala
@@ -21,10 +21,14 @@ import java.time.Clock
import java.time.Instant
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
-import spray.http.StatusCodes._
-import spray.httpx.SprayJsonSupport._
+
+import akka.http.scaladsl.model.StatusCodes._
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
+import akka.http.scaladsl.server.Route
+
import spray.json._
import spray.json.DefaultJsonProtocol._
+
import whisk.core.controller.WhiskActivationsApi
import whisk.core.database.ArtifactStoreProvider
import whisk.core.entity._
@@ -72,7 +76,7 @@ class ActivationsApiTests extends ControllerTestCommon with WhiskActivationsApi
activations foreach { put(activationStore, _) }
waitOnView(activationStore, namespace, 2)
whisk.utils.retry {
- Get(s"$collectionPath") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val rawResponse = responseAs[List[JsObject]]
val response = responseAs[List[JsObject]]
@@ -84,7 +88,7 @@ class ActivationsApiTests extends ControllerTestCommon with WhiskActivationsApi
// it should "list activations with explicit namespace owned by subject" in {
whisk.utils.retry {
- Get(s"/$namespace/${collection.path}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"/$namespace/${collection.path}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val rawResponse = responseAs[List[JsObject]]
val response = responseAs[List[JsObject]]
@@ -96,7 +100,7 @@ class ActivationsApiTests extends ControllerTestCommon with WhiskActivationsApi
// it should "reject list activations with explicit namespace not owned by subject" in {
val auser = WhiskAuthHelpers.newIdentity()
- Get(s"/$namespace/${collection.path}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"/$namespace/${collection.path}") ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
}
@@ -118,7 +122,7 @@ class ActivationsApiTests extends ControllerTestCommon with WhiskActivationsApi
waitOnView(activationStore, namespace, 2)
whisk.utils.retry {
- Get(s"$collectionPath?docs=true") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath?docs=true") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[JsObject]]
activations.length should be(response.length)
@@ -151,7 +155,7 @@ class ActivationsApiTests extends ControllerTestCommon with WhiskActivationsApi
// get between two time stamps
whisk.utils.retry {
- Get(s"$collectionPath?docs=true&since=${since.toEpochMilli}&upto=${upto.toEpochMilli}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath?docs=true&since=${since.toEpochMilli}&upto=${upto.toEpochMilli}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[JsObject]]
val expected = activations filter {
@@ -164,7 +168,7 @@ class ActivationsApiTests extends ControllerTestCommon with WhiskActivationsApi
// get 'upto' with no defined since value should return all activation 'upto'
whisk.utils.retry {
- Get(s"$collectionPath?docs=true&upto=${upto.toEpochMilli}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath?docs=true&upto=${upto.toEpochMilli}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[JsObject]]
val expected = activations filter {
@@ -177,7 +181,7 @@ class ActivationsApiTests extends ControllerTestCommon with WhiskActivationsApi
// get 'since' with no defined upto value should return all activation 'since'
whisk.utils.retry {
- Get(s"$collectionPath?docs=true&since=${since.toEpochMilli}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath?docs=true&since=${since.toEpochMilli}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[JsObject]]
val expected = activations filter {
@@ -206,7 +210,7 @@ class ActivationsApiTests extends ControllerTestCommon with WhiskActivationsApi
waitOnView(activationStore, namespace, 2)
whisk.utils.retry {
- Get(s"$collectionPath?name=xyz") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath?name=xyz") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[JsObject]]
activations.length should be(response.length)
@@ -218,7 +222,7 @@ class ActivationsApiTests extends ControllerTestCommon with WhiskActivationsApi
it should "reject activation list when limit is greater than maximum allowed value" in {
implicit val tid = transid()
val exceededMaxLimit = WhiskActivationsApi.maxActivationLimit + 1
- val response = Get(s"$collectionPath?limit=$exceededMaxLimit") ~> sealRoute(routes(creds)) ~> check {
+ val response = Get(s"$collectionPath?limit=$exceededMaxLimit") ~> Route.seal(routes(creds)) ~> check {
val response = responseAs[String]
response should include(Messages.maxActivationLimitExceeded(exceededMaxLimit, WhiskActivationsApi.maxActivationLimit))
status should be(BadRequest)
@@ -227,17 +231,17 @@ class ActivationsApiTests extends ControllerTestCommon with WhiskActivationsApi
it should "reject get activation by namespace and action name when action name is not a valid name" in {
implicit val tid = transid()
- Get(s"$collectionPath?name=0%20") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath?name=0%20") ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
}
}
it should "reject get activation with invalid since/upto value" in {
implicit val tid = transid()
- Get(s"$collectionPath?since=xxx") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath?since=xxx") ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
}
- Get(s"$collectionPath?upto=yyy") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath?upto=yyy") ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
}
}
@@ -248,14 +252,14 @@ class ActivationsApiTests extends ControllerTestCommon with WhiskActivationsApi
val activation = WhiskActivation(namespace, aname, creds.subject, ActivationId(), start = Instant.now, end = Instant.now)
put(activationStore, activation)
- Get(s"$collectionPath/${activation.activationId.asString}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${activation.activationId.asString}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[JsObject]
response should be(activation.toExtendedJson)
}
// it should "get activation by name in explicit namespace owned by subject" in
- Get(s"/$namespace/${collection.path}/${activation.activationId.asString}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"/$namespace/${collection.path}/${activation.activationId.asString}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[JsObject]
response should be(activation.toExtendedJson)
@@ -263,7 +267,7 @@ class ActivationsApiTests extends ControllerTestCommon with WhiskActivationsApi
// it should "reject get activation by name in explicit namespace not owned by subject" in
val auser = WhiskAuthHelpers.newIdentity()
- Get(s"/$namespace/${collection.path}/${activation.activationId.asString}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"/$namespace/${collection.path}/${activation.activationId.asString}") ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
}
@@ -274,7 +278,7 @@ class ActivationsApiTests extends ControllerTestCommon with WhiskActivationsApi
val activation = WhiskActivation(namespace, aname, creds.subject, ActivationId(), start = Instant.now, end = Instant.now)
put(activationStore, activation)
- Get(s"$collectionPath/${activation.activationId.asString}/result") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${activation.activationId.asString}/result") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[JsObject]
response should be(activation.response.toExtendedJson)
@@ -287,7 +291,7 @@ class ActivationsApiTests extends ControllerTestCommon with WhiskActivationsApi
val activation = WhiskActivation(namespace, aname, creds.subject, ActivationId(), start = Instant.now, end = Instant.now)
put(activationStore, activation)
- Get(s"$collectionPath/${activation.activationId.asString}/logs") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${activation.activationId.asString}/logs") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[JsObject]
response should be(activation.logs.toJsonObject)
@@ -300,7 +304,7 @@ class ActivationsApiTests extends ControllerTestCommon with WhiskActivationsApi
val activation = WhiskActivation(namespace, aname, creds.subject, ActivationId(), start = Instant.now, end = Instant.now)
put(entityStore, activation)
- Get(s"$collectionPath/${activation.activationId.asString}/bogus") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${activation.activationId.asString}/bogus") ~> Route.seal(routes(creds)) ~> check {
status should be(NotFound)
}
}
@@ -312,38 +316,38 @@ class ActivationsApiTests extends ControllerTestCommon with WhiskActivationsApi
val toolong = activationId + "xxx"
val malformed = tooshort + "z"
- Get(s"$collectionPath/$tooshort") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/$tooshort") ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[String] shouldBe Messages.activationIdLengthError(SizeError("Activation id", tooshort.length.B, 32.B))
}
- Get(s"$collectionPath/$toolong") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/$toolong") ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[String] shouldBe Messages.activationIdLengthError(SizeError("Activation id", toolong.length.B, 32.B))
}
- Get(s"$collectionPath/$malformed") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/$malformed") ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
}
}
it should "reject request with put" in {
implicit val tid = transid()
- Put(s"$collectionPath/${ActivationId()}") ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${ActivationId()}") ~> Route.seal(routes(creds)) ~> check {
status should be(MethodNotAllowed)
}
}
it should "reject request with post" in {
implicit val tid = transid()
- Post(s"$collectionPath/${ActivationId()}") ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${ActivationId()}") ~> Route.seal(routes(creds)) ~> check {
status should be(MethodNotAllowed)
}
}
it should "reject request with delete" in {
implicit val tid = transid()
- Delete(s"$collectionPath/${ActivationId()}") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${ActivationId()}") ~> Route.seal(routes(creds)) ~> check {
status should be(MethodNotAllowed)
}
}
@@ -355,7 +359,7 @@ class ActivationsApiTests extends ControllerTestCommon with WhiskActivationsApi
val entity = BadEntity(namespace, EntityName(ActivationId().toString))
put(activationStore, entity)
- Get(s"$collectionPath/${entity.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${entity.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(InternalServerError)
responseAs[ErrorResponse].error shouldBe Messages.corruptedEntity
}
diff --git a/tests/src/test/scala/whisk/core/controller/test/AuthenticateTests.scala b/tests/src/test/scala/whisk/core/controller/test/AuthenticateTests.scala
index 8e3cca3..e964856 100644
--- a/tests/src/test/scala/whisk/core/controller/test/AuthenticateTests.scala
+++ b/tests/src/test/scala/whisk/core/controller/test/AuthenticateTests.scala
@@ -22,15 +22,10 @@ import scala.concurrent.Await
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
-import spray.http.BasicHttpCredentials
-import spray.http.StatusCodes._
-import spray.routing.authentication.UserPass
-import spray.routing.directives.AuthMagnet.fromContextAuthenticator
-import whisk.common.TransactionCounter
+import akka.http.scaladsl.model.headers.BasicHttpCredentials
+
import whisk.core.controller.Authenticate
-import whisk.core.controller.AuthenticatedRoute
import whisk.core.entity._
-import whisk.http.BasicHttpService
import whisk.core.entitlement.Privilege
/**
@@ -62,7 +57,7 @@ class AuthenticateTests extends ControllerTestCommon with Authenticate {
// Try to login with each specific namespace
namespaces.foreach { ns =>
println(s"Trying to login to $ns")
- val pass = UserPass(ns.authkey.uuid.asString, ns.authkey.key.asString)
+ val pass = BasicHttpCredentials(ns.authkey.uuid.asString, ns.authkey.key.asString)
val user = Await.result(validateCredentials(Some(pass)), dbOpTimeout)
user.get shouldBe Identity(subject, ns.name, ns.authkey, Privilege.ALL)
@@ -82,7 +77,7 @@ class AuthenticateTests extends ControllerTestCommon with Authenticate {
val ns = namespaces.head
val key = ns.authkey.key.asString
Seq(key.drop(1), key.dropRight(1), key + "x", AuthKey().key.asString).foreach { k =>
- val pass = UserPass(ns.authkey.uuid.asString, k)
+ val pass = BasicHttpCredentials(ns.authkey.uuid.asString, k)
val user = Await.result(validateCredentials(Some(pass)), dbOpTimeout)
user shouldBe empty
}
@@ -91,7 +86,7 @@ class AuthenticateTests extends ControllerTestCommon with Authenticate {
it should "not log key during validation" in {
implicit val tid = transid()
val creds = WhiskAuthHelpers.newIdentity()
- val pass = UserPass(creds.authkey.uuid.asString, creds.authkey.key.asString)
+ val pass = BasicHttpCredentials(creds.authkey.uuid.asString, creds.authkey.key.asString)
val user = Await.result(validateCredentials(Some(pass)), dbOpTimeout)
user should be(None)
stream.toString should not include creds.authkey.key.asString
@@ -100,7 +95,7 @@ class AuthenticateTests extends ControllerTestCommon with Authenticate {
it should "not authorize an unknown user" in {
implicit val tid = transid()
val creds = WhiskAuthHelpers.newIdentity()
- val pass = UserPass(creds.authkey.uuid.asString, creds.authkey.key.asString)
+ val pass = BasicHttpCredentials(creds.authkey.uuid.asString, creds.authkey.key.asString)
val user = Await.result(validateCredentials(Some(pass)), dbOpTimeout)
user should be(None)
}
@@ -113,61 +108,22 @@ class AuthenticateTests extends ControllerTestCommon with Authenticate {
it should "not authorize when malformed user is provided" in {
implicit val tid = transid()
- val pass = UserPass("x", Secret().asString)
+ val pass = BasicHttpCredentials("x", Secret().asString)
val user = Await.result(validateCredentials(Some(pass)), dbOpTimeout)
user should be(None)
}
it should "not authorize when malformed secret is provided" in {
implicit val tid = transid()
- val pass = UserPass(UUID().asString, "x")
+ val pass = BasicHttpCredentials(UUID().asString, "x")
val user = Await.result(validateCredentials(Some(pass)), dbOpTimeout)
user should be(None)
}
it should "not authorize when malformed creds are provided" in {
implicit val tid = transid()
- val pass = UserPass("x", "y")
+ val pass = BasicHttpCredentials("x", "y")
val user = Await.result(validateCredentials(Some(pass)), dbOpTimeout)
user should be(None)
}
}
-
-class AuthenticatedRouteTests
- extends ControllerTestCommon
- with Authenticate
- with AuthenticatedRoute
- with TransactionCounter {
-
- behavior of "Authenticated Route"
-
- val route = sealRoute {
- implicit val tid = transid()
- handleRejections(BasicHttpService.customRejectionHandler) {
- path("secured") {
- authenticate(basicauth) {
- user => complete("ok")
- }
- }
-
- }
- }
-
- it should "authorize a known user" in {
- implicit val tid = transid()
- val entry = WhiskAuthHelpers.newAuth()
- put(authStore, entry) // this test entry is reclaimed when the test completes
-
- val validCredentials = BasicHttpCredentials(entry.namespaces.head.authkey.uuid.asString, entry.namespaces.head.authkey.key.asString)
- Get("/secured") ~> addCredentials(validCredentials) ~> route ~> check {
- status should be(OK)
- }
- }
-
- it should "not authorize an unknown user" in {
- val invalidCredentials = BasicHttpCredentials(UUID().asString, Secret().asString)
- Get("/secured") ~> addCredentials(invalidCredentials) ~> route ~> check {
- status should be(Unauthorized)
- }
- }
-}
diff --git a/tests/src/test/scala/whisk/core/controller/test/AuthenticateV2Tests.scala b/tests/src/test/scala/whisk/core/controller/test/AuthenticateV2Tests.scala
index 0485b05..9bca5b7 100644
--- a/tests/src/test/scala/whisk/core/controller/test/AuthenticateV2Tests.scala
+++ b/tests/src/test/scala/whisk/core/controller/test/AuthenticateV2Tests.scala
@@ -22,7 +22,8 @@ import scala.concurrent.Await
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
-import spray.routing.authentication.UserPass
+import akka.http.scaladsl.model.headers.BasicHttpCredentials
+
import whisk.core.controller.Authenticate
import whisk.core.entity.AuthKey
import whisk.core.entity.Subject
@@ -66,7 +67,7 @@ class AuthenticateV2Tests extends ControllerTestCommon with Authenticate {
// Try to login with each specific namespace
namespaces.foreach { ns =>
println(s"Trying to login to $ns")
- val pass = UserPass(ns.authkey.uuid.asString, ns.authkey.key.asString)
+ val pass = BasicHttpCredentials(ns.authkey.uuid.asString, ns.authkey.key.asString)
val user = Await.result(validateCredentials(Some(pass)), dbOpTimeout)
user.get shouldBe Identity(subject, ns.name, ns.authkey, Privilege.ALL)
}
diff --git a/tests/src/test/scala/whisk/core/controller/test/ControllerTestCommon.scala b/tests/src/test/scala/whisk/core/controller/test/ControllerTestCommon.scala
index 49864b9..d652272 100644
--- a/tests/src/test/scala/whisk/core/controller/test/ControllerTestCommon.scala
+++ b/tests/src/test/scala/whisk/core/controller/test/ControllerTestCommon.scala
@@ -28,10 +28,13 @@ import org.scalatest.FlatSpec
import org.scalatest.Matchers
import common.StreamLogging
+
+import akka.http.scaladsl.testkit.ScalatestRouteTest
+import akka.http.scaladsl.testkit.RouteTestTimeout
+
import spray.json.DefaultJsonProtocol
import spray.json.JsString
-import spray.routing.HttpService
-import spray.testkit.ScalatestRouteTest
+
import whisk.common.TransactionCounter
import whisk.common.TransactionId
import whisk.core.WhiskConfig
@@ -55,14 +58,12 @@ protected trait ControllerTestCommon
with DbUtils
with ExecHelpers
with WhiskServices
- with HttpService
with StreamLogging {
override val instance = InstanceId(0)
override val numberOfInstances = 1
val activeAckTopicIndex = InstanceId(0)
- override val actorRefFactory = null
implicit val routeTestTimeout = RouteTestTimeout(90 seconds)
override implicit val actorSystem = system // defined in ScalatestRouteTest
diff --git a/tests/src/test/scala/whisk/core/controller/test/EntitlementProviderTests.scala b/tests/src/test/scala/whisk/core/controller/test/EntitlementProviderTests.scala
index ce1205b..e372abb 100644
--- a/tests/src/test/scala/whisk/core/controller/test/EntitlementProviderTests.scala
+++ b/tests/src/test/scala/whisk/core/controller/test/EntitlementProviderTests.scala
@@ -24,7 +24,8 @@ import org.junit.runner.RunWith
import org.scalatest.concurrent.ScalaFutures
import org.scalatest.junit.JUnitRunner
-import spray.http.StatusCodes._
+import akka.http.scaladsl.model.StatusCodes._
+
import whisk.core.controller.RejectRequest
import whisk.core.entitlement._
import whisk.core.entitlement.Privilege._
diff --git a/tests/src/test/scala/whisk/core/controller/test/NamespacesApiTests.scala b/tests/src/test/scala/whisk/core/controller/test/NamespacesApiTests.scala
index a601cd5..545918d 100644
--- a/tests/src/test/scala/whisk/core/controller/test/NamespacesApiTests.scala
+++ b/tests/src/test/scala/whisk/core/controller/test/NamespacesApiTests.scala
@@ -20,16 +20,22 @@ package whisk.core.controller.test
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
-import spray.http.StatusCodes.Forbidden
-import spray.http.StatusCodes.MethodNotAllowed
-import spray.http.StatusCodes.OK
-import spray.httpx.SprayJsonSupport.sprayJsonUnmarshaller
+import akka.http.scaladsl.model.StatusCodes.OK
+import akka.http.scaladsl.model.StatusCodes.Forbidden
+import akka.http.scaladsl.model.StatusCodes.MethodNotAllowed
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport.sprayJsonUnmarshaller
+import akka.http.scaladsl.server.Route
+
import spray.json.DefaultJsonProtocol._
import spray.json._
import whisk.core.controller.Namespaces
import whisk.core.controller.WhiskNamespacesApi
import whisk.core.entity.EntityPath
+import spray.json.JsObject
+import spray.json.JsObject
+import whisk.core.controller.Namespaces
+import spray.json.JsArray
/**
* Tests Namespaces API.
@@ -55,7 +61,7 @@ class NamespacesApiTests extends ControllerTestCommon with WhiskNamespacesApi {
it should "list namespaces for subject" in {
implicit val tid = transid()
- Get(collectionPath) ~> sealRoute(routes(creds)) ~> check {
+ Get(collectionPath) ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val ns = responseAs[List[EntityPath]]
ns should be(List(EntityPath(creds.subject.asString)))
@@ -64,7 +70,7 @@ class NamespacesApiTests extends ControllerTestCommon with WhiskNamespacesApi {
it should "list namespaces for subject with trailing /" in {
implicit val tid = transid()
- Get(s"$collectionPath/") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val ns = responseAs[List[EntityPath]]
ns should be(List(EntityPath(creds.subject.asString)))
@@ -73,7 +79,7 @@ class NamespacesApiTests extends ControllerTestCommon with WhiskNamespacesApi {
it should "get namespace entities for subject" in {
implicit val tid = transid()
- Get(s"$collectionPath/${creds.subject}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${creds.subject}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val ns = responseAs[JsObject]
ns should be(JsObject(Namespaces.emptyNamespace map { kv => (kv._1, JsArray()) }))
@@ -83,28 +89,28 @@ class NamespacesApiTests extends ControllerTestCommon with WhiskNamespacesApi {
it should "reject get namespace entities for unauthorized subject" in {
implicit val tid = transid()
val anothercred = WhiskAuthHelpers.newIdentity()
- Get(s"$collectionPath/${anothercred.subject}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${anothercred.subject}") ~> Route.seal(routes(creds)) ~> check {
status should be(Forbidden)
}
}
it should "reject request with put" in {
implicit val tid = transid()
- Put(s"$collectionPath/${creds.subject}") ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${creds.subject}") ~> Route.seal(routes(creds)) ~> check {
status should be(MethodNotAllowed)
}
}
it should "reject request with post" in {
implicit val tid = transid()
- Post(s"$collectionPath/${creds.subject}") ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${creds.subject}") ~> Route.seal(routes(creds)) ~> check {
status should be(MethodNotAllowed)
}
}
it should "reject request with delete" in {
implicit val tid = transid()
- Delete(s"$collectionPath/${creds.subject}") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${creds.subject}") ~> Route.seal(routes(creds)) ~> check {
status should be(MethodNotAllowed)
}
}
diff --git a/tests/src/test/scala/whisk/core/controller/test/PackageActionsApiTests.scala b/tests/src/test/scala/whisk/core/controller/test/PackageActionsApiTests.scala
index cec0489..4b8241a 100644
--- a/tests/src/test/scala/whisk/core/controller/test/PackageActionsApiTests.scala
+++ b/tests/src/test/scala/whisk/core/controller/test/PackageActionsApiTests.scala
@@ -20,10 +20,14 @@ package whisk.core.controller.test
import scala.concurrent.duration.DurationInt
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
-import spray.http.StatusCodes._
-import spray.httpx.SprayJsonSupport._
+
+import akka.http.scaladsl.model.StatusCodes._
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
+import akka.http.scaladsl.server.Route
+
import spray.json.DefaultJsonProtocol._
import spray.json._
+
import whisk.core.controller.WhiskActionsApi
import whisk.core.entity._
import whisk.core.entitlement.Resource
@@ -66,7 +70,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
put(entityStore, provider)
actions foreach { put(entityStore, _) }
whisk.utils.retry {
- Get(s"$collectionPath/${provider.name}/") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${provider.name}/") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[JsObject]]
actions.length should be(response.length)
@@ -86,7 +90,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
put(entityStore, reference)
actions foreach { put(entityStore, _) }
whisk.utils.retry {
- Get(s"$collectionPath/${reference.name}/") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${reference.name}/") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[JsObject]]
actions.length should be(response.length)
@@ -104,7 +108,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
put(entityStore, action1)
put(entityStore, action2)
whisk.utils.retry {
- Get(s"$collectionPath") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[JsObject]]
response.length should be(2)
@@ -119,7 +123,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val provider = WhiskPackage(namespace, aname, None)
put(entityStore, provider)
whisk.utils.retry {
- Get(s"$collectionPath/${provider.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${provider.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(Conflict)
}
}
@@ -129,7 +133,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
implicit val tid = transid()
val provider = WhiskPackage(namespace, aname, None)
put(entityStore, provider)
- Delete(s"$collectionPath/${provider.name}/") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${provider.name}/") ~> Route.seal(routes(creds)) ~> check {
status should be(NotFound)
}
}
@@ -141,7 +145,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val action = WhiskAction(provider.fullPath, aname, jsDefault("??"))
val content = WhiskActionPut(Some(action.exec))
put(entityStore, provider)
- Put(s"$collectionPath/${provider.name}/${action.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${provider.name}/${action.name}", content) ~> Route.seal(routes(creds)) ~> check {
deleteAction(action.docid)
status should be(OK)
val response = responseAs[WhiskAction]
@@ -156,7 +160,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val provider = WhiskPackage(namespace, aname)
val action = WhiskAction(provider.fullPath, aname, jsDefault("??"))
val content = WhiskActionPut(Some(action.exec))
- Put(s"$collectionPath/${provider.name}/${action.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${provider.name}/${action.name}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(NotFound)
}
}
@@ -167,7 +171,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val binding = WhiskPackage(namespace, aname, provider.bind)
val content = WhiskActionPut(Some(jsDefault("??")))
put(entityStore, binding)
- Put(s"$collectionPath/${binding.name}/$aname", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${binding.name}/$aname", content) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
}
}
@@ -179,7 +183,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val content = WhiskActionPut(Some(jsDefault("??")))
put(entityStore, provider)
put(entityStore, binding)
- Put(s"$collectionPath/${binding.name}/$aname", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${binding.name}/$aname", content) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
}
}
@@ -189,7 +193,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val provider = WhiskPackage(EntityPath(Subject().asString), aname, publish = true)
val content = WhiskActionPut(Some(jsDefault("??")))
put(entityStore, provider)
- Put(s"/${provider.namespace}/${collection.path}/${provider.name}/$aname", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"/${provider.namespace}/${collection.path}/${provider.name}/$aname", content) ~> Route.seal(routes(creds)) ~> check {
status should be(Forbidden)
}
}
@@ -204,11 +208,11 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
// it should "reject delete action in package owned by different subject" in {
val auser = WhiskAuthHelpers.newIdentity()
- Delete(s"/${provider.namespace}/${collection.path}/${provider.name}/${action.name}") ~> sealRoute(routes(auser)) ~> check {
+ Delete(s"/${provider.namespace}/${collection.path}/${provider.name}/${action.name}") ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
- Delete(s"$collectionPath/${provider.name}/${action.name}") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${provider.name}/${action.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskAction]
response should be(action)
@@ -220,7 +224,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val provider = WhiskPackage(namespace, aname)
val action = WhiskAction(provider.fullPath, aname, jsDefault("??"))
put(entityStore, action)
- Delete(s"$collectionPath/${provider.name}/${action.name}") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${provider.name}/${action.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(NotFound)
}
}
@@ -230,7 +234,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val provider = WhiskPackage(namespace, aname)
val action = WhiskAction(provider.fullPath, aname, jsDefault("??"))
put(entityStore, provider)
- Delete(s"$collectionPath/${provider.name}/${action.name}") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${provider.name}/${action.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(NotFound)
}
}
@@ -241,7 +245,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val binding = WhiskPackage(namespace, aname, provider.bind)
val content = WhiskActionPut(Some(jsDefault("??")))
put(entityStore, binding)
- Delete(s"$collectionPath/${binding.name}/$aname") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${binding.name}/$aname") ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
}
}
@@ -253,7 +257,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val content = WhiskActionPut(Some(jsDefault("??")))
put(entityStore, provider)
put(entityStore, binding)
- Delete(s"$collectionPath/${binding.name}/$aname") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${binding.name}/$aname") ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
}
}
@@ -264,7 +268,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val action = WhiskAction(provider.fullPath, aname, jsDefault("??"))
put(entityStore, provider)
put(entityStore, action)
- Delete(s"/${provider.namespace}/${collection.path}/${provider.name}/${action.name}") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"/${provider.namespace}/${collection.path}/${provider.name}/${action.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(Forbidden)
}
}
@@ -277,7 +281,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
put(entityStore, provider)
put(entityStore, action)
whisk.utils.retry {
- Get(s"$collectionPath/${provider.name}/${action.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${provider.name}/${action.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskAction]
response should be(action inherit provider.parameters)
@@ -295,7 +299,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
put(entityStore, binding)
put(entityStore, action)
whisk.utils.retry {
- Get(s"$collectionPath/${binding.name}/${action.name}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"$collectionPath/${binding.name}/${action.name}") ~> Route.seal(routes(auser)) ~> check {
status should be(OK)
val response = responseAs[WhiskAction]
response should be(action inherit (provider.parameters ++ binding.parameters))
@@ -313,7 +317,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
put(entityStore, binding)
put(entityStore, action)
whisk.utils.retry {
- Get(s"$collectionPath/${binding.name}/${action.name}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"$collectionPath/${binding.name}/${action.name}") ~> Route.seal(routes(auser)) ~> check {
status should be(OK)
val response = responseAs[WhiskAction]
response should be(action inherit (provider.parameters ++ binding.parameters))
@@ -334,7 +338,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
put(entityStore, action)
val pkgaccess = Resource(provider.namespace, PACKAGES, Some(provider.name.asString))
Await.result(entitlementProvider.grant(auser.subject, READ, pkgaccess), 1 second)
- Get(s"$collectionPath/${binding.name}/${action.name}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"$collectionPath/${binding.name}/${action.name}") ~> Route.seal(routes(auser)) ~> check {
status should be(OK)
val response = responseAs[WhiskAction]
response should be(action inherit (provider.parameters ++ binding.parameters))
@@ -346,7 +350,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val provider = WhiskPackage(namespace, aname)
val action = WhiskAction(provider.fullPath, aname, jsDefault("??"))
put(entityStore, action)
- Get(s"$collectionPath/${provider.name}/${action.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${provider.name}/${action.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(NotFound)
}
}
@@ -356,7 +360,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val provider = WhiskPackage(namespace, aname)
val action = WhiskAction(provider.fullPath, aname, jsDefault("??"))
put(entityStore, provider)
- Get(s"$collectionPath/${provider.name}/${action.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${provider.name}/${action.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(NotFound)
}
}
@@ -370,7 +374,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val action = WhiskAction(provider.fullPath, aname, jsDefault("??"), Parameters("a", "A"))
put(entityStore, provider)
put(entityStore, action)
- Get(s"$collectionPath/${binding.name}/${action.name}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"$collectionPath/${binding.name}/${action.name}") ~> Route.seal(routes(auser)) ~> check {
status should be(NotFound)
}
}
@@ -384,7 +388,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val action = WhiskAction(provider.fullPath, aname, jsDefault("??"), Parameters("a", "A"))
put(entityStore, binding)
put(entityStore, action)
- Get(s"$collectionPath/${binding.name}/${action.name}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"$collectionPath/${binding.name}/${action.name}") ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden) // do not leak that package does not exist
}
}
@@ -398,7 +402,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val action = WhiskAction(provider.fullPath, aname, jsDefault("??"), Parameters("a", "A"))
put(entityStore, provider)
put(entityStore, binding)
- Get(s"$collectionPath/${binding.name}/${action.name}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"$collectionPath/${binding.name}/${action.name}") ~> Route.seal(routes(auser)) ~> check {
status should be(NotFound)
}
}
@@ -412,7 +416,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
put(entityStore, provider)
put(entityStore, binding)
put(entityStore, action)
- Get(s"$collectionPath/${binding.name}/${action.name}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"$collectionPath/${binding.name}/${action.name}") ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
}
@@ -425,7 +429,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val content = JsObject("xxx" -> "yyy".toJson)
put(entityStore, provider)
put(entityStore, action)
- Post(s"$collectionPath/${provider.name}/${action.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${provider.name}/${action.name}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(Accepted)
val response = responseAs[JsObject]
response.fields("activationId") should not be None
@@ -440,7 +444,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val content = JsObject("xxx" -> "yyy".toJson)
put(entityStore, provider)
put(entityStore, action)
- Post(s"/$namespace/${collection.path}/${provider.name}/${action.name}", content) ~> sealRoute(routes(auser)) ~> check {
+ Post(s"/$namespace/${collection.path}/${provider.name}/${action.name}", content) ~> Route.seal(routes(auser)) ~> check {
status should be(Accepted)
val response = responseAs[JsObject]
response.fields("activationId") should not be None
@@ -457,7 +461,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
put(entityStore, provider)
put(entityStore, reference)
put(entityStore, action)
- Post(s"$collectionPath/${reference.name}/${action.name}", content) ~> sealRoute(routes(auser)) ~> check {
+ Post(s"$collectionPath/${reference.name}/${action.name}", content) ~> Route.seal(routes(auser)) ~> check {
status should be(Accepted)
val response = responseAs[JsObject]
response.fields("activationId") should not be None
@@ -478,7 +482,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
put(entityStore, action)
val pkgaccess = Resource(provider.namespace, PACKAGES, Some(provider.name.asString))
Await.result(entitlementProvider.grant(auser.subject, ACTIVATE, pkgaccess), 1 second)
- Post(s"$collectionPath/${reference.name}/${action.name}", content) ~> sealRoute(routes(auser)) ~> check {
+ Post(s"$collectionPath/${reference.name}/${action.name}", content) ~> Route.seal(routes(auser)) ~> check {
status should be(Accepted)
val response = responseAs[JsObject]
response.fields("activationId") should not be None
@@ -493,7 +497,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val content = JsObject("xxx" -> "yyy".toJson)
put(entityStore, provider)
put(entityStore, action)
- Post(s"/$namespace/${collection.path}/${provider.name}/${action.name}", content) ~> sealRoute(routes(auser)) ~> check {
+ Post(s"/$namespace/${collection.path}/${provider.name}/${action.name}", content) ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
}
@@ -504,7 +508,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val action = WhiskAction(provider.fullPath, aname, jsDefault("??"))
val content = JsObject("xxx" -> "yyy".toJson)
put(entityStore, action)
- Post(s"$collectionPath/${provider.name}/${action.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${provider.name}/${action.name}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(NotFound)
}
}
@@ -515,7 +519,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
val action = WhiskAction(provider.fullPath, aname, jsDefault("??"))
val content = JsObject("xxx" -> "yyy".toJson)
put(entityStore, action)
- Post(s"$collectionPath/${provider.name}/${action.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${provider.name}/${action.name}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(NotFound)
}
}
@@ -530,7 +534,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
put(entityStore, provider)
put(entityStore, reference)
put(entityStore, action)
- Post(s"$collectionPath/${reference.name}/${action.name}", content) ~> sealRoute(routes(auser)) ~> check {
+ Post(s"$collectionPath/${reference.name}/${action.name}", content) ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
}
@@ -542,7 +546,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
put(entityStore, provider)
put(entityStore, entity)
- Delete(s"$collectionPath/${provider.name}/${entity.name}") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${provider.name}/${entity.name}") ~> Route.seal(routes(creds)) ~> check {
responseAs[ErrorResponse].error shouldBe Messages.corruptedEntity
}
}
@@ -554,7 +558,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
put(entityStore, provider, false)
put(entityStore, entity, false)
- Delete(s"$collectionPath/${provider.name}/${entity.name}") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${provider.name}/${entity.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(InternalServerError)
responseAs[ErrorResponse].error shouldBe Messages.corruptedEntity
}
@@ -567,13 +571,13 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
put(entityStore, provider)
put(entityStore, entity)
- Get(s"$collectionPath/${provider.name}/${entity.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${provider.name}/${entity.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(InternalServerError)
responseAs[ErrorResponse].error shouldBe Messages.corruptedEntity
}
val auser = WhiskAuthHelpers.newIdentity()
- Get(s"/${provider.namespace}/${collection.path}/${provider.name}/${entity.name}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"/${provider.namespace}/${collection.path}/${provider.name}/${entity.name}") ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
responseAs[ErrorResponse].error shouldBe Messages.notAuthorizedtoOperateOnResource
}
@@ -586,7 +590,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
put(entityStore, provider)
put(entityStore, entity)
- Get(s"$collectionPath/${provider.name}/${entity.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${provider.name}/${entity.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(InternalServerError)
responseAs[ErrorResponse].error shouldBe Messages.corruptedEntity
}
@@ -600,7 +604,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
put(entityStore, entity)
val content = WhiskActionPut()
- Put(s"$collectionPath/${provider.name}/${entity.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${provider.name}/${entity.name}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(InternalServerError)
responseAs[ErrorResponse].error shouldBe Messages.corruptedEntity
}
@@ -614,7 +618,7 @@ class PackageActionsApiTests extends ControllerTestCommon with WhiskActionsApi {
put(entityStore, entity)
val content = WhiskActionPut()
- Put(s"$collectionPath/${provider.name}/${entity.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${provider.name}/${entity.name}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(InternalServerError)
responseAs[ErrorResponse].error shouldBe Messages.corruptedEntity
}
diff --git a/tests/src/test/scala/whisk/core/controller/test/PackagesApiTests.scala b/tests/src/test/scala/whisk/core/controller/test/PackagesApiTests.scala
index 9df7087..688e444 100644
--- a/tests/src/test/scala/whisk/core/controller/test/PackagesApiTests.scala
+++ b/tests/src/test/scala/whisk/core/controller/test/PackagesApiTests.scala
@@ -21,10 +21,14 @@ import scala.language.postfixOps
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
-import spray.http.StatusCodes._
-import spray.httpx.SprayJsonSupport._
+
+import akka.http.scaladsl.model.StatusCodes._
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
+import akka.http.scaladsl.server.Route
+
import spray.json.DefaultJsonProtocol._
import spray.json._
+
import whisk.core.entity._
import whisk.core.controller.WhiskPackagesApi
import whisk.http.ErrorResponse
@@ -73,7 +77,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
providers foreach { put(entityStore, _) }
waitOnView(entityStore, WhiskPackage, namespace, providers.length)
whisk.utils.retry {
- Get(s"$collectionPath") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[JsObject]]
providers.length should be(response.length)
@@ -82,7 +86,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
}
val auser = WhiskAuthHelpers.newIdentity()
- Get(s"/$namespace/${collection.path}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"/$namespace/${collection.path}") ~> Route.seal(routes(auser)) ~> check {
val response = responseAs[List[JsObject]]
response should be(List()) // cannot list packages that are private in another namespace
}
@@ -105,7 +109,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
waitOnView(entityStore, WhiskPackage, namespaces(1), 1)
waitOnView(entityStore, WhiskPackage, namespaces(2), 1)
waitOnView(entityStore, WhiskPackage, namespaces(0), 1 + 4)
- Get(s"$collectionPath") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[JsObject]]
val expected = providers.filter { _.namespace == namespace } ++ references
@@ -114,7 +118,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
}
val auser = WhiskAuthHelpers.newIdentity()
- Get(s"/$namespace/${collection.path}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"/$namespace/${collection.path}") ~> Route.seal(routes(auser)) ~> check {
status should be(OK)
val response = responseAs[List[JsObject]]
val expected = providers.filter {
@@ -144,7 +148,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
waitOnView(entityStore, WhiskPackage, namespaces(1), 1)
waitOnView(entityStore, WhiskPackage, namespaces(2), 1)
waitOnView(entityStore, WhiskPackage, namespaces(0), 1 + 4)
- Get(s"$collectionPath?public=true") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath?public=true") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[JsObject]]
val expected = providers filter { _.publish }
@@ -167,7 +171,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
waitOnView(entityStore, WhiskPackage, namespaces(0), 1)
waitOnView(entityStore, WhiskPackage, namespaces(1), 1)
waitOnView(entityStore, WhiskPackage, namespaces(2), 1)
- Get(s"$collectionPath?public=true") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath?public=true") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[JsObject]]
val expected = providers filter { _.publish }
@@ -179,7 +183,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
// confirm ?public disabled
it should "ignore ?public on list all packages" in {
implicit val tid = transid()
- Get(s"$collectionPath?public=true") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath?public=true") ~> Route.seal(routes(creds)) ~> check {
implicit val tid = transid()
// create packages and package bindings, set some public and confirm API lists only public packages
val namespaces = Seq(namespace, EntityPath(aname().toString), EntityPath(aname().toString))
@@ -192,7 +196,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
waitOnView(entityStore, WhiskPackage, namespaces(0), 1)
waitOnView(entityStore, WhiskPackage, namespaces(1), 1)
waitOnView(entityStore, WhiskPackage, namespaces(2), 1)
- Get(s"$collectionPath?public=true") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath?public=true") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[JsObject]]
val expected = providers filter { _.namespace == creds.namespace.toPath }
@@ -205,7 +209,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
// ?public disabled
ignore should "reject list all public packages with invalid parameters" in {
implicit val tid = transid()
- Get(s"$collectionPath?public=true&docs=true") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath?public=true&docs=true") ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
}
}
@@ -215,13 +219,13 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
implicit val tid = transid()
val provider = WhiskPackage(namespace, aname(), None)
put(entityStore, provider)
- Get(s"$collectionPath/${provider.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${provider.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskPackageWithActions]
response should be(provider withActions ())
}
- Get(s"$collectionPath/${provider.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${provider.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskPackageWithActions]
response should be(provider withActions ())
@@ -234,7 +238,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
val reference = WhiskPackage(namespace, aname(), provider.bind, Parameters("b", "b") ++ Parameters("c", "C"))
put(entityStore, provider)
put(entityStore, reference)
- Get(s"$collectionPath/${reference.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${reference.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskPackageWithActions]
response should be(reference inherit provider.parameters withActions ())
@@ -252,7 +256,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
val reference = WhiskPackage(namespace, aname(), provider.bind)
put(entityStore, provider)
put(entityStore, reference)
- Get(s"$collectionPath/${reference.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${reference.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(Forbidden)
}
}
@@ -268,11 +272,11 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
// it should "reject get private package from other subject" in {
val auser = WhiskAuthHelpers.newIdentity()
- Get(s"/$namespace/${collection.path}/${provider.name}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"/$namespace/${collection.path}/${provider.name}") ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
- Get(s"$collectionPath/${provider.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${provider.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskPackageWithActions]
response should be(provider withActions (List(action, feed)))
@@ -292,11 +296,11 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
// it should "reject get package reference from other subject" in {
val auser = WhiskAuthHelpers.newIdentity()
- Get(s"/$namespace/${collection.path}/${reference.name}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"/$namespace/${collection.path}/${reference.name}") ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
- Get(s"$collectionPath/${reference.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${reference.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskPackageWithActions]
response should be(reference withActions (List(action, feed)))
@@ -318,11 +322,11 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
// it should "reject get package reference from other subject" in {
val auser = WhiskAuthHelpers.newIdentity()
- Get(s"/$namespace/${collection.path}/${reference.name}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"/$namespace/${collection.path}/${reference.name}") ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
- Get(s"$collectionPath/${reference.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${reference.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(Forbidden)
}
}
@@ -334,7 +338,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
// binding annotation should be removed
val someBindingAnnotation = Parameters(WhiskPackage.bindingFieldName, "???")
val content = WhiskPackagePut(annotations = Some(someBindingAnnotation ++ Parameters("a", "b")))
- Put(s"$collectionPath/${provider.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${provider.name}", content) ~> Route.seal(routes(creds)) ~> check {
deletePackage(provider.docid)
status should be(OK)
val response = responseAs[WhiskPackage]
@@ -353,11 +357,11 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
// it should "reject create package reference in some other namespace" in {
val auser = WhiskAuthHelpers.newIdentity()
- Put(s"/$namespace/${collection.path}/${reference.name}", content) ~> sealRoute(routes(auser)) ~> check {
+ Put(s"/$namespace/${collection.path}/${reference.name}", content) ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
- Put(s"/$namespace/${collection.path}/${reference.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"/$namespace/${collection.path}/${reference.name}", content) ~> Route.seal(routes(creds)) ~> check {
deletePackage(reference.docid)
status should be(OK)
val response = responseAs[WhiskPackage]
@@ -376,7 +380,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
val content = WhiskPackagePut(reference.binding)
put(entityStore, provider)
- Put(s"/$namespace/${collection.path}/${reference.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"/$namespace/${collection.path}/${reference.name}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(Forbidden)
}
}
@@ -387,7 +391,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
val reference = WhiskPackage(namespace, aname(), Some(Binding(EntityPath.DEFAULT.root, provider.name)))
val content = WhiskPackagePut(reference.binding)
put(entityStore, provider)
- Put(s"$collectionPath/${reference.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${reference.name}", content) ~> Route.seal(routes(creds)) ~> check {
deletePackage(reference.docid)
status should be(OK)
val response = responseAs[WhiskPackage]
@@ -402,7 +406,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
implicit val tid = transid()
val binding = Some(Binding(namespace.root, aname()))
val content = WhiskPackagePut(binding)
- Put(s"$collectionPath/${aname()}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${aname()}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[ErrorResponse].error should include(Messages.bindingDoesNotExist)
}
@@ -415,7 +419,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
val binding = Some(Binding(privateNamespace.root, aname()))
val content = WhiskPackagePut(binding)
- Put(s"$collectionPath/${aname()}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${aname()}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(Forbidden)
}
}
@@ -427,7 +431,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
val content = WhiskPackagePut(Some(Binding(reference.namespace.root, reference.name)))
put(entityStore, provider)
put(entityStore, reference)
- Put(s"$collectionPath/${aname()}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${aname()}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[ErrorResponse].error should include(Messages.bindingCannotReferenceBinding)
}
@@ -440,7 +444,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
Parameters(key.toString, "a" * 10)
} reduce (_ ++ _)
val content = s"""{"annotations":$annotations}""".parseJson.asJsObject
- Put(s"$collectionPath/${aname()}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${aname()}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(RequestEntityTooLarge)
responseAs[String] should include {
Messages.entityTooBig(SizeError(WhiskEntity.annotationsFieldName, annotations.size, Parameters.sizeLimit))
@@ -455,7 +459,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
Parameters(key.toString, "a" * 10)
} reduce (_ ++ _)
val content = s"""{"parameters":$parameters}""".parseJson.asJsObject
- Put(s"$collectionPath/${aname()}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${aname()}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(RequestEntityTooLarge)
responseAs[String] should include {
Messages.entityTooBig(SizeError(WhiskEntity.paramsFieldName, parameters.size, Parameters.sizeLimit))
@@ -472,7 +476,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
val provider = WhiskPackage(namespace, aname())
val content = s"""{"parameters":$parameters}""".parseJson.asJsObject
put(entityStore, provider)
- Put(s"$collectionPath/${aname()}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${aname()}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
status should be(RequestEntityTooLarge)
responseAs[String] should include {
Messages.entityTooBig(SizeError(WhiskEntity.paramsFieldName, parameters.size, Parameters.sizeLimit))
@@ -488,11 +492,11 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
// it should "reject update package owned by different user" in {
val auser = WhiskAuthHelpers.newIdentity()
- Put(s"/$namespace/${collection.path}/${provider.name}?overwrite=true", content) ~> sealRoute(routes(auser)) ~> check {
+ Put(s"/$namespace/${collection.path}/${provider.name}?overwrite=true", content) ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
- Put(s"$collectionPath/${provider.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${provider.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
deletePackage(provider.docid)
val response = responseAs[WhiskPackage]
response should be(WhiskPackage(namespace, provider.name, None, version = provider.version.upPatch, publish = true))
@@ -511,11 +515,11 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
// it should "reject update package reference owned by different user"
val auser = WhiskAuthHelpers.newIdentity()
- Put(s"/$namespace/${collection.path}/${reference.name}?overwrite=true", content) ~> sealRoute(routes(auser)) ~> check {
+ Put(s"/$namespace/${collection.path}/${reference.name}?overwrite=true", content) ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
- Put(s"$collectionPath/${reference.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${reference.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
deletePackage(reference.docid)
status should be(OK)
val response = responseAs[WhiskPackage]
@@ -533,7 +537,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
val provider = WhiskPackage(namespace, aname())
val content = WhiskPackagePut(provider.bind)
put(entityStore, provider)
- Put(s"$collectionPath/${provider.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${provider.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
status should be(Conflict)
responseAs[ErrorResponse].error should include(Messages.packageCannotBecomeBinding)
}
@@ -545,7 +549,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
val reference = WhiskPackage(namespace, aname(), provider.bind)
val content = WhiskPackagePut(reference.binding)
put(entityStore, reference)
- Put(s"$collectionPath/${reference.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${reference.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[ErrorResponse].error should include(Messages.bindingDoesNotExist)
}
@@ -560,7 +564,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
val reference = WhiskPackage(namespace, aname(), provider.bind)
val content = WhiskPackagePut(reference.binding)
put(entityStore, reference)
- Put(s"$collectionPath/${reference.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${reference.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
status should be(Forbidden)
}
}
@@ -575,7 +579,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
val content = WhiskPackagePut(reference.binding)
put(entityStore, provider)
put(entityStore, reference)
- Put(s"$collectionPath/${reference.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${reference.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
status should be(Forbidden)
}
}
@@ -588,11 +592,11 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
// it should "reject deleting package owned by different user" in {
val auser = WhiskAuthHelpers.newIdentity()
- Get(s"/$namespace/${collection.path}/${provider.name}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"/$namespace/${collection.path}/${provider.name}") ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
- Delete(s"$collectionPath/${provider.name}") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${provider.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskPackage]
response should be(provider)
@@ -607,11 +611,11 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
// it should "reject deleting package reference owned by different user" in {
val auser = WhiskAuthHelpers.newIdentity()
- Get(s"/$namespace/${collection.path}/${reference.name}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"/$namespace/${collection.path}/${reference.name}") ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
- Delete(s"$collectionPath/${reference.name}") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${reference.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskPackage]
response should be(reference)
@@ -625,14 +629,14 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
put(entityStore, provider)
put(entityStore, action)
whisk.utils.retry {
- Get(s"$collectionPath/${provider.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${provider.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[JsObject]
response.fields("actions").asInstanceOf[JsArray].elements.length should be(1)
}
}
- Delete(s"$collectionPath/${provider.name}") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${provider.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(Conflict)
val response = responseAs[ErrorResponse]
response.error should include("Package not empty (contains 1 entity)")
@@ -645,7 +649,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
implicit val tid = transid()
val provider = WhiskPackage(namespace, aname())
put(entityStore, provider)
- Get(s"$collectionPath/${provider.name}/bar") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${provider.name}/bar") ~> Route.seal(routes(creds)) ~> check {
status should be(NotFound)
}
}
@@ -658,7 +662,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
put(entityStore, action)
- Put(s"$collectionPath/${reference.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${reference.name}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(Conflict)
responseAs[ErrorResponse].error should include(Messages.requestedBindingIsNotValid)
}
@@ -669,7 +673,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
val entity = BadEntity(namespace, aname())
put(entityStore, entity)
- Delete(s"$collectionPath/${entity.name}") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${entity.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(InternalServerError)
responseAs[ErrorResponse].error shouldBe Messages.corruptedEntity
}
@@ -680,7 +684,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
val entity = BadEntity(namespace, aname())
put(entityStore, entity)
- Get(s"$collectionPath/${entity.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${entity.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(InternalServerError)
}
}
@@ -691,7 +695,7 @@ class PackagesApiTests extends ControllerTestCommon with WhiskPackagesApi {
put(entityStore, entity)
val content = WhiskPackagePut()
- Put(s"$collectionPath/${entity.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${entity.name}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(InternalServerError)
responseAs[ErrorResponse].error shouldBe Messages.corruptedEntity
}
diff --git a/tests/src/test/scala/whisk/core/controller/test/RespondWithHeadersTests.scala b/tests/src/test/scala/whisk/core/controller/test/RespondWithHeadersTests.scala
index 48cbd6b..fc8ddb9 100644
--- a/tests/src/test/scala/whisk/core/controller/test/RespondWithHeadersTests.scala
+++ b/tests/src/test/scala/whisk/core/controller/test/RespondWithHeadersTests.scala
@@ -20,10 +20,10 @@ package whisk.core.controller.test
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
-import spray.http.StatusCodes.NotFound
-import spray.http.StatusCodes.OK
-import spray.httpx.marshalling.ToResponseMarshallable.isMarshallable
-import spray.routing.Directive.pimpApply
+import akka.http.scaladsl.model.StatusCodes.NotFound
+import akka.http.scaladsl.model.StatusCodes.OK
+import akka.http.scaladsl.server.Route
+
import whisk.core.controller.RespondWithHeaders
/**
@@ -62,28 +62,28 @@ class RespondWithHeadersTests extends ControllerTestCommon with RespondWithHeade
}
it should "respond to options" in {
- Options("/api/v1") ~> sealRoute(routes) ~> check {
+ Options("/api/v1") ~> Route.seal(routes) ~> check {
headers should contain allOf (allowOrigin, allowHeaders)
}
}
it should "respond to options on every route under /api/v1" in {
- Options("/api/v1/one") ~> sealRoute(routes) ~> check {
+ Options("/api/v1/one") ~> Route.seal(routes) ~> check {
headers should contain allOf (allowOrigin, allowHeaders)
}
- Options("/api/v1/two") ~> sealRoute(routes) ~> check {
+ Options("/api/v1/two") ~> Route.seal(routes) ~> check {
headers should contain allOf (allowOrigin, allowHeaders)
}
}
it should "respond to options even on bogus routes under /api/v1" in {
- Options("/api/v1/bogus") ~> sealRoute(routes) ~> check {
+ Options("/api/v1/bogus") ~> Route.seal(routes) ~> check {
headers should contain allOf (allowOrigin, allowHeaders)
}
}
it should "not respond to options on routes before /api/v1" in {
- Options("/api") ~> sealRoute(routes) ~> check {
+ Options("/api") ~> Route.seal(routes) ~> check {
status shouldBe NotFound
}
}
diff --git a/tests/src/test/scala/whisk/core/controller/test/RulesApiTests.scala b/tests/src/test/scala/whisk/core/controller/test/RulesApiTests.scala
index 6a2d93d..d224080 100644
--- a/tests/src/test/scala/whisk/core/controller/test/RulesApiTests.scala
+++ b/tests/src/test/scala/whisk/core/controller/test/RulesApiTests.scala
@@ -21,10 +21,14 @@ import scala.language.postfixOps
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
-import spray.http.StatusCodes._
-import spray.httpx.SprayJsonSupport._
+
+import akka.http.scaladsl.model.StatusCodes._
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
+import akka.http.scaladsl.server.Route
+
import spray.json.DefaultJsonProtocol._
import spray.json._
+
import whisk.core.controller.WhiskRulesApi
import whisk.core.entity._
import whisk.core.entity.test.OldWhiskTrigger
@@ -69,7 +73,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
}.toList
rules foreach { put(entityStore, _) }
waitOnView(entityStore, WhiskRule, namespace, 2)
- Get(s"$collectionPath") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[JsObject]]
rules.length should be(response.length)
@@ -77,7 +81,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
}
// it should "list trirulesggers with explicit namespace owned by subject" in {
- Get(s"/$namespace/${collection.path}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"/$namespace/${collection.path}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[JsObject]]
rules.length should be(response.length)
@@ -86,7 +90,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
// it should "reject list rules with explicit namespace not owned by subject" in {
val auser = WhiskAuthHelpers.newIdentity()
- Get(s"/$namespace/${collection.path}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"/$namespace/${collection.path}") ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
}
@@ -100,7 +104,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
}.toList
rules foreach { put(entityStore, _) }
waitOnView(entityStore, WhiskRule, namespace, 2)
- Get(s"$collectionPath?docs=true") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath?docs=true") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[WhiskRule]]
rules.length should be(response.length)
@@ -114,14 +118,14 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
val rule = WhiskRule(namespace, aname(), afullname(namespace, "bogus trigger"), afullname(namespace, "bogus action"))
put(entityStore, rule)
- Get(s"$collectionPath/${rule.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${rule.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskRuleResponse]
response should be(rule.withStatus(Status.INACTIVE))
}
// it should "get trigger by name in explicit namespace owned by subject" in
- Get(s"/$namespace/${collection.path}/${rule.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"/$namespace/${collection.path}/${rule.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskRuleResponse]
response should be(rule.withStatus(Status.INACTIVE))
@@ -129,7 +133,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
// it should "reject get trigger by name in explicit namespace not owned by subject" in
val auser = WhiskAuthHelpers.newIdentity()
- Get(s"/$namespace/${collection.path}/${rule.name}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"/$namespace/${collection.path}/${rule.name}") ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
}
@@ -137,7 +141,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
it should "reject get of non existent rule" in {
implicit val tid = transid()
- Get(s"$collectionPath/xxx") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/xxx") ~> Route.seal(routes(creds)) ~> check {
status should be(NotFound)
}
}
@@ -153,7 +157,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, trigger)
put(entityStore, rule)
- Get(s"$collectionPath/${rule.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${rule.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskRuleResponse]
response should be(rule.withStatus(Status.ACTIVE))
@@ -169,7 +173,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, trigger)
put(entityStore, rule)
- Get(s"$collectionPath/${rule.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${rule.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskRuleResponse]
response should be(rule.withStatus(Status.INACTIVE))
@@ -183,7 +187,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, trigger)
- Get(s"/$namespace/${collection.path}/${trigger.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"/$namespace/${collection.path}/${trigger.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(Conflict)
}
}
@@ -200,7 +204,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, trigger)
put(entityStore, rule)
- Delete(s"$collectionPath/${rule.name}") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${rule.name}") ~> Route.seal(routes(creds)) ~> check {
deleteTrigger(trigger.docid)
status should be(OK)
@@ -219,7 +223,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, trigger, false)
put(entityStore, rule)
- Delete(s"$collectionPath/${rule.name}") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${rule.name}") ~> Route.seal(routes(creds)) ~> check {
val t = get(entityStore, trigger.docid, WhiskTrigger)
deleteTrigger(t.docid)
@@ -237,7 +241,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, rule)
- Delete(s"$collectionPath/${rule.name}") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${rule.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskRuleResponse]
response should be(rule.withStatus(Status.INACTIVE))
@@ -253,7 +257,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, trigger, false)
put(entityStore, rule)
- Delete(s"$collectionPath/${rule.name}") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${rule.name}") ~> Route.seal(routes(creds)) ~> check {
deleteTrigger(trigger.docid)
status should be(OK)
@@ -274,7 +278,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, trigger, false)
put(entityStore, action)
- Put(s"$collectionPath/${rule.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${rule.name}", content) ~> Route.seal(routes(creds)) ~> check {
val t = get(entityStore, trigger.docid, WhiskTrigger)
deleteTrigger(t.docid)
deleteRule(rule.docid)
@@ -297,7 +301,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, trigger, false)
put(entityStore, action)
- Put(s"$collectionPath/${rule.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${rule.name}", content) ~> Route.seal(routes(creds)) ~> check {
val t = get(entityStore, trigger.docid, WhiskTrigger)
deleteTrigger(t.docid)
deleteRule(rule.docid)
@@ -318,12 +322,12 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
val contentT = JsObject("trigger" -> trigger.name.toJson, "action" -> action.fullyQualifiedName(false).toDocId.toJson)
val contentA = JsObject("action" -> action.name.toJson, "trigger" -> trigger.fullyQualifiedName(false).toDocId.toJson)
- Put(s"$collectionPath/${rule.name}", contentT) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${rule.name}", contentT) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[String] shouldBe s"The request content was malformed:\nrequirement failed: ${Messages.malformedFullyQualifiedEntityName}"
}
- Put(s"$collectionPath/${rule.name}", contentA) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${rule.name}", contentA) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[String] shouldBe s"The request content was malformed:\nrequirement failed: ${Messages.malformedFullyQualifiedEntityName}"
}
@@ -342,7 +346,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, trigger, false)
put(entityStore, action)
- Put(s"$collectionPath/${rule.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${rule.name}", content) ~> Route.seal(routes(creds)) ~> check {
val t = get(entityStore, trigger.docid, WhiskTrigger)
deleteTrigger(t.docid)
deleteRule(rule.docid)
@@ -370,7 +374,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, trigger, false)
put(entityStore, action)
- Put(s"$collectionPath/${rule.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${rule.name}", content) ~> Route.seal(routes(creds)) ~> check {
val t = get(entityStore, trigger.docid, WhiskTrigger)
deleteTrigger(t.docid)
deleteRule(rule.docid)
@@ -397,7 +401,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, trigger, false)
put(entityStore, action)
- Put(s"$collectionPath/${aname()}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${aname()}", content) ~> Route.seal(routes(creds)) ~> check {
val t = get(entityStore, trigger.docid, WhiskTrigger)
deleteTrigger(t.docid)
@@ -425,7 +429,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, action)
put(entityStore, rule)
- Put(s"$collectionPath/${rule.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${rule.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
val t = get(entityStore, trigger.docid, WhiskTrigger)
deleteTrigger(t.docid)
@@ -444,7 +448,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, trigger)
- Put(s"$collectionPath/xxx", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/xxx", content) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[String] === s"${content.action.get.qualifiedNameWithLeadingSlash} does not exist"
}
@@ -458,7 +462,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, action)
- Put(s"$collectionPath/xxx", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/xxx", content) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[String] === s"${content.trigger.get.qualifiedNameWithLeadingSlash} does not exist"
}
@@ -469,7 +473,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
val content = WhiskRulePut(Some(afullname(namespace, "bogus trigger")), Some(afullname(namespace, "bogus action")))
- Put(s"$collectionPath/xxx", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/xxx", content) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[String].contains("does not exist") should be(true)
}
@@ -487,7 +491,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, action)
put(entityStore, rule, false)
- Put(s"$collectionPath/${rule.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${rule.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
val t = get(entityStore, trigger.docid, WhiskTrigger)
deleteTrigger(t.docid)
deleteRule(rule.docid)
@@ -512,7 +516,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, action)
put(entityStore, rule, false)
- Put(s"$collectionPath/${rule.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${rule.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
val t = get(entityStore, trigger.docid, WhiskTrigger)
deleteTrigger(t.docid)
deleteRule(rule.docid)
@@ -536,7 +540,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, action)
put(entityStore, rule, false)
- Put(s"$collectionPath/${rule.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${rule.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
val t = get(entityStore, trigger.docid, WhiskTrigger)
deleteTrigger(t.docid)
deleteRule(rule.docid)
@@ -560,7 +564,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, action)
put(entityStore, rule, false)
- Put(s"$collectionPath/${rule.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${rule.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
val t = get(entityStore, trigger.docid, WhiskTrigger)
deleteTrigger(t.docid)
deleteRule(rule.docid)
@@ -583,7 +587,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, action)
put(entityStore, rule, false)
- Put(s"$collectionPath/${rule.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${rule.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
deleteTrigger(trigger.docid)
deleteRule(rule.docid)
@@ -603,7 +607,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, action)
put(entityStore, rule)
- Put(s"$collectionPath/${rule.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${rule.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[String] === s"${rule.trigger.qualifiedNameWithLeadingSlash} does not exist"
}
@@ -619,7 +623,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, trigger)
put(entityStore, rule)
- Put(s"$collectionPath/${rule.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${rule.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[String] === s"${rule.action.qualifiedNameWithLeadingSlash} does not exist"
}
@@ -632,7 +636,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, rule)
- Put(s"$collectionPath/${rule.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${rule.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[String] should {
include(s"${rule.action.qualifiedNameWithLeadingSlash} does not exist") or
@@ -655,7 +659,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, action)
put(entityStore, rule, false)
- Put(s"$collectionPath/${rule.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${rule.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
val t = get(entityStore, trigger.docid, WhiskTrigger)
deleteTrigger(t.docid)
deleteRule(rule.docid)
@@ -675,7 +679,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, rule)
- Post(s"$collectionPath/${rule.name}", inactiveStatus) ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${rule.name}", inactiveStatus) ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
}
}
@@ -691,7 +695,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, trigger)
put(entityStore, rule)
- Post(s"$collectionPath/${rule.name}", activeStatus) ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${rule.name}", activeStatus) ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
}
}
@@ -699,7 +703,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
it should "reject post with status undefined" in {
implicit val tid = transid()
- Post(s"$collectionPath/xyz") ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/xyz") ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
}
}
@@ -709,7 +713,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
val badStatus = s"""{"status":"xxx"}""".parseJson.asJsObject
- Post(s"$collectionPath/xyz", badStatus) ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/xyz", badStatus) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
}
}
@@ -725,7 +729,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, trigger, false)
put(entityStore, rule)
- Post(s"$collectionPath/${rule.name}", activeStatus) ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${rule.name}", activeStatus) ~> Route.seal(routes(creds)) ~> check {
val t = get(entityStore, trigger.docid, WhiskTrigger)
deleteTrigger(t.docid)
@@ -744,7 +748,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, trigger, false)
put(entityStore, rule)
- Post(s"$collectionPath/${rule.name}", activeStatus) ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${rule.name}", activeStatus) ~> Route.seal(routes(creds)) ~> check {
val t = get(entityStore, trigger.docid, WhiskTrigger)
deleteTrigger(t.docid)
@@ -760,7 +764,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, rule)
- Post(s"$collectionPath/${rule.name}", activeStatus) ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${rule.name}", activeStatus) ~> Route.seal(routes(creds)) ~> check {
status should be(NotFound)
}
}
@@ -776,7 +780,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, trigger, false)
put(entityStore, rule)
- Post(s"$collectionPath/${rule.name}", inactiveStatus) ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${rule.name}", inactiveStatus) ~> Route.seal(routes(creds)) ~> check {
val t = get(entityStore, trigger.docid, WhiskTrigger)
deleteTrigger(t.docid)
@@ -793,7 +797,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, rule)
- Get(s"$collectionPath/${rule.name}/bar") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${rule.name}/bar") ~> Route.seal(routes(creds)) ~> check {
status should be(NotFound)
}
}
@@ -806,7 +810,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, rule)
- Get(s"$collectionPath/${rule.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${rule.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskRuleResponse]
response should be(rule.toWhiskRule.withStatus(Status.INACTIVE))
@@ -825,7 +829,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, trigger, false)
put(entityStore, action)
- Put(s"$collectionPath/${rule.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${rule.name}", content) ~> Route.seal(routes(creds)) ~> check {
val t = get(entityStore, trigger.docid, WhiskTrigger)
deleteTrigger(t.docid)
deleteRule(rule.docid)
@@ -849,7 +853,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, trigger, false)
put(entityStore, rule)
- Post(s"$collectionPath/${rule.name}", activeStatus) ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${rule.name}", activeStatus) ~> Route.seal(routes(creds)) ~> check {
val t = get(entityStore, trigger.docid, WhiskTrigger)
deleteTrigger(t.docid)
@@ -864,7 +868,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
val entity = BadEntity(namespace, aname())
put(entityStore, entity)
- Delete(s"$collectionPath/${entity.name}") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${entity.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(InternalServerError)
responseAs[ErrorResponse].error shouldBe Messages.corruptedEntity
}
@@ -875,7 +879,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
val entity = BadEntity(namespace, aname())
put(entityStore, entity)
- Get(s"$collectionPath/${entity.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${entity.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(InternalServerError)
responseAs[ErrorResponse].error shouldBe Messages.corruptedEntity
}
@@ -887,7 +891,7 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, entity)
val content = WhiskRulePut()
- Put(s"$collectionPath/${entity.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${entity.name}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(InternalServerError)
responseAs[ErrorResponse].error shouldBe Messages.corruptedEntity
}
@@ -910,17 +914,17 @@ class RulesApiTests extends ControllerTestCommon with WhiskRulesApi {
put(entityStore, trigger)
put(entityStore, action)
- Put(s"$collectionPath/${aname()}", contenta) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${aname()}", contenta) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[ErrorResponse].error shouldBe Messages.corruptedEntity
}
- Put(s"$collectionPath/${aname()}", contentb) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${aname()}", contentb) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[ErrorResponse].error shouldBe Messages.corruptedEntity
}
- Put(s"$collectionPath/${aname()}", contentc) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${aname()}", contentc) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[ErrorResponse].error shouldBe Messages.corruptedEntity
}
diff --git a/tests/src/test/scala/whisk/core/controller/test/SequenceApiTests.scala b/tests/src/test/scala/whisk/core/controller/test/SequenceApiTests.scala
index fccc86f..689dd9a 100644
--- a/tests/src/test/scala/whisk/core/controller/test/SequenceApiTests.scala
+++ b/tests/src/test/scala/whisk/core/controller/test/SequenceApiTests.scala
@@ -23,10 +23,13 @@ import scala.language.postfixOps
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
-import spray.http.StatusCodes._
-import spray.httpx.SprayJsonSupport._
+import akka.http.scaladsl.model.StatusCodes._
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
+import akka.http.scaladsl.server.Route
+
import spray.json._
import spray.json.DefaultJsonProtocol._
+
import whisk.common.TransactionId
import whisk.core.controller.WhiskActionsApi
import whisk.core.entity._
@@ -62,7 +65,7 @@ class SequenceApiTests
val content = WhiskActionPut(Some(sequence(components.toVector)))
// create an action sequence
- Put(s"$collectionPath/${seqName.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${seqName.name}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[ErrorResponse].error shouldBe Messages.sequenceIsTooLong
}
@@ -75,7 +78,7 @@ class SequenceApiTests
val content = WhiskActionPut(Some(sequence(Vector())))
// create an action sequence
- Put(s"$collectionPath/$seqName", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/$seqName", content) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[ErrorResponse].error shouldBe Messages.sequenceNoComponent
}
@@ -91,7 +94,7 @@ class SequenceApiTests
val updateContent = WhiskActionPut(Some(sequence(Vector())))
// create an action sequence
- Put(s"$collectionPath/$seqName?overwrite=true", updateContent) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/$seqName?overwrite=true", updateContent) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[ErrorResponse].error shouldBe Messages.sequenceNoComponent
}
@@ -106,7 +109,7 @@ class SequenceApiTests
val content = WhiskActionPut(Some(sequence(components)))
// create an action sequence
- Put(s"$collectionPath/${seqName.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${seqName.name}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[ErrorResponse].error shouldBe Messages.sequenceComponentNotFound
}
@@ -119,7 +122,7 @@ class SequenceApiTests
// create an action sequence
val content = WhiskActionPut(Some(sSeq.exec))
- Put(s"$collectionPath/$seqName", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/$seqName", content) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[ErrorResponse].error shouldBe Messages.sequenceIsCyclic
}
@@ -137,7 +140,7 @@ class SequenceApiTests
// create an action sequence
val content = WhiskActionPut(Some(sSeq.exec))
- Put(s"$collectionPath/$seqName", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/$seqName", content) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[ErrorResponse].error shouldBe Messages.sequenceIsCyclic
}
@@ -154,7 +157,7 @@ class SequenceApiTests
val content = WhiskActionPut(Some(sequence(components.toVector)))
// create a valid action sequence first
- Put(s"$collectionPath/${seqName.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${seqName.name}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
}
@@ -164,7 +167,7 @@ class SequenceApiTests
val updatedContent = WhiskActionPut(Some(sequence(updatedSeq.toVector)))
// update the sequence
- Put(s"$collectionPath/${seqName.name}?overwrite=true", updatedContent) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${seqName.name}?overwrite=true", updatedContent) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[ErrorResponse].error shouldBe Messages.sequenceIsCyclic
}
@@ -182,7 +185,7 @@ class SequenceApiTests
val content = WhiskActionPut(Some(sequence(components.toVector)))
// create an action sequence
- Put(s"$collectionPath/${seqName.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${seqName.name}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
}
}
@@ -212,7 +215,7 @@ class SequenceApiTests
val content = WhiskActionPut(Some(sequence(components)))
// create an action sequence
- Put(s"$collectionPath/${seqName.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${seqName.name}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[String]
}
@@ -235,7 +238,7 @@ class SequenceApiTests
// create an action sequence
val namespaceWithPkg = EntityPath(s"/$namespace/$pkg")
val content = WhiskActionPut(Some(sequence(components.toVector)))
- Put(s"$collectionPath/$pkg/${seqName.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/$pkg/${seqName.name}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
}
@@ -250,7 +253,7 @@ class SequenceApiTests
val updatedContent = WhiskActionPut(Some(sequence(updatedSeq.toVector)))
// update the sequence
- Put(s"$collectionPath/$pkg/${seqName.name}?overwrite=true", updatedContent) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/$pkg/${seqName.name}?overwrite=true", updatedContent) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[ErrorResponse].error shouldBe Messages.sequenceIsCyclic
}
@@ -260,7 +263,7 @@ class SequenceApiTests
implicit val tid = transid()
val content = JsObject("exec" -> JsObject("kind" -> Exec.SEQUENCE.toJson, "components" -> Vector("a", "b").toJson))
- Put(s"$collectionPath/${aname()}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${aname()}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
// the content will fail to deserialize on the route directive,
// and without a custom rejection, the response will be a string
@@ -273,7 +276,7 @@ class SequenceApiTests
val content = JsObject("exec" -> JsObject("kind" -> Exec.SEQUENCE.toJson, "components" -> Vector("a", "b").toJson))
// update an action sequence
- Put(s"$collectionPath/${aname()}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${aname()}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
// the content will fail to deserialize on the route directive,
// and without a custom rejection, the response will be a string
@@ -296,7 +299,7 @@ class SequenceApiTests
val content = WhiskActionPut(Some(sSeq.exec))
Console.withOut(stream) {
- Put(s"$collectionPath/$sSeqName", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/$sSeqName", content) ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
logContains(s"atomic action count ${2 * actionCnt}")(stream)
}
@@ -337,7 +340,7 @@ class SequenceApiTests
stream.reset()
Console.withOut(stream) {
- Put(s"$collectionPath/$sAct", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/$sAct", content) ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
}
logContains("atomic action count 4")(stream)
@@ -346,7 +349,7 @@ class SequenceApiTests
// update action z to point to s --- should be rejected
val zUpdate = makeSimpleSequence(zAct, namespace, Vector(s"$sAct"), false) // s in the db already
val zUpdateContent = WhiskActionPut(Some(zUpdate.exec))
- Put(s"$collectionPath/$zAct?overwrite=true", zUpdateContent) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/$zAct?overwrite=true", zUpdateContent) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[ErrorResponse].error shouldBe Messages.sequenceIsCyclic
}
@@ -354,7 +357,7 @@ class SequenceApiTests
// update action s to point to a, s, b --- should be rejected
val sUpdate = makeSimpleSequence(sAct, namespace, Vector(s"$aAct", s"$sAct", s"$bAct"), false) // s in the db already
val sUpdateContent = WhiskActionPut(Some(sUpdate.exec))
- Put(s"$collectionPath/$sAct?overwrite=true", sUpdateContent) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/$sAct?overwrite=true", sUpdateContent) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[ErrorResponse].error shouldBe Messages.sequenceIsCyclic
}
@@ -364,7 +367,7 @@ class SequenceApiTests
val updateContent = WhiskActionPut(Some(zSeq.exec))
stream.reset()
Console.withOut(stream) {
- Put(s"$collectionPath/$zAct?overwrite=true", updateContent) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/$zAct?overwrite=true", updateContent) ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
}
logContains("atomic action count 1")(stream)
@@ -374,7 +377,7 @@ class SequenceApiTests
val newSContent = WhiskActionPut(Some(newS.exec))
stream.reset()
Console.withOut(stream) {
- Put(s"${collectionPath}/$sAct?overwrite=true", newSContent) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"${collectionPath}/$sAct?overwrite=true", newSContent) ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
}
logContains("atomic action count 6")(stream)
diff --git a/tests/src/test/scala/whisk/core/controller/test/SwaggerRoutesTests.scala b/tests/src/test/scala/whisk/core/controller/test/SwaggerRoutesTests.scala
index 1eb341b..b63a818 100644
--- a/tests/src/test/scala/whisk/core/controller/test/SwaggerRoutesTests.scala
+++ b/tests/src/test/scala/whisk/core/controller/test/SwaggerRoutesTests.scala
@@ -21,11 +21,15 @@ import org.junit.runner.RunWith
import org.scalatest.BeforeAndAfterEach
import org.scalatest.junit.JUnitRunner
-import spray.http.StatusCodes._
-import spray.http.Uri
-import spray.httpx.SprayJsonSupport.sprayJsonUnmarshaller
+import akka.http.scaladsl.model.StatusCodes._
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
+//import akka.http.scaladsl.model.Uri.Query
+import akka.http.scaladsl.server.Route
+import akka.http.scaladsl.model.Uri
+
import spray.json._
import spray.json.DefaultJsonProtocol._
+
import whisk.core.controller.SwaggerDocs
/**
@@ -44,12 +48,12 @@ class SwaggerRoutesTests extends ControllerTestCommon with BeforeAndAfterEach {
it should "server docs" in {
implicit val tid = transid()
val swagger = new SwaggerDocs(Uri.Path.Empty, "infoswagger.json")
- Get("/docs") ~> sealRoute(swagger.swaggerRoutes) ~> check {
+ Get("/docs") ~> Route.seal(swagger.swaggerRoutes) ~> check {
status shouldBe PermanentRedirect
header("location").get.value shouldBe "docs/index.html?url=/api-docs"
}
- Get("/api-docs") ~> sealRoute(swagger.swaggerRoutes) ~> check {
+ Get("/api-docs") ~> Route.seal(swagger.swaggerRoutes) ~> check {
status shouldBe OK
responseAs[JsObject].fields("swagger") shouldBe JsString("2.0")
}
diff --git a/tests/src/test/scala/whisk/core/controller/test/TriggersApiTests.scala b/tests/src/test/scala/whisk/core/controller/test/TriggersApiTests.scala
index 5501f0d..26195ba 100644
--- a/tests/src/test/scala/whisk/core/controller/test/TriggersApiTests.scala
+++ b/tests/src/test/scala/whisk/core/controller/test/TriggersApiTests.scala
@@ -24,10 +24,14 @@ import scala.language.postfixOps
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
-import spray.http.StatusCodes._
-import spray.httpx.SprayJsonSupport._
+import akka.http.scaladsl.model.StatusCodes._
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
+import akka.http.scaladsl.server.Route
+import akka.http.scaladsl.model.StatusCodes._
+
import spray.json._
import spray.json.DefaultJsonProtocol._
+
import whisk.core.controller.WhiskTriggersApi
import whisk.core.entity._
import whisk.core.entity.WhiskRule
@@ -68,7 +72,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
}.toList
triggers foreach { put(entityStore, _) }
waitOnView(entityStore, WhiskTrigger, namespace, 2)
- Get(s"$collectionPath") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[JsObject]]
triggers.length should be(response.length)
@@ -76,7 +80,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
}
// it should "list triggers with explicit namespace owned by subject" in {
- Get(s"/$namespace/${collection.path}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"/$namespace/${collection.path}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[JsObject]]
triggers.length should be(response.length)
@@ -85,7 +89,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
// it should "reject list triggers with explicit namespace not owned by subject" in {
val auser = WhiskAuthHelpers.newIdentity()
- Get(s"/$namespace/${collection.path}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"/$namespace/${collection.path}") ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
}
@@ -98,7 +102,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
}.toList
triggers foreach { put(entityStore, _) }
waitOnView(entityStore, WhiskTrigger, namespace, 2)
- Get(s"$collectionPath?docs=true") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath?docs=true") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[WhiskTrigger]]
triggers.length should be(response.length)
@@ -111,14 +115,14 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
implicit val tid = transid()
val trigger = WhiskTrigger(namespace, aname, Parameters("x", "b"))
put(entityStore, trigger)
- Get(s"$collectionPath/${trigger.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${trigger.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskTrigger]
response should be(trigger.withoutRules)
}
// it should "get trigger by name in explicit namespace owned by subject" in
- Get(s"/$namespace/${collection.path}/${trigger.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"/$namespace/${collection.path}/${trigger.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskTrigger]
response should be(trigger.withoutRules)
@@ -126,7 +130,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
// it should "reject get trigger by name in explicit namespace not owned by subject" in
val auser = WhiskAuthHelpers.newIdentity()
- Get(s"/$namespace/${collection.path}/${trigger.name}") ~> sealRoute(routes(auser)) ~> check {
+ Get(s"/$namespace/${collection.path}/${trigger.name}") ~> Route.seal(routes(auser)) ~> check {
status should be(Forbidden)
}
}
@@ -135,7 +139,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
implicit val tid = transid()
val rule = WhiskRule(namespace, aname, FullyQualifiedEntityName(namespace, aname), FullyQualifiedEntityName(namespace, aname))
put(entityStore, rule)
- Get(s"/$namespace/${collection.path}/${rule.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"/$namespace/${collection.path}/${rule.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(Conflict)
}
}
@@ -145,7 +149,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
implicit val tid = transid()
val trigger = WhiskTrigger(namespace, aname, Parameters("x", "b"))
put(entityStore, trigger)
- Delete(s"$collectionPath/${trigger.name}") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${trigger.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskTrigger]
response should be(trigger.withoutRules)
@@ -157,7 +161,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
implicit val tid = transid()
val trigger = WhiskTrigger(namespace, aname)
val content = WhiskTriggerPut()
- Put(s"$collectionPath/${trigger.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${trigger.name}", content) ~> Route.seal(routes(creds)) ~> check {
deleteTrigger(trigger.docid)
status should be(OK)
val response = responseAs[WhiskTrigger]
@@ -169,7 +173,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
implicit val tid = transid()
val trigger = WhiskTrigger(namespace, aname, annotations = Parameters(Parameters.Feed, "xyz"))
val content = WhiskTriggerPut(annotations = Some(trigger.annotations))
- Put(s"$collectionPath/${trigger.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${trigger.name}", content) ~> Route.seal(routes(creds)) ~> check {
deleteTrigger(trigger.docid)
status should be(OK)
val response = responseAs[WhiskTrigger]
@@ -181,7 +185,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
implicit val tid = transid()
val trigger = WhiskTrigger(namespace, aname, annotations = Parameters(Parameters.Feed, ""))
val content = WhiskTriggerPut(annotations = Some(trigger.annotations))
- Put(s"$collectionPath/${trigger.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${trigger.name}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
}
}
@@ -190,7 +194,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
implicit val tid = transid()
val trigger = WhiskTrigger(namespace, aname, annotations = Parameters(Parameters.Feed, "a,b"))
val content = WhiskTriggerPut(annotations = Some(trigger.annotations))
- Put(s"$collectionPath/${trigger.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${trigger.name}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
}
}
@@ -199,10 +203,10 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
implicit val tid = transid()
val code = "a" * (allowedActivationEntitySize.toInt + 1)
val content = s"""{"a":"$code"}""".stripMargin
- Post(s"$collectionPath/${aname}", content.parseJson.asJsObject) ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${aname}", content.parseJson.asJsObject) ~> Route.seal(routes(creds)) ~> check {
status should be(RequestEntityTooLarge)
responseAs[String] should include {
- Messages.entityTooBig(SizeError(fieldDescriptionForSizeError, (content.length + 5).B, allowedActivationEntitySize.B))
+ Messages.entityTooBig(SizeError(fieldDescriptionForSizeError, (content.length).B, allowedActivationEntitySize.B))
}
}
}
@@ -214,7 +218,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
Parameters(key.toString, "a" * 10)
} reduce (_ ++ _)
val content = s"""{"parameters":$parameters}""".parseJson.asJsObject
- Put(s"$collectionPath/${aname}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${aname}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(RequestEntityTooLarge)
responseAs[String] should include {
Messages.entityTooBig(SizeError(WhiskEntity.paramsFieldName, parameters.size, Parameters.sizeLimit))
@@ -229,7 +233,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
Parameters(key.toString, "a" * 10)
} reduce (_ ++ _)
val content = s"""{"annotations":$annotations}""".parseJson.asJsObject
- Put(s"$collectionPath/${aname}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${aname}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(RequestEntityTooLarge)
responseAs[String] should include {
Messages.entityTooBig(SizeError(WhiskEntity.annotationsFieldName, annotations.size, Parameters.sizeLimit))
@@ -246,7 +250,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
} reduce (_ ++ _)
val content = s"""{"parameters":$parameters}""".parseJson.asJsObject
put(entityStore, trigger)
- Put(s"$collectionPath/${trigger.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${trigger.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
status should be(RequestEntityTooLarge)
responseAs[String] should include {
Messages.entityTooBig(SizeError(WhiskEntity.paramsFieldName, parameters.size, Parameters.sizeLimit))
@@ -259,7 +263,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
val trigger = WhiskTrigger(namespace, aname, Parameters("x", "b"))
val content = WhiskTriggerPut()
put(entityStore, trigger)
- Put(s"$collectionPath/${trigger.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${trigger.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
deleteTrigger(trigger.docid)
status should be(OK)
val response = responseAs[WhiskTrigger]
@@ -272,7 +276,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
val trigger = WhiskTrigger(namespace, aname, annotations = Parameters(Parameters.Feed, "xyz"))
val content = WhiskTriggerPut(annotations = Some(trigger.annotations))
put(entityStore, trigger)
- Put(s"$collectionPath/${trigger.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${trigger.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
}
}
@@ -282,7 +286,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
val trigger = WhiskTrigger(namespace, aname)
val content = WhiskTriggerPut(annotations = Some(Parameters(Parameters.Feed, "xyz")))
put(entityStore, trigger)
- Put(s"$collectionPath/${trigger.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${trigger.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
}
}
@@ -293,7 +297,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
val trigger = WhiskTrigger(namespace, aname, Parameters("x", "b"))
val content = JsObject("xxx" -> "yyy".toJson)
put(entityStore, trigger)
- Post(s"$collectionPath/${trigger.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${trigger.name}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[JsObject]
val JsString(id) = response.fields("activationId")
@@ -312,7 +316,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
implicit val tid = transid()
val trigger = WhiskTrigger(namespace, aname, Parameters("x", "b"))
put(entityStore, trigger)
- Post(s"$collectionPath/${trigger.name}") ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$collectionPath/${trigger.name}") ~> Route.seal(routes(creds)) ~> check {
val response = responseAs[JsObject]
val JsString(id) = response.fields("activationId")
val activationId = ActivationId(id)
@@ -326,7 +330,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
implicit val tid = transid()
val trigger = WhiskTrigger(namespace, aname)
put(entityStore, trigger)
- Get(s"$collectionPath/${trigger.name}/bar") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${trigger.name}/bar") ~> Route.seal(routes(creds)) ~> check {
status should be(NotFound)
}
}
@@ -336,7 +340,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
implicit val tid = transid()
val trigger = OldWhiskTrigger(namespace, aname)
put(entityStore, trigger)
- Get(s"$collectionPath/${trigger.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${trigger.name}") ~> Route.seal(routes(creds)) ~> check {
val response = responseAs[WhiskTrigger]
status should be(OK)
@@ -349,7 +353,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
val entity = BadEntity(namespace, aname)
put(entityStore, entity)
- Delete(s"$collectionPath/${entity.name}") ~> sealRoute(routes(creds)) ~> check {
+ Delete(s"$collectionPath/${entity.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(InternalServerError)
responseAs[ErrorResponse].error shouldBe Messages.corruptedEntity
}
@@ -360,7 +364,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
val entity = BadEntity(namespace, aname)
put(entityStore, entity)
- Get(s"$collectionPath/${entity.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${entity.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(InternalServerError)
responseAs[ErrorResponse].error shouldBe Messages.corruptedEntity
}
@@ -372,7 +376,7 @@ class TriggersApiTests extends ControllerTestCommon with WhiskTriggersApi {
put(entityStore, entity)
val content = WhiskTriggerPut()
- Put(s"$collectionPath/${entity.name}", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${entity.name}", content) ~> Route.seal(routes(creds)) ~> check {
status should be(InternalServerError)
responseAs[ErrorResponse].error shouldBe Messages.corruptedEntity
}
diff --git a/tests/src/test/scala/whisk/core/controller/test/WebActionsApiTests.scala b/tests/src/test/scala/whisk/core/controller/test/WebActionsApiTests.scala
index 3a7722a..d0b4f0a 100644
--- a/tests/src/test/scala/whisk/core/controller/test/WebActionsApiTests.scala
+++ b/tests/src/test/scala/whisk/core/controller/test/WebActionsApiTests.scala
@@ -29,19 +29,22 @@ import org.scalatest.junit.JUnitRunner
import org.scalatest.Matchers
import org.scalatest.FlatSpec
-import spray.http.FormData
-import spray.http.HttpEntity
-import spray.http.HttpMethods
-import spray.http.MediaTypes
-import spray.http.StatusCodes._
-import spray.http.HttpCharsets
-import spray.http.HttpHeader
-import spray.http.HttpHeaders
-import spray.http.HttpResponse
-import spray.http.Uri.Query
-import spray.httpx.SprayJsonSupport._
-import spray.httpx.SprayJsonSupport.sprayJsonMarshaller
-import spray.httpx.SprayJsonSupport.sprayJsonUnmarshaller
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
+
+import akka.http.scaladsl.model.FormData
+import akka.http.scaladsl.model.HttpEntity
+import akka.http.scaladsl.model.MediaTypes
+import akka.http.scaladsl.model.StatusCodes._
+import akka.http.scaladsl.model.HttpCharsets
+import akka.http.scaladsl.model.HttpHeader
+import akka.http.scaladsl.model.HttpResponse
+import akka.http.scaladsl.model.Uri.Query
+import akka.http.scaladsl.server.Route
+import akka.http.scaladsl.model.HttpMethods
+import akka.http.scaladsl.model.headers.`Content-Type`
+import akka.http.scaladsl.model.ContentTypes
+import akka.http.scaladsl.model.headers.RawHeader
+
import spray.json._
import spray.json.DefaultJsonProtocol._
@@ -178,12 +181,16 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
assert(invocationsAllowed == invocationCount, "allowed invoke count did not match actual")
}
- val allowedMethods = {
- val nonModifierMethods = Seq(Get, Options, Head)
+ val allowedMethodsWithEntity = {
+ val nonModifierMethods = Seq(Get, Options)
val modifierMethods = Seq(Post, Put, Delete, Patch)
modifierMethods ++ nonModifierMethods
}
+ val allowedMethods = {
+ allowedMethodsWithEntity ++ Seq(Head)
+ }
+
// there is only one package that is predefined 'proxy'
val packages = Seq(
WhiskPackage(
@@ -349,7 +356,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
Seq("a", "a/b", "/a", s"$systemId/c", s"$systemId/export_c").
foreach { path =>
allowedMethods.foreach { m =>
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(NotFound)
}
}
@@ -366,7 +373,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
Seq((???, MethodNotAllowed)).
foreach {
case (m, code) =>
- m(s"$testRoutePath/$systemId/proxy/export_c.json") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$systemId/proxy/export_c.json") ~> Route.seal(routes(creds)) ~> check {
status should be(code)
}
}
@@ -386,11 +393,11 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
allowedMethods.foreach { m =>
failActionLookup = path.endsWith("fail")
- m(s"$testRoutePath/${path}.json") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/${path}.json") ~> Route.seal(routes(creds)) ~> check {
status should be(NotFound)
}
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
if (webApiDirectives.enforceExtension) {
status should be(NotAcceptable)
confirmErrorWithTid(responseAs[JsObject], Some(Messages.contentTypeExtensionNotSupported(WhiskWebActionsApi.allowedExtensions)))
@@ -412,7 +419,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
invocationsAllowed += 1
requireAuthentication = true
- m(s"$testRoutePath/${path}.json") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/${path}.json") ~> Route.seal(routes(creds)) ~> check {
creds match {
case None => status should be(Unauthorized)
case Some(user) =>
@@ -436,7 +443,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
allowedMethods.foreach { m =>
invocationsAllowed += 1
- m(s"$testRoutePath/$systemId/proxy/export_c.json") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$systemId/proxy/export_c.json") ~> Route.seal(routes(creds)) ~> check {
status should be(Accepted)
val response = responseAs[JsObject]
confirmErrorWithTid(response, Some("Response not yet ready."))
@@ -451,7 +458,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
allowedMethods.foreach { m =>
invocationsAllowed += 1
- m(s"$testRoutePath/$systemId/proxy/export_c.json") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$systemId/proxy/export_c.json") ~> Route.seal(routes(creds)) ~> check {
status should be(InternalServerError)
val response = responseAs[JsObject]
confirmErrorWithTid(response)
@@ -467,7 +474,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
allowedMethods.foreach { m =>
invocationsAllowed += 1
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[JsObject]
response shouldBe JsObject(
@@ -489,11 +496,11 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
// both of these should produce full result objects (trailing slash is ok)
Seq(s"$systemId/proxy/export_c.json", s"$systemId/proxy/export_c.json/").
foreach { path =>
- allowedMethods.foreach { m =>
+ allowedMethodsWithEntity.foreach { m =>
val content = JsObject("extra" -> "read all about it".toJson, "yummy" -> true.toJson)
val p = if (path.endsWith("/")) "/" else ""
invocationsAllowed += 1
- m(s"$testRoutePath/$path", content) ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path", content) ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[JsObject]
response shouldBe JsObject(
@@ -516,11 +523,11 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
Seq(s"$systemId/proxy/export_c.json?a=b&c=d").
foreach { path =>
- allowedMethods.foreach { m =>
+ allowedMethodsWithEntity.foreach { m =>
val content = JsObject("extra" -> "read all about it".toJson, "yummy" -> true.toJson)
invocationsAllowed += 1
- m(s"$testRoutePath/$path", content) ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path", content) ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[JsObject]
response shouldBe JsObject(
@@ -545,7 +552,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
allowedMethods.foreach { m =>
invocationsAllowed += 1
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[JsObject]
response shouldBe JsObject(
@@ -565,7 +572,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
allowedMethods.foreach { m =>
invocationsAllowed += 1
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[JsObject]
response shouldBe metaPayload(m.method.name.toLowerCase, JsObject(), creds, path = "/content", pkgName = "proxy")
@@ -578,7 +585,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
allowedMethods.foreach { m =>
invocationsAllowed += 1
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[String]
response shouldBe "Z"
@@ -597,7 +604,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
invocationsAllowed += 1
actionResult = Some(JsObject("a" -> JsString("b")))
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
confirmErrorWithTid(responseAs[JsObject], Some(Messages.invalidMedia(MediaTypes.`application/json`)))
}
@@ -613,7 +620,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
allowedMethods.foreach { m =>
invocationsAllowed += 1
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(NotFound)
confirmErrorWithTid(responseAs[JsObject], Some(Messages.propertyNotFound))
}
@@ -631,7 +638,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
actionResult = Some(JsObject("headers" -> JsObject("location" -> "http://openwhisk.org".toJson), webApiDirectives.statusCode -> Found.intValue.toJson))
invocationsAllowed += 1
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(Found)
header("location").get.toString shouldBe "location: http://openwhisk.org"
}
@@ -648,7 +655,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
invocationsAllowed += 1
actionResult = Some(JsObject("headers" -> JsObject("location" -> "http://openwhisk.org".toJson), webApiDirectives.statusCode -> Found.intValue.toJson))
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(Found)
header("location").get.toString shouldBe "location: http://openwhisk.org"
}
@@ -662,7 +669,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
invocationsAllowed += 1
actionResult = Some(JsObject("text" -> JsString(text)))
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
contentType shouldBe MediaTypes.`text/plain`.withCharset(HttpCharsets.`UTF-8`)
val response = responseAs[String]
@@ -677,7 +684,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
invocationsAllowed += 1
actionResult = Some(JsObject("foobar" -> JsString("foobar")))
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[JsObject]
response shouldBe actionResult.get
@@ -692,7 +699,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
invocationsAllowed += 1
actionResult = Some(JsObject("html" -> JsString(html)))
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
contentType shouldBe MediaTypes.`text/html`.withCharset(HttpCharsets.`UTF-8`)
val response = responseAs[String]
@@ -708,9 +715,9 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
invocationsAllowed += 1
actionResult = Some(JsObject("svg" -> JsString(svg)))
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
- contentType shouldBe MediaTypes.`image/svg+xml`.withCharset(HttpCharsets.`UTF-8`)
+ //contentType shouldBe MediaTypes.`image/svg+xml`.withCharset(HttpCharsets.`UTF-8`)
val response = responseAs[String]
response shouldBe svg
}
@@ -727,7 +734,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
invocationsAllowed += 1
actionResult = Some(JsObject())
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
response.entity shouldBe HttpEntity.Empty
withClue(headers) {
@@ -748,7 +755,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
invocationsAllowed += 1
actionResult = Some(JsObject("res" -> jsval))
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
responseAs[String] shouldBe {
jsval match {
case _: JsObject => jsval.prettyPrint
@@ -779,7 +786,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
JsObject("field" -> "value".toJson).compactPrint.getBytes
}.toJson))
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
header("content-type").get.toString shouldBe "content-type: application/json"
responseAs[JsObject] shouldBe JsObject("field" -> "value".toJson)
@@ -799,7 +806,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
webApiDirectives.statusCode -> OK.intValue.toJson,
"body" -> "hello world".toJson))
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
responseAs[String] shouldBe "hello world"
}
@@ -820,7 +827,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
webApiDirectives.statusCode -> OK.intValue.toJson,
"body" -> "hello world".toJson))
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
confirmErrorWithTid(responseAs[JsObject], Some(Messages.httpContentTypeError))
}
@@ -841,7 +848,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
webApiDirectives.statusCode -> OK.intValue.toJson,
"body" -> "hello world".toJson))
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
confirmErrorWithTid(responseAs[JsObject], Some(Messages.httpUnknownContentType))
}
@@ -861,7 +868,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
webApiDirectives.statusCode -> OK.intValue.toJson,
"body" -> "no hello for you".toJson)))
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
responseAs[String] shouldBe "no hello for you"
}
@@ -878,7 +885,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
invocationsAllowed += 1
actionResult = Some(JsObject("application_error" -> "bad response type".toJson))
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
confirmErrorWithTid(responseAs[JsObject], Some(Messages.invalidMedia(MediaTypes.`application/json`)))
}
@@ -896,7 +903,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
invocationsAllowed += 1
actionResult = Some(JsObject(e -> "bad response type".toJson))
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
if (e == "application_error") {
confirmErrorWithTid(responseAs[JsObject], Some(Messages.invalidMedia(MediaTypes.`application/json`)))
@@ -914,10 +921,11 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
Seq(s"$systemId/proxy/export_c.text/content/field1", s"$systemId/proxy/export_c.text/content/field2").
foreach { path =>
- val form = FormData(Seq("field1" -> "value1", "field2" -> "value2"))
+
+ val form = FormData(Map("field1" -> "value1", "field2" -> "value2"))
invocationsAllowed += 1
- Post(s"$testRoutePath/$path", form) ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$testRoutePath/$path", form) ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
responseAs[String] should (be("value1") or be("value2"))
}
@@ -932,17 +940,17 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
val largeEntity = "a" * (allowedActivationEntitySize.toInt + 1)
val content = s"""{"a":"$largeEntity"}"""
- Post(s"$testRoutePath/$path", content.parseJson.asJsObject) ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$testRoutePath/$path", content.parseJson.asJsObject) ~> Route.seal(routes(creds)) ~> check {
status should be(RequestEntityTooLarge)
val expectedErrorMsg = Messages.entityTooBig(SizeError(
fieldDescriptionForSizeError,
- (largeEntity.length + 13).B,
+ (largeEntity.length + 8).B,
allowedActivationEntitySize.B))
confirmErrorWithTid(responseAs[JsObject], Some(expectedErrorMsg))
}
- val form = FormData(Seq("a" -> largeEntity))
- Post(s"$testRoutePath/$path", form) ~> sealRoute(routes(creds)) ~> check {
+ val form = FormData(Map("a" -> largeEntity))
+ Post(s"$testRoutePath/$path", form) ~> Route.seal(routes(creds)) ~> check {
status should be(RequestEntityTooLarge)
val expectedErrorMsg = Messages.entityTooBig(SizeError(
fieldDescriptionForSizeError,
@@ -962,7 +970,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
allowedMethods.foreach { m =>
actionResult = Some(JsObject("statusCode" -> 201.toJson))
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
if (webApiDirectives.enforceExtension) {
status should be(NotAcceptable)
confirmErrorWithTid(responseAs[JsObject], Some(Messages.contentTypeExtensionNotSupported(WhiskWebActionsApi.allowedExtensions)))
@@ -978,14 +986,14 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
it should s"reject request that tries to override reserved properties (auth? ${creds.isDefined})" in {
implicit val tid = transid()
- allowedMethods.foreach { m =>
+ allowedMethodsWithEntity.foreach { m =>
webApiDirectives.reservedProperties.foreach { p =>
- m(s"$testRoutePath/$systemId/proxy/export_c.json?$p=YYY") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$systemId/proxy/export_c.json?$p=YYY") ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[ErrorResponse].error shouldBe Messages.parametersNotAllowed
}
- m(s"$testRoutePath/$systemId/proxy/export_c.json", JsObject(p -> "YYY".toJson)) ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$systemId/proxy/export_c.json", JsObject(p -> "YYY".toJson)) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[ErrorResponse].error shouldBe Messages.parametersNotAllowed
}
@@ -998,30 +1006,30 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
val contentX = JsObject("x" -> "overriden".toJson)
val contentZ = JsObject("z" -> "overriden".toJson)
- allowedMethods.foreach { m =>
+ allowedMethodsWithEntity.foreach { m =>
invocationsAllowed += 1
- m(s"$testRoutePath/$systemId/proxy/export_c.json?x=overriden") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$systemId/proxy/export_c.json?x=overriden") ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[ErrorResponse].error shouldBe Messages.parametersNotAllowed
}
- m(s"$testRoutePath/$systemId/proxy/export_c.json?y=overriden") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$systemId/proxy/export_c.json?y=overriden") ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[ErrorResponse].error shouldBe Messages.parametersNotAllowed
}
- m(s"$testRoutePath/$systemId/proxy/export_c.json", contentX) ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$systemId/proxy/export_c.json", contentX) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[ErrorResponse].error shouldBe Messages.parametersNotAllowed
}
- m(s"$testRoutePath/$systemId/proxy/export_c.json?y=overriden", contentZ) ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$systemId/proxy/export_c.json?y=overriden", contentZ) ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
responseAs[ErrorResponse].error shouldBe Messages.parametersNotAllowed
}
- m(s"$testRoutePath/$systemId/proxy/export_c.json?empty=overriden") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$systemId/proxy/export_c.json?empty=overriden") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[JsObject]
response shouldBe JsObject(
@@ -1044,15 +1052,15 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
/*
* Now supporting all content types with inlined "body".
*
- Post(s"$testRoutePath/$systemId/proxy/export_c.json?a=b&c=d", "1,2,3") ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$testRoutePath/$systemId/proxy/export_c.json?a=b&c=d", "1,2,3") ~> Route.seal(routes(creds)) ~> check {
status should be(BadRequest)
confirmErrorWithTid(responseAs[JsObject], Some(Messages.contentTypeNotSupported))
}
*
*/
- Post(s"$testRoutePath/$systemId/proxy/export_c.json", str) ~> addHeader("Content-type", MediaTypes.`text/html`.value) ~> sealRoute(routes(creds)) ~> check {
- //status should be(OK)
+ Post(s"$testRoutePath/$systemId/proxy/export_c.json", str) ~> addHeader("Content-type", ContentTypes.`text/html(UTF-8)`.value) ~> Route.seal(routes(creds)) ~> check {
+ status should be(OK)
val response = responseAs[JsObject]
response shouldBe JsObject(
"pkg" -> s"$systemId/proxy".toJson,
@@ -1062,10 +1070,10 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
JsObject(webApiDirectives.body -> str.toJson),
creds,
pkgName = "proxy",
- headers = List(HttpHeaders.`Content-Type`(MediaTypes.`text/html`))))
+ headers = List(`Content-Type`(ContentTypes.`text/html(UTF-8)`))))
}
- Post(s"$testRoutePath/$systemId/proxy/export_c.json?a=b&c=d") ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$testRoutePath/$systemId/proxy/export_c.json?a=b&c=d") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[JsObject]
response shouldBe JsObject(
@@ -1078,7 +1086,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
pkgName = "proxy"))
}
- Post(s"$testRoutePath/$systemId/proxy/export_c.json?a=b&c=d", JsObject()) ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$testRoutePath/$systemId/proxy/export_c.json?a=b&c=d", JsObject()) ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[JsObject]
response shouldBe JsObject(
@@ -1100,7 +1108,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
foreach { path =>
allowedMethods.foreach { m =>
failThrottleForSubject = Some(systemId)
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
status should be(TooManyRequests)
confirmErrorWithTid(responseAs[JsObject], Some(Messages.tooManyRequests))
}
@@ -1120,7 +1128,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
"headers" -> JsObject(
"Access-Control-Allow-Methods" -> "OPTIONS, GET, PATCH".toJson)))
- Options(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ Options(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
header("Access-Control-Allow-Origin") shouldBe None
header("Access-Control-Allow-Methods").get.toString shouldBe "Access-Control-Allow-Methods: OPTIONS, GET, PATCH"
}
@@ -1138,10 +1146,10 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
"headers" -> JsObject(
"Set-Cookie" -> JsArray(JsString("a=b"), JsString("c=d; Path = /")))))
- Options(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ Options(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
headers should contain allOf (
- HttpHeaders.RawHeader("Set-Cookie", "a=b"),
- HttpHeaders.RawHeader("Set-Cookie", "c=d; Path = /")
+ RawHeader("Set-Cookie", "a=b"),
+ RawHeader("Set-Cookie", "c=d; Path = /")
)
}
}
@@ -1155,7 +1163,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
foreach { path =>
allowedMethods.foreach { m =>
invocationsAllowed += 1
- m(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ m(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
header("Access-Control-Allow-Origin").get.toString shouldBe "Access-Control-Allow-Origin: *"
header("Access-Control-Allow-Methods").get.toString shouldBe "Access-Control-Allow-Methods: OPTIONS, GET, DELETE, POST, PUT, HEAD, PATCH"
header("Access-Control-Allow-Headers").get.toString shouldBe "Access-Control-Allow-Headers: Authorization, Content-Type"
@@ -1177,7 +1185,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
"headers" -> JsObject(
"location" -> "http://openwhisk.org".toJson)))
- Head(s"$testRoutePath/$path") ~> sealRoute(routes(creds)) ~> check {
+ Head(s"$testRoutePath/$path") ~> Route.seal(routes(creds)) ~> check {
header("location").get.toString shouldBe "location: http://openwhisk.org"
}
}
@@ -1198,7 +1206,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
case (res, expectedMediaType) =>
actionResult = Some(JsObject("html" -> res.toJson))
- Get(s"$testRoutePath/$path") ~> addHeader("Accept", expectedMediaType.value) ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$testRoutePath/$path") ~> addHeader("Accept", expectedMediaType.value) ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
responseAs[String] shouldBe res
mediaType shouldBe expectedMediaType
@@ -1212,7 +1220,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
invocationsAllowed = 2
val queryString = "x=overriden&key2=value2"
- Post(s"$testRoutePath/$systemId/proxy/raw_export_c.json?$queryString") ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$testRoutePath/$systemId/proxy/raw_export_c.json?$queryString") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[JsObject]
response shouldBe JsObject(
@@ -1226,7 +1234,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
pkgName = "proxy"))
}
- Post(s"$testRoutePath/$systemId/proxy/raw_export_c.json", JsObject("x" -> "overriden".toJson, "key2" -> "value2".toJson)) ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$testRoutePath/$systemId/proxy/raw_export_c.json", JsObject("x" -> "overriden".toJson, "key2" -> "value2".toJson)) ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[JsObject]
response shouldBe JsObject(
@@ -1236,12 +1244,11 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
Post.method.name.toLowerCase,
Map(webApiDirectives.query -> "".toJson,
webApiDirectives.body -> Base64.getEncoder.encodeToString {
- JsObject("x" -> JsString("overriden"), "key2" -> JsString("value2")).prettyPrint.getBytes
+ JsObject("x" -> JsString("overriden"), "key2" -> JsString("value2")).compactPrint.getBytes
}.toJson).toJson.asJsObject,
creds,
pkgName = "proxy"))
}
-
}
it should s"invoke raw action ensuring body and query arguments are set properly (auth? ${creds.isDefined})" in {
@@ -1250,7 +1257,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
invocationsAllowed = 1
val queryString = "key1=value1&key2=value2"
- Post(s"$testRoutePath/$systemId/proxy/raw_export_c.json?$queryString", str) ~> addHeader("Content-type", MediaTypes.`application/json`.value) ~> sealRoute(routes(creds)) ~> check {
+ Post(s"$testRoutePath/$systemId/proxy/raw_export_c.json?$queryString", str) ~> addHeader("Content-type", MediaTypes.`application/json`.value) ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[JsObject]
response shouldBe JsObject(
@@ -1262,7 +1269,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
webApiDirectives.query -> queryString.toJson).toJson.asJsObject,
creds,
pkgName = "proxy",
- headers = List(HttpHeaders.`Content-Type`(MediaTypes.`application/json`))))
+ headers = List(`Content-Type`(ContentTypes.`application/json`))))
}
}
@@ -1274,9 +1281,9 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
actionResult = Some(JsObject("body" -> "Plain text".toJson))
invocationsAllowed += 1
- Get(s"$testRoutePath/$path") ~> addHeader("Accept", "application/json") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$testRoutePath/$path") ~> addHeader("Accept", "application/json") ~> Route.seal(routes(creds)) ~> check {
status should be(NotAcceptable)
- response shouldBe HttpResponse(NotAcceptable, "Resource representation is only available with these Content-Types:\ntext/html")
+ response shouldBe HttpResponse(NotAcceptable, entity = "Resource representation is only available with these types:\ntext/html")
}
}
}
@@ -1291,7 +1298,7 @@ trait WebActionsApiTests extends ControllerTestCommon with BeforeAndAfterEach wi
invocationsAllowed += 1
actionResult = Some(JsObject("html" -> xml.toJson))
- Get(s"$testRoutePath/$path") ~> addHeader("Accept", MediaTypes.`text/xml`.value) ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$testRoutePath/$path") ~> addHeader("Accept", MediaTypes.`text/xml`.value) ~> Route.seal(routes(creds)) ~> check {
status should be(NotAcceptable)
}
}
diff --git a/tests/src/test/scala/whisk/core/controller/test/migration/SequenceActionApiMigrationTests.scala b/tests/src/test/scala/whisk/core/controller/test/migration/SequenceActionApiMigrationTests.scala
index 6624fba..1689af1 100644
--- a/tests/src/test/scala/whisk/core/controller/test/migration/SequenceActionApiMigrationTests.scala
+++ b/tests/src/test/scala/whisk/core/controller/test/migration/SequenceActionApiMigrationTests.scala
@@ -24,10 +24,14 @@ import org.scalatest.junit.JUnitRunner
import common.TestHelpers
import common.WskTestHelpers
-import spray.http.StatusCodes.OK
-import spray.httpx.SprayJsonSupport._
+
+import akka.http.scaladsl.server.Route
+import akka.http.scaladsl.model.StatusCodes.OK
+import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
+
import spray.json.DefaultJsonProtocol._
import spray.json._
+
import whisk.core.controller.WhiskActionsApi
import whisk.core.controller.test.ControllerTestCommon
import whisk.core.controller.test.WhiskAuthHelpers
@@ -59,7 +63,7 @@ class SequenceActionApiMigrationTests extends ControllerTestCommon
}.toList
actions foreach { put(entityStore, _) }
waitOnView(entityStore, WhiskAction, namespace, 2)
- Get(s"/$namespace/${collection.path}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"/$namespace/${collection.path}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[List[JsObject]]
@@ -73,7 +77,7 @@ class SequenceActionApiMigrationTests extends ControllerTestCommon
val components = Vector("/_/a", "/_/x/b", "/n/a", "/n/x/c").map(stringToFullyQualifiedName(_))
val action = WhiskAction(namespace, aname, sequence(components))
put(entityStore, action)
- Get(s"$collectionPath/${action.name}") ~> sealRoute(routes(creds)) ~> check {
+ Get(s"$collectionPath/${action.name}") ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskAction]
response should be(action)
@@ -90,7 +94,7 @@ class SequenceActionApiMigrationTests extends ControllerTestCommon
put(entityStore, action, false)
// create an action sequence
- Put(s"$collectionPath/${action.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${action.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
deleteAction(action.docid)
status should be(OK)
val response = responseAs[WhiskAction]
@@ -109,7 +113,7 @@ class SequenceActionApiMigrationTests extends ControllerTestCommon
put(entityStore, action, false)
// create an action sequence
- Put(s"$collectionPath/${action.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${action.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
deleteAction(action.docid)
status should be(OK)
val response = responseAs[WhiskAction]
@@ -127,7 +131,7 @@ class SequenceActionApiMigrationTests extends ControllerTestCommon
put(entityStore, action, false)
// create an action sequence
- Put(s"$collectionPath/${action.name}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${action.name}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
deleteAction(action.docid)
status should be(OK)
val response = responseAs[String]
@@ -159,7 +163,7 @@ class SequenceActionApiMigrationTests extends ControllerTestCommon
val content = WhiskActionPut(Some(seqAction.exec), Some(Parameters()))
// update an action sequence
- Put(s"$collectionPath/${seqName}?overwrite=true", content) ~> sealRoute(routes(creds)) ~> check {
+ Put(s"$collectionPath/${seqName}?overwrite=true", content) ~> Route.seal(routes(creds)) ~> check {
status should be(OK)
val response = responseAs[WhiskAction]
response.exec.kind should be(Exec.SEQUENCE)
--
To stop receiving notification emails like this one, please contact
['"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>'].