Skip to content

Commit 8578887

Browse files
bdoyle0182Brendan Doyle
andauthored
Add cors headers to components' server admin routes (#5351)
* add container pool state route to invoker * scalafmt * wip * add cors headers to components server admin routes * scalafmt * fix bad merge Co-authored-by: Brendan Doyle <[email protected]>
1 parent 44791f3 commit 8578887

File tree

8 files changed

+109
-73
lines changed

8 files changed

+109
-73
lines changed
Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,20 @@
1515
* limitations under the License.
1616
*/
1717

18-
package org.apache.openwhisk.core.controller
18+
package org.apache.openwhisk.http
1919

20-
import akka.http.scaladsl.model.headers._
21-
import akka.http.scaladsl.model.HttpMethods.{DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT}
20+
import akka.http.scaladsl.model.HttpMethods._
21+
import akka.http.scaladsl.model.headers.{
22+
`Access-Control-Allow-Headers`,
23+
`Access-Control-Allow-Methods`,
24+
`Access-Control-Allow-Origin`
25+
}
26+
import akka.http.scaladsl.server.Directives
2227

2328
/**
2429
* Defines the CORS settings for the REST APIs and Web Actions.
2530
*/
26-
protected[controller] object CorsSettings {
31+
object CorsSettings {
2732

2833
trait RestAPIs {
2934
val allowOrigin = Defaults.allowOrigin
@@ -38,6 +43,16 @@ protected[controller] object CorsSettings {
3843
val allowMethods = `Access-Control-Allow-Methods`(OPTIONS, GET, DELETE, POST, PUT, HEAD, PATCH)
3944
}
4045

46+
object ServerAPIs {
47+
val allowOrigin = Defaults.allowOrigin
48+
val allowHeaders = Defaults.allowHeaders
49+
val allowMethods = `Access-Control-Allow-Methods`(OPTIONS, GET, POST)
50+
}
51+
52+
trait RespondWithServerCorsHeaders extends Directives {
53+
val sendCorsHeaders = respondWithHeaders(ServerAPIs.allowOrigin, ServerAPIs.allowHeaders, ServerAPIs.allowMethods)
54+
}
55+
4156
object Defaults {
4257
val allowOrigin = `Access-Control-Allow-Origin`.*
4358

core/controller/src/main/scala/org/apache/openwhisk/core/controller/Controller.scala

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import org.apache.openwhisk.core.entity.ActivationId.ActivationIdGenerator
3737
import org.apache.openwhisk.core.entity.ExecManifest.Runtimes
3838
import org.apache.openwhisk.core.entity._
3939
import org.apache.openwhisk.core.loadBalancer.LoadBalancerProvider
40+
import org.apache.openwhisk.http.CorsSettings.RespondWithServerCorsHeaders
4041
import org.apache.openwhisk.http.ErrorResponse.terminate
4142
import org.apache.openwhisk.http.{BasicHttpService, BasicRasService}
4243
import org.apache.openwhisk.spi.SpiLoader
@@ -78,7 +79,8 @@ class Controller(val instance: ControllerInstanceId,
7879
implicit val whiskConfig: WhiskConfig,
7980
implicit val actorSystem: ActorSystem,
8081
implicit val logging: Logging)
81-
extends BasicRasService {
82+
extends BasicRasService
83+
with RespondWithServerCorsHeaders {
8284

8385
TransactionId.controller.mark(
8486
this,
@@ -98,7 +100,7 @@ class Controller(val instance: ControllerInstanceId,
98100
(pathEndOrSingleSlash & get) {
99101
complete(info)
100102
}
101-
} ~ apiV1.routes ~ swagger.swaggerRoutes ~ internalInvokerHealth ~ activationStatus ~ disable
103+
} ~ apiV1.routes ~ swagger.swaggerRoutes ~ adminRoutes
102104
}
103105

104106
// initialize datastores
@@ -217,6 +219,14 @@ class Controller(val instance: ControllerInstanceId,
217219
}
218220
}
219221
}
222+
223+
private def adminRoutes(implicit transid: TransactionId) = {
224+
sendCorsHeaders {
225+
options {
226+
complete(OK)
227+
} ~ internalInvokerHealth ~ activationStatus ~ disable
228+
}
229+
}
220230
}
221231

222232
/**

core/controller/src/main/scala/org/apache/openwhisk/core/controller/RestAPIs.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import org.apache.openwhisk.core.entity._
3636
import org.apache.openwhisk.core.entity.types._
3737
import org.apache.openwhisk.core.loadBalancer.LoadBalancer
3838
import org.apache.openwhisk.core.{ConfigKeys, WhiskConfig}
39-
import org.apache.openwhisk.http.Messages
39+
import org.apache.openwhisk.http.{CorsSettings, Messages}
4040
import org.apache.openwhisk.spi.{Spi, SpiLoader}
4141

4242
import scala.concurrent.{ExecutionContext, Future}

core/controller/src/main/scala/org/apache/openwhisk/core/controller/WebActions.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
package org.apache.openwhisk.core.controller
1919

2020
import java.util.Base64
21-
2221
import scala.concurrent.Future
2322
import scala.util.{Failure, Success, Try}
2423
import akka.http.scaladsl.model.HttpEntity.Empty
@@ -56,7 +55,7 @@ import org.apache.openwhisk.core.entity._
5655
import org.apache.openwhisk.core.entity.types._
5756
import org.apache.openwhisk.core.loadBalancer.LoadBalancerException
5857
import org.apache.openwhisk.http.ErrorResponse.terminate
59-
import org.apache.openwhisk.http.Messages
58+
import org.apache.openwhisk.http.{CorsSettings, Messages}
6059
import org.apache.openwhisk.http.LenientSprayJsonSupport._
6160
import org.apache.openwhisk.spi.SpiLoader
6261
import org.apache.openwhisk.utils.JsHelpers._

core/invoker/src/main/scala/org/apache/openwhisk/core/containerpool/v2/FunctionPullingContainerPool.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@ case class TotalContainerPoolState(totalContainers: Int,
6565
prewarmedPool: PrewarmedContainerPoolState,
6666
busyPool: WarmContainerPoolState,
6767
pausedPool: WarmContainerPoolState) {
68-
6968
def serialize(): String = TotalContainerPoolState.totalPoolSerdes.write(this).compactPrint
7069
}
7170

@@ -436,15 +435,13 @@ class FunctionPullingContainerPool(
436435
// Reset the prewarmCreateCount value when do expiration check and backfill prewarm if possible
437436
prewarmCreateFailedCount.set(0)
438437
adjustPrewarmedContainer(false, true)
439-
440438
case GetState =>
441439
val totalContainers = busyPool.size + inProgressPool.size + warmedPool.size + prewarmedPool.size
442440
val prewarmedState =
443441
PrewarmedContainerPoolState(prewarmedPool.size, prewarmedPool.groupBy(_._2.kind).mapValues(_.size).toMap)
444442
val busyState = WarmContainerPoolState(busyPool.size, busyPool.values.map(_.basicContainerInfo).toList)
445443
val pausedState = WarmContainerPoolState(warmedPool.size, warmedPool.values.map(_.basicContainerInfo).toList)
446444
sender() ! TotalContainerPoolState(totalContainers, inProgressPool.size, prewarmedState, busyState, pausedState)
447-
448445
}
449446

450447
/** Install prewarm containers up to the configured requirements for each kind/memory combination or specified kind/memory */

core/invoker/src/main/scala/org/apache/openwhisk/core/invoker/FPCInvokerServer.scala

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,13 @@ package org.apache.openwhisk.core.invoker
1919

2020
import akka.actor.ActorSystem
2121
import akka.http.scaladsl.model.StatusCodes
22+
import akka.http.scaladsl.model.StatusCodes.OK
2223
import akka.http.scaladsl.model.headers.BasicHttpCredentials
2324
import akka.http.scaladsl.server.Route
2425
import org.apache.openwhisk.common.{Logging, TransactionId}
2526
import org.apache.openwhisk.core.ConfigKeys
2627
import org.apache.openwhisk.http.BasicRasService
28+
import org.apache.openwhisk.http.CorsSettings.RespondWithServerCorsHeaders
2729
import org.apache.openwhisk.http.ErrorResponse.terminate
2830
import pureconfig.loadConfigOrThrow
2931
import spray.json.PrettyPrinter
@@ -39,42 +41,48 @@ class FPCInvokerServer(val invoker: InvokerCore, systemUsername: String, systemP
3941
implicit val ec: ExecutionContext,
4042
val actorSystem: ActorSystem,
4143
val logger: Logging)
42-
extends BasicRasService {
44+
extends BasicRasService
45+
with RespondWithServerCorsHeaders {
4346

4447
/** Pretty print JSON response. */
4548
implicit val jsonPrettyResponsePrinter = PrettyPrinter
4649

4750
override def routes(implicit transid: TransactionId): Route = {
48-
super.routes ~ extractCredentials {
49-
case Some(BasicHttpCredentials(username, password)) if username == systemUsername && password == systemPassword =>
50-
(path("enable") & post) {
51-
complete(invoker.enable())
52-
} ~ (path("disable") & post) {
53-
complete(invoker.disable())
54-
} ~ (path("isEnabled") & get) {
55-
complete(invoker.isEnabled())
56-
} ~ (pathPrefix("pool") & get) {
57-
pathEndOrSingleSlash {
58-
complete {
59-
invoker.getPoolState().map {
60-
case Right(poolState) =>
61-
poolState.serialize()
62-
case Left(value) =>
63-
value.serialize()
51+
super.routes ~ sendCorsHeaders {
52+
options {
53+
complete(OK)
54+
} ~ extractCredentials {
55+
case Some(BasicHttpCredentials(username, password))
56+
if username == systemUsername && password == systemPassword =>
57+
(path("enable") & post) {
58+
complete(invoker.enable())
59+
} ~ (path("disable") & post) {
60+
complete(invoker.disable())
61+
} ~ (path("isEnabled") & get) {
62+
complete(invoker.isEnabled())
63+
} ~ (pathPrefix("pool") & get) {
64+
pathEndOrSingleSlash {
65+
complete {
66+
invoker.getPoolState().map {
67+
case Right(poolState) =>
68+
poolState.serialize()
69+
case Left(value) =>
70+
value.serialize()
71+
}
6472
}
65-
}
66-
} ~ (path("count") & get) {
67-
complete {
68-
invoker.getPoolState().map {
69-
case Right(poolState) =>
70-
(poolState.busyPool.total + poolState.pausedPool.total + poolState.inProgressCount).toJson.compactPrint
71-
case Left(value) =>
72-
value.serialize()
73+
} ~ (path("count") & get) {
74+
complete {
75+
invoker.getPoolState().map {
76+
case Right(poolState) =>
77+
(poolState.busyPool.total + poolState.pausedPool.total + poolState.inProgressCount).toJson.compactPrint
78+
case Left(value) =>
79+
value.serialize()
80+
}
7381
}
7482
}
7583
}
76-
}
77-
case _ => terminate(StatusCodes.Unauthorized)
84+
case _ => terminate(StatusCodes.Unauthorized)
85+
}
7886
}
7987
}
8088
}

core/invoker/src/main/scala/org/apache/openwhisk/core/invoker/InvokerReactive.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,5 +334,4 @@ class InvokerReactive(
334334
override def getPoolState(): Future[Either[NotSupportedPoolState, TotalContainerPoolState]] = {
335335
Future.successful(Left(NotSupportedPoolState()))
336336
}
337-
338337
}

core/scheduler/src/main/scala/org/apache/openwhisk/core/scheduler/FPCSchedulerServer.scala

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ package org.apache.openwhisk.core.scheduler
2020
import akka.actor.ActorSystem
2121
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
2222
import akka.http.scaladsl.model.StatusCodes
23+
import akka.http.scaladsl.model.StatusCodes.OK
2324
import akka.http.scaladsl.model.headers.BasicHttpCredentials
2425
import akka.http.scaladsl.server.Route
2526
import org.apache.openwhisk.common.{Logging, TransactionId}
2627
import org.apache.openwhisk.core.ConfigKeys
2728
import org.apache.openwhisk.http.BasicRasService
29+
import org.apache.openwhisk.http.CorsSettings.RespondWithServerCorsHeaders
2830
import org.apache.openwhisk.http.ErrorResponse.terminate
2931
import pureconfig.loadConfigOrThrow
3032
import spray.json.DefaultJsonProtocol._
@@ -40,43 +42,49 @@ class FPCSchedulerServer(scheduler: SchedulerCore, systemUsername: String, syste
4042
implicit val ec: ExecutionContext,
4143
implicit val actorSystem: ActorSystem,
4244
implicit val logger: Logging)
43-
extends BasicRasService {
45+
extends BasicRasService
46+
with RespondWithServerCorsHeaders {
4447

4548
override def routes(implicit transid: TransactionId): Route = {
46-
super.routes ~ extractCredentials {
47-
case Some(BasicHttpCredentials(username, password)) if username == systemUsername && password == systemPassword =>
48-
(path("state") & get) {
49-
complete {
50-
scheduler.getState.map {
51-
case (list, creationCount) =>
52-
val sum = list.map(tuple => tuple._2).sum
53-
(Map("queue" -> sum.toString) ++ Map("creationCount" -> creationCount.toString)).toJson
49+
super.routes ~ sendCorsHeaders {
50+
options {
51+
complete(OK)
52+
} ~ extractCredentials {
53+
case Some(BasicHttpCredentials(username, password))
54+
if username == systemUsername && password == systemPassword =>
55+
(path("state") & get) {
56+
complete {
57+
scheduler.getState.map {
58+
case (list, creationCount) =>
59+
val sum = list.map(tuple => tuple._2).sum
60+
(Map("queue" -> sum.toString) ++ Map("creationCount" -> creationCount.toString)).toJson
61+
}
62+
}
63+
} ~ (path("disable") & post) {
64+
logger.warn(this, "Scheduler is disabled")
65+
scheduler.disable()
66+
complete("scheduler disabled")
67+
} ~ (pathPrefix(FPCSchedulerServer.queuePathPrefix) & get) {
68+
pathEndOrSingleSlash {
69+
complete(scheduler.getQueueStatusData.map(s => s.toJson))
70+
} ~ (path("count") & get) {
71+
complete(scheduler.getQueueSize.map(s => s.toJson))
72+
}
73+
} ~ (path("activation" / "count") & get) {
74+
pathEndOrSingleSlash {
75+
complete(
76+
scheduler.getQueueStatusData
77+
.map { s =>
78+
s.map(_.waitingActivation.size)
79+
}
80+
.map(a => a.sum)
81+
.map(_.toJson))
5482
}
5583
}
56-
} ~ (path("disable") & post) {
57-
logger.warn(this, "Scheduler is disabled")
58-
scheduler.disable()
59-
complete("scheduler disabled")
60-
} ~ (pathPrefix(FPCSchedulerServer.queuePathPrefix) & get) {
61-
pathEndOrSingleSlash {
62-
complete(scheduler.getQueueStatusData.map(s => s.toJson))
63-
} ~ (path("count") & get) {
64-
complete(scheduler.getQueueSize.map(s => s.toJson))
65-
}
66-
} ~ (path("activation" / "count") & get) {
67-
pathEndOrSingleSlash {
68-
complete(
69-
scheduler.getQueueStatusData
70-
.map { s =>
71-
s.map(_.waitingActivation.size)
72-
}
73-
.map(a => a.sum)
74-
.map(_.toJson))
75-
}
76-
}
77-
case _ =>
78-
implicit val jsonPrettyResponsePrinter = PrettyPrinter
79-
terminate(StatusCodes.Unauthorized)
84+
case _ =>
85+
implicit val jsonPrettyResponsePrinter = PrettyPrinter
86+
terminate(StatusCodes.Unauthorized)
87+
}
8088
}
8189
}
8290
}

0 commit comments

Comments
 (0)