Skip to content

Commit 5d658ca

Browse files
authored
Merge pull request #44 from delphi-hub/develop
Update stable features into master
2 parents e832a0d + e4791da commit 5d658ca

File tree

19 files changed

+815
-271
lines changed

19 files changed

+815
-271
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33
.idea
44
project/target
55
target
6+
local-path

build.sbt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ libraryDependencies ++= Seq(
2424
"com.sksamuel.elastic4s" %% "elastic4s-http-streams" % elastic4sVersion,
2525
)
2626

27+
libraryDependencies += "com.pauldijou" %% "jwt-core" % "1.0.0"
28+
2729
libraryDependencies += "org.parboiled" %% "parboiled" % "2.1.4"
2830
libraryDependencies += "io.spray" %% "spray-json" % "1.3.3"
2931
libraryDependencies += "org.scalactic" %% "scalactic" % "3.0.4"
@@ -54,7 +56,9 @@ scalastyleConfig := baseDirectory.value / "project" / "scalastyle-config.xml"
5456
// Pinning secure versions of insecure transitive libraryDependencies
5557
// Please update when updating dependencies above (including Play plugin)
5658
libraryDependencies ++= Seq(
57-
"com.fasterxml.jackson.core" % "jackson-databind" % "2.9.7"
59+
"com.fasterxml.jackson.core" % "jackson-databind" % "2.9.9"
5860
)
5961

6062
trapExit := false
63+
fork := true
64+
connectInput := true

project/build.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
sbt.version=1.1.1
1+
sbt.version=1.2.7
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Copyright (C) 2018 The Delphi Team.
2+
// See the LICENCE file distributed with this work for additional
3+
// information regarding copyright ownership.
4+
//
5+
// Licensed under the Apache License, Version 2.0 (the "License");
6+
// you may not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing, software
12+
// distributed under the License is distributed on an "AS IS" BASIS,
13+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
// See the License for the specific language governing permissions and
15+
// limitations under the License.
16+
17+
package de.upb.cs.swt.delphi.webapi
18+
19+
import akka.http.scaladsl.Http
20+
import akka.http.scaladsl.model.{HttpRequest, HttpResponse}
21+
import akka.http.scaladsl.unmarshalling.{Unmarshal, Unmarshaller}
22+
import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpec}
23+
import spray.json._
24+
25+
import scala.concurrent.duration._
26+
import scala.concurrent.{Await, Future}
27+
import scala.util.{Failure, Success}
28+
29+
/**
30+
* @author Hariharan.
31+
*/
32+
class RequestLimitCheck extends WordSpec with Matchers with BeforeAndAfterAll with JsonSupport {
33+
val delphiRoutes = DelphiRoutes()
34+
val serverBinding: Future[Http.ServerBinding] = Http()
35+
.bindAndHandle(delphiRoutes, "localhost", 8085)
36+
37+
override protected def beforeAll(): Unit = {
38+
serverBinding.onComplete {
39+
case Success(server) =>
40+
println(s"Server started at http://${server.localAddress.getHostString}:${server.localAddress.getPort}/")
41+
case Failure(e) =>
42+
e.printStackTrace()
43+
sys.exit(0)
44+
}
45+
}
46+
47+
48+
"Requests" should {
49+
"throttle when limit reached" in {
50+
def responseFuture: Future[HttpResponse] = Http()
51+
.singleRequest(HttpRequest(uri = "http://localhost:8085/version"))
52+
53+
//Completing request limit
54+
for (i <- (1 to maxIndividualReq)) {
55+
Await.result(responseFuture, 1.second)
56+
}
57+
case class LimitMsg(msg: String)
58+
implicit val msgFormat = jsonFormat1(LimitMsg)
59+
60+
val limitReachedFuture = responseFuture
61+
limitReachedFuture.onComplete {
62+
case Success(res) => {
63+
val msgPromise = Unmarshal(res.entity).to[LimitMsg]
64+
msgPromise.onComplete {
65+
case Success(limitMsg) => {
66+
assertResult("Request limit exceeded")(limitMsg.msg)
67+
}
68+
case Failure(exception) => {
69+
fail(exception)
70+
}
71+
}
72+
}
73+
case Failure(exception) => {
74+
fail(exception)
75+
}
76+
}
77+
Await.result(system.terminate(), 5.seconds)
78+
}
79+
}
80+
}

src/it/scala/de/upb/cs/swt/delphi/webapi/SearchQueryTest.scala

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,24 @@
1616

1717
package de.upb.cs.swt.delphi.webapi
1818

19-
import de.upb.cs.swt.delphi.webapi.search.{QueryRequest, SearchQuery}
19+
import de.upb.cs.swt.delphi.webapi.search.{QueryRequest, SearchError, SearchQuery}
2020
import org.scalatest.{FlatSpec, Matchers}
2121

22-
import scala.util.Success
22+
import scala.util.Failure
2323

2424
class SearchQueryTest extends FlatSpec with Matchers {
25-
"Search query" should "check for fields" in {
25+
"Search query" should "fail on large request limit" in {
2626
val configuration = new Configuration()
2727
val q = new SearchQuery(configuration, new FeatureQuery(configuration))
28-
29-
val response = q.search(QueryRequest("[if_icmpeq (opcode:159)]>1"))
30-
response shouldBe a [Success[_]]
28+
val size = 20000
29+
val response = q.search(QueryRequest("[dstore_1 (opcode:72)]<1", Some(size)))
30+
response match {
31+
case Failure(exception) => {
32+
exception shouldBe a[SearchError]
33+
}
34+
case _ => {
35+
fail("Limit exceeded should fail")
36+
}
37+
}
3138
}
3239
}

src/main/scala/de/upb/cs/swt/delphi/instancemanagement/Instance.scala

Lines changed: 88 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,72 +15,134 @@
1515
// limitations under the License.
1616

1717
package de.upb.cs.swt.delphi.instancemanagement
18+
1819
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
20+
import de.upb.cs.swt.delphi.instancemanagement.InstanceEnums.{ComponentType, InstanceState}
1921
import spray.json.{DefaultJsonProtocol, DeserializationException, JsString, JsValue, JsonFormat}
2022

21-
trait JsonSupport extends SprayJsonSupport with DefaultJsonProtocol {
23+
/**
24+
* Trait defining the implicit JSON formats needed to work with Instances
25+
*/
26+
trait InstanceJsonSupport extends SprayJsonSupport with DefaultJsonProtocol with InstanceLinkJsonSupport {
2227

23-
implicit val componentTypeFormat : JsonFormat[InstanceEnums.ComponentType] = new JsonFormat[InstanceEnums.ComponentType] {
28+
//Custom JSON format for an ComponentType
29+
implicit val componentTypeFormat : JsonFormat[ComponentType] = new JsonFormat[ComponentType] {
2430

25-
def write(compType : InstanceEnums.ComponentType) = JsString(compType.toString)
31+
/**
32+
* Custom write method for serializing an ComponentType
33+
* @param compType The ComponentType to serialize
34+
* @return JsString containing the serialized value
35+
*/
36+
def write(compType : ComponentType) = JsString(compType.toString)
2637

27-
def read(value: JsValue) : InstanceEnums.ComponentType = value match {
38+
/**
39+
* Custom read method for deserialization of an ComponentType
40+
* @param value JsValue to deserialize (must be a JsString)
41+
* @return ComponentType that has been read
42+
* @throws DeserializationException Exception thrown when JsValue is in incorrect format
43+
*/
44+
def read(value: JsValue) : ComponentType = value match {
2845
case JsString(s) => s match {
29-
case "Crawler" => InstanceEnums.ComponentType.Crawler
30-
case "WebApi" => InstanceEnums.ComponentType.WebApi
31-
case "WebApp" => InstanceEnums.ComponentType.WebApp
32-
case "DelphiManagement" => InstanceEnums.ComponentType.DelphiManagement
33-
case "ElasticSearch" => InstanceEnums.ComponentType.ElasticSearch
46+
case "Crawler" => ComponentType.Crawler
47+
case "WebApi" => ComponentType.WebApi
48+
case "WebApp" => ComponentType.WebApp
49+
case "DelphiManagement" => ComponentType.DelphiManagement
50+
case "ElasticSearch" => ComponentType.ElasticSearch
3451
case x => throw DeserializationException(s"Unexpected string value $x for component type.")
3552
}
36-
case y => throw DeserializationException(s"Unexpected type $y while deserializing component type.")
53+
case y => throw DeserializationException(s"Unexpected type $y during deserialization component type.")
3754
}
3855
}
3956

40-
implicit val stateFormat : JsonFormat[InstanceEnums.State] = new JsonFormat[InstanceEnums.State] {
57+
//Custom JSON format for an InstanceState
58+
implicit val stateFormat : JsonFormat[InstanceState] = new JsonFormat[InstanceState] {
4159

42-
def write(compType : InstanceEnums.State) = JsString(compType.toString)
60+
/**
61+
* Custom write method for serializing an InstanceState
62+
* @param state The InstanceState to serialize
63+
* @return JsString containing the serialized value
64+
*/
65+
def write(state : InstanceState) = JsString(state.toString)
4366

44-
def read(value: JsValue) : InstanceEnums.State = value match {
67+
/**
68+
* Custom read method for deserialization of an InstanceState
69+
* @param value JsValue to deserialize (must be a JsString)
70+
* @return InstanceState that has been read
71+
* @throws DeserializationException Exception thrown when JsValue is in incorrect format
72+
*/
73+
def read(value: JsValue) : InstanceState = value match {
4574
case JsString(s) => s match {
46-
case "Running" => InstanceEnums.InstanceState.Running
47-
case "Stopped" => InstanceEnums.InstanceState.Stopped
48-
case "Failed" => InstanceEnums.InstanceState.Failed
49-
case "Paused" => InstanceEnums.InstanceState.Paused
50-
case "NotReachable" => InstanceEnums.InstanceState.NotReachable
75+
case "Running" => InstanceState.Running
76+
case "Stopped" => InstanceState.Stopped
77+
case "Failed" => InstanceState.Failed
78+
case "Paused" => InstanceState.Paused
79+
case "NotReachable" => InstanceState.NotReachable
80+
case "Deploying" => InstanceState.Deploying
5181
case x => throw DeserializationException(s"Unexpected string value $x for instance state.")
5282
}
53-
case y => throw DeserializationException(s"Unexpected type $y while deserializing instance state.")
83+
case y => throw DeserializationException(s"Unexpected type $y during deserialization instance state.")
5484
}
5585
}
5686

57-
implicit val instanceFormat : JsonFormat[Instance] = jsonFormat7(Instance)
87+
//JSON format for Instances
88+
implicit val instanceFormat : JsonFormat[Instance] = jsonFormat10(Instance)
5889
}
5990

91+
/**
92+
* The instance type used for transmitting data about an instance from an to the registry
93+
* @param id Id of the instance. This is an Option[Long], as an registering instance will not yet have an id.
94+
* @param host Host of the instance.
95+
* @param portNumber Port the instance is reachable at.
96+
* @param name Name of the instance
97+
* @param componentType ComponentType of the instance.
98+
* @param dockerId The docker container id of the instance. This is an Option[String], as not all instance have to be docker containers.
99+
* @param instanceState State of the instance
100+
*/
60101
final case class Instance (
61102
id: Option[Long],
62103
host: String,
63104
portNumber: Long,
64105
name: String,
65-
componentType: InstanceEnums.ComponentType,
106+
componentType: ComponentType,
66107
dockerId: Option[String],
67-
instanceState: InstanceEnums.State
108+
instanceState: InstanceState,
109+
labels: List[String],
110+
linksTo: List[InstanceLink],
111+
linksFrom: List[InstanceLink]
68112
)
113+
114+
/**
115+
* Enumerations concerning instances
116+
*/
69117
object InstanceEnums {
118+
119+
//Type to use when working with component types
70120
type ComponentType = ComponentType.Value
121+
122+
/**
123+
* ComponentType enumeration defining the valid types of delphi components
124+
*/
71125
object ComponentType extends Enumeration {
72126
val Crawler : Value = Value("Crawler")
73-
val ElasticSearch : Value = Value("ElasticSearch")
74127
val WebApi : Value = Value("WebApi")
75128
val WebApp : Value = Value("WebApp")
76129
val DelphiManagement : Value = Value("DelphiManagement")
130+
val ElasticSearch : Value = Value("ElasticSearch")
77131
}
78-
type State = InstanceState.Value
132+
133+
//Type to use when working with instance states
134+
type InstanceState = InstanceState.Value
135+
136+
/**
137+
* InstanceState enumeration defining the valid states for instances of delphi components
138+
*/
79139
object InstanceState extends Enumeration {
140+
val Deploying : Value = Value("Deploying")
80141
val Running : Value = Value("Running")
81-
val Paused : Value = Value("Paused")
82142
val Stopped : Value = Value("Stopped")
83143
val Failed : Value = Value("Failed")
144+
val Paused : Value = Value("Paused")
84145
val NotReachable : Value = Value("NotReachable")
85146
}
86-
}
147+
148+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright (C) 2018 The Delphi Team.
2+
// See the LICENCE file distributed with this work for additional
3+
// information regarding copyright ownership.
4+
//
5+
// Licensed under the Apache License, Version 2.0 (the "License");
6+
// you may not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing, software
12+
// distributed under the License is distributed on an "AS IS" BASIS,
13+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
// See the License for the specific language governing permissions and
15+
// limitations under the License.
16+
package de.upb.cs.swt.delphi.instancemanagement
17+
18+
import LinkEnums.LinkState
19+
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
20+
import spray.json.{DefaultJsonProtocol, DeserializationException, JsString, JsValue, JsonFormat}
21+
22+
trait InstanceLinkJsonSupport extends SprayJsonSupport with DefaultJsonProtocol {
23+
24+
implicit val linkStateFormat: JsonFormat[LinkState] = new JsonFormat[LinkState] {
25+
override def read(value: JsValue): LinkState = value match {
26+
case JsString(s) => s match {
27+
case "Assigned" => LinkState.Assigned
28+
case "Outdated" => LinkState.Outdated
29+
case "Failed" => LinkState.Failed
30+
case x => throw DeserializationException(s"Unexpected string value $x for LinkState.")
31+
}
32+
case y => throw DeserializationException(s"Unexpected type $y during deserialization of LinkState")
33+
}
34+
35+
override def write(linkState: LinkState): JsValue = JsString(linkState.toString)
36+
}
37+
38+
implicit val instanceLinkFormat: JsonFormat[InstanceLink] =
39+
jsonFormat3(InstanceLink)
40+
}
41+
42+
43+
final case class InstanceLink(idFrom: Long, idTo:Long, linkState: LinkState)
44+
45+
object LinkEnums {
46+
type LinkState = LinkState.Value
47+
48+
object LinkState extends Enumeration {
49+
val Assigned: Value = Value("Assigned")
50+
val Failed: Value = Value("Failed")
51+
val Outdated: Value = Value("Outdated")
52+
}
53+
}

0 commit comments

Comments
 (0)