summaryrefslogtreecommitdiff
path: root/opendc-web
diff options
context:
space:
mode:
Diffstat (limited to 'opendc-web')
-rw-r--r--opendc-web/opendc-web-client/build.gradle.kts2
-rw-r--r--opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/PortfolioResource.kt15
-rw-r--r--opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/ScenarioResource.kt21
-rw-r--r--opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/TopologyResource.kt21
-rw-r--r--opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/auth/OpenIdAuthController.kt55
-rw-r--r--opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/internal/ClientUtils.kt10
-rw-r--r--opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/internal/OAuthTokenRequest.kt8
-rw-r--r--opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/internal/OAuthTokenResponse.kt2
-rw-r--r--opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/internal/OpenIdConfiguration.kt2
-rw-r--r--opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/runner/JobResource.kt5
-rw-r--r--opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/transport/HttpTransportClient.kt71
-rw-r--r--opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/transport/TransportClient.kt22
-rw-r--r--opendc-web/opendc-web-proto/build.gradle.kts2
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/JobState.kt2
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Machine.kt2
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/MemoryUnit.kt2
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/OperationalPhenomena.kt2
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/ProcessingUnit.kt2
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Rack.kt2
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Room.kt2
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/RoomTile.kt2
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Targets.kt4
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Trace.kt2
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Workload.kt6
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Job.kt2
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Portfolio.kt2
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Scenario.kt2
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Topology.kt2
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Job.kt2
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Portfolio.kt8
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Project.kt8
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/ProjectRole.kt2
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Scenario.kt8
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Topology.kt8
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/User.kt2
-rw-r--r--opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/UserAccounting.kt2
-rw-r--r--opendc-web/opendc-web-runner-quarkus-deployment/build.gradle.kts2
-rw-r--r--opendc-web/opendc-web-runner-quarkus/src/main/java/org/opendc/web/runner/runtime/OpenDCRunnerRecorder.java2
-rw-r--r--opendc-web/opendc-web-runner/Dockerfile4
-rw-r--r--opendc-web/opendc-web-runner/build.gradle.kts4
-rw-r--r--opendc-web/opendc-web-runner/src/cli/kotlin/org/opendc/web/runner/Main.kt14
-rw-r--r--opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/JobManager.kt16
-rw-r--r--opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt196
-rw-r--r--opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/internal/JobManagerImpl.kt16
-rw-r--r--opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/internal/WebComputeMonitor.kt33
-rw-r--r--opendc-web/opendc-web-server/Dockerfile4
-rw-r--r--opendc-web/opendc-web-server/build.gradle.kts6
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Job.java33
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Portfolio.java45
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Project.java37
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/ProjectAuthorization.java70
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Scenario.java34
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Topology.java40
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Trace.java10
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/UserAccounting.java14
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Workload.java6
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/SchedulerResource.java6
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/TraceResource.java10
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/error/MissingKotlinParameterExceptionMapper.java8
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/error/WebApplicationExceptionMapper.java10
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/runner/JobResource.java20
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/PortfolioResource.java22
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/PortfolioScenarioResource.java20
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/ProjectResource.java26
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/ScenarioResource.java16
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/TopologyResource.java26
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/UserResource.java8
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/JobService.java2
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/UserAccountingService.java4
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/DevSecurityOverrideFilter.java10
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/KotlinModuleCustomizer.java2
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/QuarkusObjectMapperSupplier.java2
-rw-r--r--opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/runner/QuarkusJobManager.java4
-rw-r--r--opendc-web/opendc-web-server/src/main/resources/application-test.properties4
-rw-r--r--opendc-web/opendc-web-server/src/main/resources/db/migration/V3.0__core.sql160
-rw-r--r--opendc-web/opendc-web-server/src/main/resources/db/testing/V3.0.1__entities.sql24
-rw-r--r--opendc-web/opendc-web-server/src/main/resources/load_data.sql124
-rw-r--r--opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/SchedulerResourceTest.java5
-rw-r--r--opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/TraceResourceTest.java4
-rw-r--r--opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/runner/JobResourceTest.java25
-rw-r--r--opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/PortfolioResourceTest.java141
-rw-r--r--opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/PortfolioScenarioResourceTest.java106
-rw-r--r--opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/ProjectResourceTest.java143
-rw-r--r--opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/ScenarioResourceTest.java57
-rw-r--r--opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/TopologyResourceTest.java120
-rw-r--r--opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/service/UserAccountingServiceTest.java2
-rw-r--r--opendc-web/opendc-web-ui-quarkus-deployment/build.gradle.kts2
-rw-r--r--opendc-web/opendc-web-ui/build.gradle.kts86
88 files changed, 1079 insertions, 1018 deletions
diff --git a/opendc-web/opendc-web-client/build.gradle.kts b/opendc-web/opendc-web-client/build.gradle.kts
index 77a0afff..55228ef9 100644
--- a/opendc-web/opendc-web-client/build.gradle.kts
+++ b/opendc-web/opendc-web-client/build.gradle.kts
@@ -22,7 +22,7 @@
description = "Client for the OpenDC web API"
-/* Build configuration */
+// Build configuration
plugins {
`kotlin-library-conventions`
}
diff --git a/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/PortfolioResource.kt b/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/PortfolioResource.kt
index 399804e8..f0e49973 100644
--- a/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/PortfolioResource.kt
+++ b/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/PortfolioResource.kt
@@ -40,19 +40,28 @@ public class PortfolioResource internal constructor(private val client: Transpor
/**
* Obtain the portfolio for [project] with [number].
*/
- public fun get(project: Long, number: Int): Portfolio? = client.get("projects/$project/portfolios/$number")
+ public fun get(
+ project: Long,
+ number: Int,
+ ): Portfolio? = client.get("projects/$project/portfolios/$number")
/**
* Create a new portfolio for [project] with the specified [request].
*/
- public fun create(project: Long, request: Portfolio.Create): Portfolio {
+ public fun create(
+ project: Long,
+ request: Portfolio.Create,
+ ): Portfolio {
return checkNotNull(client.post("projects/$project/portfolios", request))
}
/**
* Delete the portfolio for [project] with [index].
*/
- public fun delete(project: Long, index: Int): Portfolio {
+ public fun delete(
+ project: Long,
+ index: Int,
+ ): Portfolio {
return requireNotNull(client.delete("projects/$project/portfolios/$index")) { "Unknown portfolio $index" }
}
}
diff --git a/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/ScenarioResource.kt b/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/ScenarioResource.kt
index 7055e752..d43515a9 100644
--- a/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/ScenarioResource.kt
+++ b/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/ScenarioResource.kt
@@ -40,24 +40,37 @@ public class ScenarioResource internal constructor(private val client: Transport
/**
* List all scenarios that belong to the specified [portfolioNumber].
*/
- public fun getAll(project: Long, portfolioNumber: Int): List<Scenario> = client.get("projects/$project/portfolios/$portfolioNumber/scenarios") ?: emptyList()
+ public fun getAll(
+ project: Long,
+ portfolioNumber: Int,
+ ): List<Scenario> = client.get("projects/$project/portfolios/$portfolioNumber/scenarios") ?: emptyList()
/**
* Obtain the scenario for [project] with [index].
*/
- public fun get(project: Long, index: Int): Scenario? = client.get("projects/$project/scenarios/$index")
+ public fun get(
+ project: Long,
+ index: Int,
+ ): Scenario? = client.get("projects/$project/scenarios/$index")
/**
* Create a new scenario for [portfolio][portfolioNumber] with the specified [request].
*/
- public fun create(project: Long, portfolioNumber: Int, request: Scenario.Create): Scenario {
+ public fun create(
+ project: Long,
+ portfolioNumber: Int,
+ request: Scenario.Create,
+ ): Scenario {
return checkNotNull(client.post("projects/$project/portfolios/$portfolioNumber", request))
}
/**
* Delete the scenario for [project] with [index].
*/
- public fun delete(project: Long, index: Int): Scenario {
+ public fun delete(
+ project: Long,
+ index: Int,
+ ): Scenario {
return requireNotNull(client.delete("projects/$project/scenarios/$index")) { "Unknown scenario $index" }
}
}
diff --git a/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/TopologyResource.kt b/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/TopologyResource.kt
index c37ae8da..34f5ea1b 100644
--- a/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/TopologyResource.kt
+++ b/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/TopologyResource.kt
@@ -41,26 +41,39 @@ public class TopologyResource internal constructor(private val client: Transport
/**
* Obtain the topology for [project] with [index].
*/
- public fun get(project: Long, index: Int): Topology? = client.get("projects/$project/topologies/$index")
+ public fun get(
+ project: Long,
+ index: Int,
+ ): Topology? = client.get("projects/$project/topologies/$index")
/**
* Create a new topology for [project] with [request].
*/
- public fun create(project: Long, request: Topology.Create): Topology {
+ public fun create(
+ project: Long,
+ request: Topology.Create,
+ ): Topology {
return checkNotNull(client.post("projects/$project/topologies", request))
}
/**
* Update the topology with [index] for [project] using the specified [request].
*/
- public fun update(project: Long, index: Int, request: Topology.Update): Topology? {
+ public fun update(
+ project: Long,
+ index: Int,
+ request: Topology.Update,
+ ): Topology? {
return client.put("projects/$project/topologies/$index", request)
}
/**
* Delete the topology for [project] with [index].
*/
- public fun delete(project: Long, index: Long): Topology {
+ public fun delete(
+ project: Long,
+ index: Long,
+ ): Topology {
return requireNotNull(client.delete("projects/$project/topologies/$index")) { "Unknown topology $index" }
}
}
diff --git a/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/auth/OpenIdAuthController.kt b/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/auth/OpenIdAuthController.kt
index 7f9cbacd..707dc138 100644
--- a/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/auth/OpenIdAuthController.kt
+++ b/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/auth/OpenIdAuthController.kt
@@ -41,39 +41,40 @@ public class OpenIdAuthController(
private val clientId: String,
private val clientSecret: String,
private val audience: String = "https://api.opendc.org/v2/",
- private val client: HttpClient = HttpClient.newHttpClient()
+ private val client: HttpClient = HttpClient.newHttpClient(),
) : AuthController {
/**
* The Jackson object mapper to convert messages from/to JSON.
*/
- private val mapper = jacksonObjectMapper()
- .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
+ private val mapper =
+ jacksonObjectMapper()
+ .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
/**
* The cached [OpenIdConfiguration].
*/
private val openidConfig: OpenIdConfiguration
get() {
- var openidConfig = _openidConfig
+ var openidConfig = localOpenidConfig
if (openidConfig == null) {
openidConfig = requestConfig()
- _openidConfig = openidConfig
+ localOpenidConfig = openidConfig
}
return openidConfig
}
- private var _openidConfig: OpenIdConfiguration? = null
+ private var localOpenidConfig: OpenIdConfiguration? = null
/**
* The cached OAuth token.
*/
- private var _token: OAuthTokenResponse? = null
+ private var localToken: OAuthTokenResponse? = null
override fun injectToken(request: HttpRequest.Builder) {
- var token = _token
+ var token = localToken
if (token == null) {
token = requestToken()
- _token = token
+ localToken = token
}
request.header("Authorization", "Bearer ${token.accessToken}")
@@ -83,22 +84,23 @@ public class OpenIdAuthController(
* Refresh the current access token.
*/
override fun refreshToken() {
- val refreshToken = _token?.refreshToken
+ val refreshToken = localToken?.refreshToken
if (refreshToken == null) {
requestToken()
return
}
- _token = refreshToken(openidConfig, refreshToken)
+ localToken = refreshToken(openidConfig, refreshToken)
}
/**
* Request the OpenID configuration from the chosen auth domain
*/
private fun requestConfig(): OpenIdConfiguration {
- val request = HttpRequest.newBuilder(URI("https://$domain/.well-known/openid-configuration"))
- .GET()
- .build()
+ val request =
+ HttpRequest.newBuilder(URI("https://$domain/.well-known/openid-configuration"))
+ .GET()
+ .build()
val response = client.send(request, HttpResponse.BodyHandlers.ofInputStream())
return mapper.readValue(response.body())
}
@@ -108,10 +110,11 @@ public class OpenIdAuthController(
*/
private fun requestToken(openidConfig: OpenIdConfiguration): OAuthTokenResponse {
val body = OAuthTokenRequest.ClientCredentials(audience, clientId, clientSecret)
- val request = HttpRequest.newBuilder(openidConfig.tokenEndpoint)
- .header("Content-Type", "application/json")
- .POST(HttpRequest.BodyPublishers.ofByteArray(mapper.writeValueAsBytes(body)))
- .build()
+ val request =
+ HttpRequest.newBuilder(openidConfig.tokenEndpoint)
+ .header("Content-Type", "application/json")
+ .POST(HttpRequest.BodyPublishers.ofByteArray(mapper.writeValueAsBytes(body)))
+ .build()
val response = client.send(request, HttpResponse.BodyHandlers.ofInputStream())
return mapper.readValue(response.body())
}
@@ -119,12 +122,16 @@ public class OpenIdAuthController(
/**
* Helper method to refresh the auth token.
*/
- private fun refreshToken(openidConfig: OpenIdConfiguration, refreshToken: String): OAuthTokenResponse {
+ private fun refreshToken(
+ openidConfig: OpenIdConfiguration,
+ refreshToken: String,
+ ): OAuthTokenResponse {
val body = OAuthTokenRequest.RefreshToken(refreshToken, clientId, clientSecret)
- val request = HttpRequest.newBuilder(openidConfig.tokenEndpoint)
- .header("Content-Type", "application/json")
- .POST(HttpRequest.BodyPublishers.ofByteArray(mapper.writeValueAsBytes(body)))
- .build()
+ val request =
+ HttpRequest.newBuilder(openidConfig.tokenEndpoint)
+ .header("Content-Type", "application/json")
+ .POST(HttpRequest.BodyPublishers.ofByteArray(mapper.writeValueAsBytes(body)))
+ .build()
val response = client.send(request, HttpResponse.BodyHandlers.ofInputStream())
return mapper.readValue(response.body())
}
@@ -134,7 +141,7 @@ public class OpenIdAuthController(
*/
private fun requestToken(): OAuthTokenResponse {
val token = requestToken(openidConfig)
- _token = token
+ localToken = token
return token
}
}
diff --git a/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/internal/ClientUtils.kt b/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/internal/ClientUtils.kt
index 29cf09dc..1ffaa602 100644
--- a/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/internal/ClientUtils.kt
+++ b/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/internal/ClientUtils.kt
@@ -35,14 +35,20 @@ internal inline fun <reified T> TransportClient.get(path: String): T? {
/**
* Perform a POST request for resource at [path] and convert to type [T].
*/
-internal inline fun <B, reified T> TransportClient.post(path: String, body: B): T? {
+internal inline fun <B, reified T> TransportClient.post(
+ path: String,
+ body: B,
+): T? {
return post(path, body, object : TypeReference<T>() {})
}
/**
* Perform a PUT request for resource at [path] and convert to type [T].
*/
-internal inline fun <B, reified T> TransportClient.put(path: String, body: B): T? {
+internal inline fun <B, reified T> TransportClient.put(
+ path: String,
+ body: B,
+): T? {
return put(path, body, object : TypeReference<T>() {})
}
diff --git a/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/internal/OAuthTokenRequest.kt b/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/internal/OAuthTokenRequest.kt
index 25341995..1bb06c8f 100644
--- a/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/internal/OAuthTokenRequest.kt
+++ b/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/internal/OAuthTokenRequest.kt
@@ -33,8 +33,8 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo
@JsonSubTypes(
value = [
JsonSubTypes.Type(value = OAuthTokenRequest.ClientCredentials::class, name = "client_credentials"),
- JsonSubTypes.Type(value = OAuthTokenRequest.RefreshToken::class, name = "refresh_token")
- ]
+ JsonSubTypes.Type(value = OAuthTokenRequest.RefreshToken::class, name = "refresh_token"),
+ ],
)
internal sealed class OAuthTokenRequest {
/**
@@ -45,7 +45,7 @@ internal sealed class OAuthTokenRequest {
@JsonProperty("client_id")
val clientId: String,
@JsonProperty("client_secret")
- val clientSecret: String
+ val clientSecret: String,
) : OAuthTokenRequest()
/**
@@ -57,6 +57,6 @@ internal sealed class OAuthTokenRequest {
@JsonProperty("client_id")
val clientId: String,
@JsonProperty("client_secret")
- val clientSecret: String
+ val clientSecret: String,
) : OAuthTokenRequest()
}
diff --git a/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/internal/OAuthTokenResponse.kt b/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/internal/OAuthTokenResponse.kt
index cd5ccab0..76fe007c 100644
--- a/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/internal/OAuthTokenResponse.kt
+++ b/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/internal/OAuthTokenResponse.kt
@@ -36,5 +36,5 @@ internal data class OAuthTokenResponse(
val tokenType: String,
val scope: String = "",
@JsonProperty("expires_in")
- val expiresIn: Long
+ val expiresIn: Long,
)
diff --git a/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/internal/OpenIdConfiguration.kt b/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/internal/OpenIdConfiguration.kt
index 23fbf368..eac1607e 100644
--- a/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/internal/OpenIdConfiguration.kt
+++ b/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/internal/OpenIdConfiguration.kt
@@ -39,5 +39,5 @@ internal data class OpenIdConfiguration(
@JsonProperty("jwks_uri")
val jwksUri: URI,
@JsonProperty("scopes_supported")
- val scopesSupported: Set<String>
+ val scopesSupported: Set<String>,
)
diff --git a/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/runner/JobResource.kt b/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/runner/JobResource.kt
index ad3f1c9b..e72f703c 100644
--- a/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/runner/JobResource.kt
+++ b/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/runner/JobResource.kt
@@ -44,5 +44,8 @@ public class JobResource internal constructor(private val client: TransportClien
/**
* Update the job with [id].
*/
- public fun update(id: Long, update: Job.Update): Job? = client.post("jobs/$id", update)
+ public fun update(
+ id: Long,
+ update: Job.Update,
+ ): Job? = client.post("jobs/$id", update)
}
diff --git a/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/transport/HttpTransportClient.kt b/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/transport/HttpTransportClient.kt
index e407380b..f6dca4d1 100644
--- a/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/transport/HttpTransportClient.kt
+++ b/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/transport/HttpTransportClient.kt
@@ -43,23 +43,28 @@ import java.nio.file.Paths
public class HttpTransportClient(
private val baseUrl: URI,
private val auth: AuthController?,
- private val client: HttpClient = HttpClient.newHttpClient()
+ private val client: HttpClient = HttpClient.newHttpClient(),
) : TransportClient {
/**
* The Jackson object mapper to convert messages from/to JSON.
*/
- private val mapper = jacksonObjectMapper()
- .registerModule(JavaTimeModule())
- .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
+ private val mapper =
+ jacksonObjectMapper()
+ .registerModule(JavaTimeModule())
+ .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
/**
* Obtain a resource at [path] of [targetType].
*/
- override fun <T> get(path: String, targetType: TypeReference<T>): T? {
- val request = HttpRequest.newBuilder(buildUri(path))
- .GET()
- .also { auth?.injectToken(it) }
- .build()
+ override fun <T> get(
+ path: String,
+ targetType: TypeReference<T>,
+ ): T? {
+ val request =
+ HttpRequest.newBuilder(buildUri(path))
+ .GET()
+ .also { auth?.injectToken(it) }
+ .build()
val response = client.send(request, HttpResponse.BodyHandlers.ofInputStream())
return when (val code = response.statusCode()) {
@@ -81,12 +86,17 @@ public class HttpTransportClient(
/**
* Update a resource at [path] of [targetType].
*/
- override fun <B, T> post(path: String, body: B, targetType: TypeReference<T>): T? {
- val request = HttpRequest.newBuilder(buildUri(path))
- .POST(HttpRequest.BodyPublishers.ofByteArray(mapper.writeValueAsBytes(body)))
- .header("Content-Type", "application/json")
- .also { auth?.injectToken(it) }
- .build()
+ override fun <B, T> post(
+ path: String,
+ body: B,
+ targetType: TypeReference<T>,
+ ): T? {
+ val request =
+ HttpRequest.newBuilder(buildUri(path))
+ .POST(HttpRequest.BodyPublishers.ofByteArray(mapper.writeValueAsBytes(body)))
+ .header("Content-Type", "application/json")
+ .also { auth?.injectToken(it) }
+ .build()
val response = client.send(request, HttpResponse.BodyHandlers.ofInputStream())
return when (val code = response.statusCode()) {
@@ -108,12 +118,17 @@ public class HttpTransportClient(
/**
* Replace a resource at [path] of [targetType].
*/
- override fun <B, T> put(path: String, body: B, targetType: TypeReference<T>): T? {
- val request = HttpRequest.newBuilder(buildUri(path))
- .PUT(HttpRequest.BodyPublishers.ofByteArray(mapper.writeValueAsBytes(body)))
- .header("Content-Type", "application/json")
- .also { auth?.injectToken(it) }
- .build()
+ override fun <B, T> put(
+ path: String,
+ body: B,
+ targetType: TypeReference<T>,
+ ): T? {
+ val request =
+ HttpRequest.newBuilder(buildUri(path))
+ .PUT(HttpRequest.BodyPublishers.ofByteArray(mapper.writeValueAsBytes(body)))
+ .header("Content-Type", "application/json")
+ .also { auth?.injectToken(it) }
+ .build()
val response = client.send(request, HttpResponse.BodyHandlers.ofInputStream())
return when (val code = response.statusCode()) {
@@ -135,11 +150,15 @@ public class HttpTransportClient(
/**
* Delete a resource at [path] of [targetType].
*/
- override fun <T> delete(path: String, targetType: TypeReference<T>): T? {
- val request = HttpRequest.newBuilder(buildUri(path))
- .DELETE()
- .also { auth?.injectToken(it) }
- .build()
+ override fun <T> delete(
+ path: String,
+ targetType: TypeReference<T>,
+ ): T? {
+ val request =
+ HttpRequest.newBuilder(buildUri(path))
+ .DELETE()
+ .also { auth?.injectToken(it) }
+ .build()
val response = client.send(request, HttpResponse.BodyHandlers.ofInputStream())
return when (val code = response.statusCode()) {
diff --git a/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/transport/TransportClient.kt b/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/transport/TransportClient.kt
index af727ca7..ebf3402f 100644
--- a/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/transport/TransportClient.kt
+++ b/opendc-web/opendc-web-client/src/main/kotlin/org/opendc/web/client/transport/TransportClient.kt
@@ -31,20 +31,34 @@ public interface TransportClient {
/**
* Obtain a resource at [path] of [targetType].
*/
- public fun <T> get(path: String, targetType: TypeReference<T>): T?
+ public fun <T> get(
+ path: String,
+ targetType: TypeReference<T>,
+ ): T?
/**
* Update a resource at [path] of [targetType].
*/
- public fun <B, T> post(path: String, body: B, targetType: TypeReference<T>): T?
+ public fun <B, T> post(
+ path: String,
+ body: B,
+ targetType: TypeReference<T>,
+ ): T?
/**
* Replace a resource at [path] of [targetType].
*/
- public fun <B, T> put(path: String, body: B, targetType: TypeReference<T>): T?
+ public fun <B, T> put(
+ path: String,
+ body: B,
+ targetType: TypeReference<T>,
+ ): T?
/**
* Delete a resource at [path] of [targetType].
*/
- public fun <T> delete(path: String, targetType: TypeReference<T>): T?
+ public fun <T> delete(
+ path: String,
+ targetType: TypeReference<T>,
+ ): T?
}
diff --git a/opendc-web/opendc-web-proto/build.gradle.kts b/opendc-web/opendc-web-proto/build.gradle.kts
index 4a566346..9b307655 100644
--- a/opendc-web/opendc-web-proto/build.gradle.kts
+++ b/opendc-web/opendc-web-proto/build.gradle.kts
@@ -22,7 +22,7 @@
description = "Web communication protocol for OpenDC"
-/* Build configuration */
+// Build configuration
plugins {
`kotlin-library-conventions`
id("org.kordamp.gradle.jandex") // Necessary for Quarkus to process annotations
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/JobState.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/JobState.kt
index 38b8ca42..a8e67ec5 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/JobState.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/JobState.kt
@@ -49,5 +49,5 @@ public enum class JobState {
/**
* The job has failed.
*/
- FAILED;
+ FAILED,
}
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Machine.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Machine.kt
index f5c50cc3..72163f51 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Machine.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Machine.kt
@@ -36,5 +36,5 @@ public data class Machine(
val memory: List<MemoryUnit> = emptyList(),
@JsonProperty("storages")
val storage: List<MemoryUnit> = emptyList(),
- val rackId: String? = null
+ val rackId: String? = null,
)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/MemoryUnit.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/MemoryUnit.kt
index 1fc604fa..00560ad6 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/MemoryUnit.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/MemoryUnit.kt
@@ -30,5 +30,5 @@ public data class MemoryUnit(
val name: String,
val speedMbPerS: Double,
val sizeMb: Double,
- val energyConsumptionW: Double
+ val energyConsumptionW: Double,
)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/OperationalPhenomena.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/OperationalPhenomena.kt
index f3164f64..28006d27 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/OperationalPhenomena.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/OperationalPhenomena.kt
@@ -27,5 +27,5 @@ package org.opendc.web.proto
*/
public data class OperationalPhenomena(
val failures: Boolean,
- val interference: Boolean
+ val interference: Boolean,
)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/ProcessingUnit.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/ProcessingUnit.kt
index 5f79d1bd..86f40516 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/ProcessingUnit.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/ProcessingUnit.kt
@@ -30,5 +30,5 @@ public data class ProcessingUnit(
val name: String,
val clockRateMhz: Double,
val numberOfCores: Int,
- val energyConsumptionW: Double
+ val energyConsumptionW: Double,
)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Rack.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Rack.kt
index 131aa184..c997e814 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Rack.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Rack.kt
@@ -30,5 +30,5 @@ public data class Rack(
val name: String,
val capacity: Int,
val powerCapacityW: Double,
- val machines: List<Machine>
+ val machines: List<Machine>,
)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Room.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Room.kt
index c5499150..5b305168 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Room.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Room.kt
@@ -29,5 +29,5 @@ public data class Room(
val id: String,
val name: String,
val tiles: Set<RoomTile>,
- val topologyId: String? = null
+ val topologyId: String? = null,
)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/RoomTile.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/RoomTile.kt
index 53cb53cd..666d66ee 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/RoomTile.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/RoomTile.kt
@@ -30,5 +30,5 @@ public data class RoomTile(
val positionX: Double,
val positionY: Double,
val rack: Rack? = null,
- val roomId: String? = null
+ val roomId: String? = null,
)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Targets.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Targets.kt
index a0100f72..25516ff0 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Targets.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Targets.kt
@@ -22,7 +22,7 @@
package org.opendc.web.proto
-import javax.validation.constraints.Min
+import jakarta.validation.constraints.Min
/**
* The targets of a portfolio.
@@ -33,5 +33,5 @@ import javax.validation.constraints.Min
public data class Targets(
val metrics: Set<String>,
@field:Min(1)
- val repeats: Int = 1
+ val repeats: Int = 1,
)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Trace.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Trace.kt
index 1c086cd8..2952a273 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Trace.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Trace.kt
@@ -32,5 +32,5 @@ package org.opendc.web.proto
public data class Trace(
val id: String,
val name: String,
- val type: String
+ val type: String,
)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Workload.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Workload.kt
index cc6e0ed8..58daf817 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Workload.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/Workload.kt
@@ -22,8 +22,8 @@
package org.opendc.web.proto
-import javax.validation.constraints.DecimalMax
-import javax.validation.constraints.DecimalMin
+import jakarta.validation.constraints.DecimalMax
+import jakarta.validation.constraints.DecimalMin
/**
* The workload to simulate for a scenario.
@@ -39,6 +39,6 @@ public data class Workload(val trace: Trace, val samplingFraction: Double) {
val trace: String,
@DecimalMin(value = "0.001", message = "Sampling fraction must be non-zero")
@DecimalMax(value = "1", message = "Sampling fraction cannot exceed one")
- val samplingFraction: Double
+ val samplingFraction: Double,
)
}
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Job.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Job.kt
index 4f21f0bb..34642436 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Job.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Job.kt
@@ -37,7 +37,7 @@ public data class Job(
val createdAt: Instant,
val updatedAt: Instant,
val runtime: Int,
- val results: Map<String, Any>? = null
+ val results: Map<String, Any>? = null,
) {
/**
* A request to update the state of a job.
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Portfolio.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Portfolio.kt
index 5faad5b3..916d8cf0 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Portfolio.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Portfolio.kt
@@ -39,5 +39,5 @@ public data class Portfolio(
val id: Long,
val number: Int,
val name: String,
- val targets: Targets
+ val targets: Targets,
)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Scenario.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Scenario.kt
index aeffc4d7..ebc10bb0 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Scenario.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Scenario.kt
@@ -38,5 +38,5 @@ public data class Scenario(
val workload: Workload,
val topology: Topology,
val phenomena: OperationalPhenomena,
- val schedulerName: String
+ val schedulerName: String,
)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Topology.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Topology.kt
index bc185aea..4bffdee9 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Topology.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/runner/Topology.kt
@@ -36,5 +36,5 @@ public data class Topology(
val name: String,
val rooms: List<Room>,
val createdAt: Instant,
- val updatedAt: Instant
+ val updatedAt: Instant,
)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Job.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Job.kt
index de5f8de3..dd2f209e 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Job.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Job.kt
@@ -36,5 +36,5 @@ public data class Job(
val state: JobState,
val createdAt: Instant,
val updatedAt: Instant,
- val results: Map<String, Any>? = null
+ val results: Map<String, Any>? = null,
)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Portfolio.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Portfolio.kt
index 99d0f65e..6f433a04 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Portfolio.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Portfolio.kt
@@ -22,9 +22,9 @@
package org.opendc.web.proto.user
+import jakarta.validation.constraints.NotBlank
import org.eclipse.microprofile.openapi.annotations.media.Schema
import org.opendc.web.proto.Targets
-import javax.validation.constraints.NotBlank
/**
* A portfolio is the composition of multiple scenarios.
@@ -42,7 +42,7 @@ public data class Portfolio(
val project: Project,
val name: String,
val targets: Targets,
- val scenarios: List<Scenario.Summary>
+ val scenarios: List<Scenario.Summary>,
) {
/**
* A request to create a new portfolio.
@@ -51,7 +51,7 @@ public data class Portfolio(
public data class Create(
@field:NotBlank(message = "Name must not be empty")
val name: String,
- val targets: Targets
+ val targets: Targets,
)
/**
@@ -67,6 +67,6 @@ public data class Portfolio(
val id: Long,
val number: Int,
val name: String,
- val targets: Targets
+ val targets: Targets,
)
}
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Project.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Project.kt
index 3a2807ca..635552a9 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Project.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Project.kt
@@ -22,9 +22,9 @@
package org.opendc.web.proto.user
+import jakarta.validation.constraints.NotBlank
import org.eclipse.microprofile.openapi.annotations.media.Schema
import java.time.Instant
-import javax.validation.constraints.NotBlank
/**
* A project in OpenDC encapsulates all the datacenter designs and simulation runs for a set of users.
@@ -34,11 +34,13 @@ public data class Project(
val name: String,
val createdAt: Instant,
val updatedAt: Instant,
- val role: ProjectRole
+ val role: ProjectRole,
) {
/**
* A request to create a new project.
*/
@Schema(name = "Project.Create")
- public data class Create(@field:NotBlank(message = "Name must not be empty") val name: String)
+ public data class Create(
+ @field:NotBlank(message = "Name must not be empty") val name: String,
+ )
}
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/ProjectRole.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/ProjectRole.kt
index ea6a30ab..0f6de1fc 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/ProjectRole.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/ProjectRole.kt
@@ -39,5 +39,5 @@ public enum class ProjectRole {
/**
* The user owns the project (so he can delete it).
*/
- OWNER
+ OWNER,
}
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Scenario.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Scenario.kt
index b9c7a4cf..e0c790f5 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Scenario.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Scenario.kt
@@ -22,10 +22,10 @@
package org.opendc.web.proto.user
+import jakarta.validation.constraints.NotBlank
import org.eclipse.microprofile.openapi.annotations.media.Schema
import org.opendc.web.proto.OperationalPhenomena
import org.opendc.web.proto.Workload
-import javax.validation.constraints.NotBlank
/**
* A single scenario to be explored by the simulator.
@@ -40,7 +40,7 @@ public data class Scenario(
val topology: Topology.Summary,
val phenomena: OperationalPhenomena,
val schedulerName: String,
- val jobs: List<Job>
+ val jobs: List<Job>,
) {
/**
* Create a new scenario.
@@ -58,7 +58,7 @@ public data class Scenario(
val workload: Workload.Spec,
val topology: Long,
val phenomena: OperationalPhenomena,
- val schedulerName: String
+ val schedulerName: String,
)
/**
@@ -81,6 +81,6 @@ public data class Scenario(
val topology: Topology.Summary,
val phenomena: OperationalPhenomena,
val schedulerName: String,
- val jobs: List<Job>
+ val jobs: List<Job>,
)
}
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Topology.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Topology.kt
index 73748bb9..0943eaf8 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Topology.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/Topology.kt
@@ -22,10 +22,10 @@
package org.opendc.web.proto.user
+import jakarta.validation.constraints.NotBlank
import org.eclipse.microprofile.openapi.annotations.media.Schema
import org.opendc.web.proto.Room
import java.time.Instant
-import javax.validation.constraints.NotBlank
/**
* Model for an OpenDC topology.
@@ -37,7 +37,7 @@ public data class Topology(
val name: String,
val rooms: List<Room>,
val createdAt: Instant,
- val updatedAt: Instant
+ val updatedAt: Instant,
) {
/**
* Create a new topology for a project.
@@ -46,7 +46,7 @@ public data class Topology(
public data class Create(
@field:NotBlank(message = "Name must not be empty")
val name: String,
- val rooms: List<Room>
+ val rooms: List<Room>,
)
/**
@@ -70,6 +70,6 @@ public data class Topology(
val number: Int,
val name: String,
val createdAt: Instant,
- val updatedAt: Instant
+ val updatedAt: Instant,
)
}
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/User.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/User.kt
index f18cda61..33dad4ff 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/User.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/User.kt
@@ -27,5 +27,5 @@ package org.opendc.web.proto.user
*/
public data class User(
val userId: String,
- val accounting: UserAccounting
+ val accounting: UserAccounting,
)
diff --git a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/UserAccounting.kt b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/UserAccounting.kt
index 2441983a..970721eb 100644
--- a/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/UserAccounting.kt
+++ b/opendc-web/opendc-web-proto/src/main/kotlin/org/opendc/web/proto/user/UserAccounting.kt
@@ -30,5 +30,5 @@ import java.time.LocalDate
public data class UserAccounting(
val periodEnd: LocalDate,
val simulationTime: Int,
- val simulationTimeBudget: Int
+ val simulationTimeBudget: Int,
)
diff --git a/opendc-web/opendc-web-runner-quarkus-deployment/build.gradle.kts b/opendc-web/opendc-web-runner-quarkus-deployment/build.gradle.kts
index b3f1ec3b..589337f4 100644
--- a/opendc-web/opendc-web-runner-quarkus-deployment/build.gradle.kts
+++ b/opendc-web/opendc-web-runner-quarkus-deployment/build.gradle.kts
@@ -22,7 +22,7 @@
description = "Quarkus extension for the OpenDC experiment runner"
-/* Build configuration */
+// Build configuration
plugins {
`java-library-conventions`
}
diff --git a/opendc-web/opendc-web-runner-quarkus/src/main/java/org/opendc/web/runner/runtime/OpenDCRunnerRecorder.java b/opendc-web/opendc-web-runner-quarkus/src/main/java/org/opendc/web/runner/runtime/OpenDCRunnerRecorder.java
index 76f2368f..d5d524f1 100644
--- a/opendc-web/opendc-web-runner-quarkus/src/main/java/org/opendc/web/runner/runtime/OpenDCRunnerRecorder.java
+++ b/opendc-web/opendc-web-runner-quarkus/src/main/java/org/opendc/web/runner/runtime/OpenDCRunnerRecorder.java
@@ -25,8 +25,8 @@ package org.opendc.web.runner.runtime;
import io.quarkus.runtime.RuntimeValue;
import io.quarkus.runtime.ShutdownContext;
import io.quarkus.runtime.annotations.Recorder;
+import jakarta.enterprise.inject.spi.CDI;
import java.io.File;
-import javax.enterprise.inject.spi.CDI;
import org.jboss.logging.Logger;
import org.opendc.web.runner.JobManager;
import org.opendc.web.runner.OpenDCRunner;
diff --git a/opendc-web/opendc-web-runner/Dockerfile b/opendc-web/opendc-web-runner/Dockerfile
index 3f393055..22c36c65 100644
--- a/opendc-web/opendc-web-runner/Dockerfile
+++ b/opendc-web/opendc-web-runner/Dockerfile
@@ -1,4 +1,4 @@
-FROM openjdk:17-slim
+FROM openjdk:19-slim
MAINTAINER OpenDC Maintainers <opendc@atlarge-research.com>
# Obtain (cache) Gradle wrapper
@@ -11,7 +11,7 @@ RUN ./gradlew --version
COPY ./ /app/
RUN ./gradlew --no-daemon :opendc-web:opendc-web-runner:installDist
-FROM openjdk:17-slim
+FROM openjdk:19-slim
COPY --from=0 /app/opendc-web/opendc-web-runner/build/install /opt/
COPY --from=0 /app/traces /opt/opendc/traces
WORKDIR /opt/opendc
diff --git a/opendc-web/opendc-web-runner/build.gradle.kts b/opendc-web/opendc-web-runner/build.gradle.kts
index 0a6ce658..38492929 100644
--- a/opendc-web/opendc-web-runner/build.gradle.kts
+++ b/opendc-web/opendc-web-runner/build.gradle.kts
@@ -22,7 +22,7 @@
description = "Experiment runner for OpenDC"
-/* Build configuration */
+// Build configuration
plugins {
`kotlin-library-conventions`
distribution
@@ -74,7 +74,7 @@ val createCli by tasks.creating(CreateStartScripts::class) {
applicationName = "opendc-runner"
mainClass.set("org.opendc.web.runner.cli.MainKt")
classpath = cliJar.outputs.files + cliRuntimeClasspath
- outputDir = project.buildDir.resolve("scripts")
+ outputDir = project.layout.buildDirectory.get().asFile.resolve("scripts")
}
distributions {
diff --git a/opendc-web/opendc-web-runner/src/cli/kotlin/org/opendc/web/runner/Main.kt b/opendc-web/opendc-web-runner/src/cli/kotlin/org/opendc/web/runner/Main.kt
index 299c4d09..5d35fd98 100644
--- a/opendc-web/opendc-web-runner/src/cli/kotlin/org/opendc/web/runner/Main.kt
+++ b/opendc-web/opendc-web-runner/src/cli/kotlin/org/opendc/web/runner/Main.kt
@@ -48,7 +48,7 @@ class RunnerCli : CliktCommand(name = "opendc-runner") {
private val apiUrl by option(
"--api-url",
help = "url to the OpenDC API",
- envvar = "OPENDC_API_URL"
+ envvar = "OPENDC_API_URL",
)
.convert { URI(it) }
.default(URI("https://api.opendc.org/v2"))
@@ -59,7 +59,7 @@ class RunnerCli : CliktCommand(name = "opendc-runner") {
private val authDomain by option(
"--auth-domain",
help = "auth domain of the OpenDC API",
- envvar = "AUTH0_DOMAIN"
+ envvar = "AUTH0_DOMAIN",
)
.required()
@@ -69,7 +69,7 @@ class RunnerCli : CliktCommand(name = "opendc-runner") {
private val authAudience by option(
"--auth-audience",
help = "auth audience of the OpenDC API",
- envvar = "AUTH0_AUDIENCE"
+ envvar = "AUTH0_AUDIENCE",
)
.required()
@@ -79,7 +79,7 @@ class RunnerCli : CliktCommand(name = "opendc-runner") {
private val authClientId by option(
"--auth-id",
help = "auth client id of the OpenDC API",
- envvar = "AUTH0_CLIENT_ID"
+ envvar = "AUTH0_CLIENT_ID",
)
.required()
@@ -89,7 +89,7 @@ class RunnerCli : CliktCommand(name = "opendc-runner") {
private val authClientSecret by option(
"--auth-secret",
help = "auth client secret of the OpenDC API",
- envvar = "AUTH0_CLIENT_SECRET"
+ envvar = "AUTH0_CLIENT_SECRET",
)
.required()
@@ -99,7 +99,7 @@ class RunnerCli : CliktCommand(name = "opendc-runner") {
private val tracePath by option(
"--traces",
help = "path to the directory containing the traces",
- envvar = "OPENDC_TRACES"
+ envvar = "OPENDC_TRACES",
)
.file(canBeFile = false)
.defaultLazy { File("traces/") }
@@ -109,7 +109,7 @@ class RunnerCli : CliktCommand(name = "opendc-runner") {
*/
private val parallelism by option(
"--parallelism",
- help = "maximum number of threads for simulations"
+ help = "maximum number of threads for simulations",
)
.int()
.default(Runtime.getRuntime().availableProcessors() - 1)
diff --git a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/JobManager.kt b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/JobManager.kt
index d6c06889..a517f3b4 100644
--- a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/JobManager.kt
+++ b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/JobManager.kt
@@ -47,17 +47,27 @@ public interface JobManager {
* @param runtime The total runtime of the job.
* @return `true` if the job can continue, `false` if the job has been cancelled.
*/
- public fun heartbeat(id: Long, runtime: Int): Boolean
+ public fun heartbeat(
+ id: Long,
+ runtime: Int,
+ ): Boolean
/**
* Mark the job as failed.
*/
- public fun fail(id: Long, runtime: Int)
+ public fun fail(
+ id: Long,
+ runtime: Int,
+ )
/**
* Persist the specified results for the specified job.
*/
- public fun finish(id: Long, runtime: Int, results: Map<String, Any>)
+ public fun finish(
+ id: Long,
+ runtime: Int,
+ results: Map<String, Any>,
+ )
public companion object {
/**
diff --git a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt
index 4351f3c1..eee340cf 100644
--- a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt
+++ b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/OpenDCRunner.kt
@@ -76,7 +76,7 @@ public class OpenDCRunner(
parallelism: Int = Runtime.getRuntime().availableProcessors(),
private val jobTimeout: Duration = Duration.ofMinutes(10),
private val pollInterval: Duration = Duration.ofSeconds(30),
- private val heartbeatInterval: Duration = Duration.ofMinutes(1)
+ private val heartbeatInterval: Duration = Duration.ofMinutes(1),
) : Runnable {
/**
* Logging instance for this runner.
@@ -149,26 +149,28 @@ public class OpenDCRunner(
val startTime = Instant.now()
val currentThread = Thread.currentThread()
- val heartbeat = scheduler.scheduleWithFixedDelay(
- {
- if (!manager.heartbeat(id, startTime.secondsSince())) {
- currentThread.interrupt()
- }
- },
- 0,
- heartbeatInterval.toMillis(),
- TimeUnit.MILLISECONDS
- )
+ val heartbeat =
+ scheduler.scheduleWithFixedDelay(
+ {
+ if (!manager.heartbeat(id, startTime.secondsSince())) {
+ currentThread.interrupt()
+ }
+ },
+ 0,
+ heartbeatInterval.toMillis(),
+ TimeUnit.MILLISECONDS,
+ )
try {
val topology = convertTopology(scenario.topology)
- val jobs = (0 until scenario.portfolio.targets.repeats).map { repeat ->
- SimulationTask(
- scenario,
- repeat,
- topology
- )
- }
+ val jobs =
+ (0 until scenario.portfolio.targets.repeats).map { repeat ->
+ SimulationTask(
+ scenario,
+ repeat,
+ topology,
+ )
+ }
val results = invokeAll(jobs).map { it.rawResult }
heartbeat.cancel(true)
@@ -194,8 +196,8 @@ public class OpenDCRunner(
"total_vms_submitted" to results.map { it.totalVmsSubmitted },
"total_vms_queued" to results.map { it.totalVmsQueued },
"total_vms_finished" to results.map { it.totalVmsFinished },
- "total_vms_failed" to results.map { it.totalVmsFailed }
- )
+ "total_vms_failed" to results.map { it.totalVmsFailed },
+ ),
)
} catch (e: Exception) {
// Check whether the job failed due to exceeding its time budget
@@ -232,7 +234,7 @@ public class OpenDCRunner(
private inner class SimulationTask(
private val scenario: Scenario,
private val repeat: Int,
- private val topology: List<HostSpec>
+ private val topology: List<HostSpec>,
) : RecursiveTask<WebComputeMonitor.Results>() {
override fun compute(): WebComputeMonitor.Results {
val monitor = WebComputeMonitor()
@@ -254,50 +256,51 @@ public class OpenDCRunner(
/**
* Run a single simulation of the scenario.
*/
- private fun runSimulation(monitor: WebComputeMonitor) = runSimulation {
- val serviceDomain = "compute.opendc.org"
- val seed = repeat.toLong()
-
- val scenario = scenario
-
- Provisioner(dispatcher, seed).use { provisioner ->
- provisioner.runSteps(
- setupComputeService(
- serviceDomain,
- { createComputeScheduler(scenario.schedulerName, Random(it.seeder.nextLong())) }
- ),
- registerComputeMonitor(serviceDomain, monitor),
- setupHosts(serviceDomain, topology)
- )
-
- val service = provisioner.registry.resolve(serviceDomain, ComputeService::class.java)!!
-
- val workload =
- trace(scenario.workload.trace.id).sampleByLoad(scenario.workload.samplingFraction)
- val vms = workload.resolve(workloadLoader, Random(seed))
+ private fun runSimulation(monitor: WebComputeMonitor) =
+ runSimulation {
+ val serviceDomain = "compute.opendc.org"
+ val seed = repeat.toLong()
+
+ val scenario = scenario
+
+ Provisioner(dispatcher, seed).use { provisioner ->
+ provisioner.runSteps(
+ setupComputeService(
+ serviceDomain,
+ { createComputeScheduler(scenario.schedulerName, Random(it.seeder.nextLong())) },
+ ),
+ registerComputeMonitor(serviceDomain, monitor),
+ setupHosts(serviceDomain, topology),
+ )
- val phenomena = scenario.phenomena
- val failureModel =
- if (phenomena.failures) {
- grid5000(Duration.ofDays(7))
- } else {
- null
+ val service = provisioner.registry.resolve(serviceDomain, ComputeService::class.java)!!
+
+ val workload =
+ trace(scenario.workload.trace.id).sampleByLoad(scenario.workload.samplingFraction)
+ val vms = workload.resolve(workloadLoader, Random(seed))
+
+ val phenomena = scenario.phenomena
+ val failureModel =
+ if (phenomena.failures) {
+ grid5000(Duration.ofDays(7))
+ } else {
+ null
+ }
+
+ // Run workload trace
+ service.replay(timeSource, vms, seed, failureModel = failureModel, interference = phenomena.interference)
+
+ val serviceMetrics = service.getSchedulerStats()
+ logger.debug {
+ "Scheduler " +
+ "Success=${serviceMetrics.attemptsSuccess} " +
+ "Failure=${serviceMetrics.attemptsFailure} " +
+ "Error=${serviceMetrics.attemptsError} " +
+ "Pending=${serviceMetrics.serversPending} " +
+ "Active=${serviceMetrics.serversActive}"
}
-
- // Run workload trace
- service.replay(timeSource, vms, seed, failureModel = failureModel, interference = phenomena.interference)
-
- val serviceMetrics = service.getSchedulerStats()
- logger.debug {
- "Scheduler " +
- "Success=${serviceMetrics.attemptsSuccess} " +
- "Failure=${serviceMetrics.attemptsFailure} " +
- "Error=${serviceMetrics.attemptsError} " +
- "Pending=${serviceMetrics.serversPending} " +
- "Active=${serviceMetrics.serversActive}"
}
}
- }
}
/**
@@ -307,46 +310,50 @@ public class OpenDCRunner(
val res = mutableListOf<HostSpec>()
val random = Random(0)
- val machines = topology.rooms.asSequence()
- .flatMap { room ->
- room.tiles.flatMap { tile ->
- val rack = tile.rack
- rack?.machines?.map { machine -> rack to machine } ?: emptyList()
+ val machines =
+ topology.rooms.asSequence()
+ .flatMap { room ->
+ room.tiles.flatMap { tile ->
+ val rack = tile.rack
+ rack?.machines?.map { machine -> rack to machine } ?: emptyList()
+ }
}
- }
for ((rack, machine) in machines) {
val clusterId = rack.id
val position = machine.position
- val processors = machine.cpus.flatMap { cpu ->
- val cores = cpu.numberOfCores
- val speed = cpu.clockRateMhz
- // TODO Remove hard coding of vendor
- val node = ProcessingNode("Intel", "amd64", cpu.name, cores)
- List(cores) { coreId ->
- ProcessingUnit(node, coreId, speed)
+ val processors =
+ machine.cpus.flatMap { cpu ->
+ val cores = cpu.numberOfCores
+ val speed = cpu.clockRateMhz
+ // TODO Remove hard coding of vendor
+ val node = ProcessingNode("Intel", "amd64", cpu.name, cores)
+ List(cores) { coreId ->
+ ProcessingUnit(node, coreId, speed)
+ }
+ }
+ val memoryUnits =
+ machine.memory.map { memory ->
+ MemoryUnit(
+ "Samsung",
+ memory.name,
+ memory.speedMbPerS,
+ memory.sizeMb.toLong(),
+ )
}
- }
- val memoryUnits = machine.memory.map { memory ->
- MemoryUnit(
- "Samsung",
- memory.name,
- memory.speedMbPerS,
- memory.sizeMb.toLong()
- )
- }
val energyConsumptionW = machine.cpus.sumOf { it.energyConsumptionW }
val powerModel = CpuPowerModels.linear(2 * energyConsumptionW, energyConsumptionW * 0.5)
- val spec = HostSpec(
- UUID(random.nextLong(), random.nextLong()),
- "node-$clusterId-$position",
- mapOf("cluster" to clusterId),
- MachineModel(processors, memoryUnits),
- SimPsuFactories.simple(powerModel)
- )
+ val spec =
+ HostSpec(
+ UUID(random.nextLong(), random.nextLong()),
+ "node-$clusterId-$position",
+ mapOf("cluster" to clusterId),
+ MachineModel(processors, memoryUnits),
+ SimPsuFactories.simple(powerModel),
+ )
res += spec
}
@@ -358,10 +365,11 @@ public class OpenDCRunner(
* A custom [ForkJoinWorkerThreadFactory] that uses the [ClassLoader] of specified by the runner.
*/
private class RunnerThreadFactory(private val classLoader: ClassLoader) : ForkJoinWorkerThreadFactory {
- override fun newThread(pool: ForkJoinPool): ForkJoinWorkerThread = object : ForkJoinWorkerThread(pool) {
- init {
- contextClassLoader = classLoader
+ override fun newThread(pool: ForkJoinPool): ForkJoinWorkerThread =
+ object : ForkJoinWorkerThread(pool) {
+ init {
+ contextClassLoader = classLoader
+ }
}
- }
}
}
diff --git a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/internal/JobManagerImpl.kt b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/internal/JobManagerImpl.kt
index 5b1b7132..7081041c 100644
--- a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/internal/JobManagerImpl.kt
+++ b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/internal/JobManagerImpl.kt
@@ -44,16 +44,26 @@ internal class JobManagerImpl(private val client: OpenDCRunnerClient) : JobManag
}
}
- override fun heartbeat(id: Long, runtime: Int): Boolean {
+ override fun heartbeat(
+ id: Long,
+ runtime: Int,
+ ): Boolean {
val res = client.jobs.update(id, Job.Update(JobState.RUNNING, runtime))
return res?.state != JobState.FAILED
}
- override fun fail(id: Long, runtime: Int) {
+ override fun fail(
+ id: Long,
+ runtime: Int,
+ ) {
client.jobs.update(id, Job.Update(JobState.FAILED, runtime))
}
- override fun finish(id: Long, runtime: Int, results: Map<String, Any>) {
+ override fun finish(
+ id: Long,
+ runtime: Int,
+ results: Map<String, Any>,
+ ) {
client.jobs.update(id, Job.Update(JobState.FINISHED, runtime))
}
}
diff --git a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/internal/WebComputeMonitor.kt b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/internal/WebComputeMonitor.kt
index 774689c9..4576a463 100644
--- a/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/internal/WebComputeMonitor.kt
+++ b/opendc-web/opendc-web-runner/src/main/kotlin/org/opendc/web/runner/internal/WebComputeMonitor.kt
@@ -34,31 +34,32 @@ import kotlin.math.roundToLong
*/
internal class WebComputeMonitor : ComputeMonitor {
override fun record(reader: HostTableReader) {
- val slices = reader.downtime / SLICE_LENGTH
+ val slices = reader.downtime / sliceLength
- hostAggregateMetrics = AggregateHostMetrics(
- hostAggregateMetrics.totalActiveTime + reader.cpuActiveTime,
- hostAggregateMetrics.totalIdleTime + reader.cpuIdleTime,
- hostAggregateMetrics.totalStealTime + reader.cpuStealTime,
- hostAggregateMetrics.totalLostTime + reader.cpuLostTime,
- hostAggregateMetrics.totalPowerDraw + reader.energyUsage,
- hostAggregateMetrics.totalFailureSlices + slices,
- hostAggregateMetrics.totalFailureVmSlices + reader.guestsRunning * slices
- )
+ hostAggregateMetrics =
+ AggregateHostMetrics(
+ hostAggregateMetrics.totalActiveTime + reader.cpuActiveTime,
+ hostAggregateMetrics.totalIdleTime + reader.cpuIdleTime,
+ hostAggregateMetrics.totalStealTime + reader.cpuStealTime,
+ hostAggregateMetrics.totalLostTime + reader.cpuLostTime,
+ hostAggregateMetrics.totalPowerDraw + reader.energyUsage,
+ hostAggregateMetrics.totalFailureSlices + slices,
+ hostAggregateMetrics.totalFailureVmSlices + reader.guestsRunning * slices,
+ )
hostMetrics.compute(reader.host.id) { _, prev ->
HostMetrics(
reader.cpuUsage + (prev?.cpuUsage ?: 0.0),
reader.cpuDemand + (prev?.cpuDemand ?: 0.0),
reader.guestsRunning + (prev?.instanceCount ?: 0),
- 1 + (prev?.count ?: 0)
+ 1 + (prev?.count ?: 0),
)
}
}
private var hostAggregateMetrics: AggregateHostMetrics = AggregateHostMetrics()
private val hostMetrics: MutableMap<String, HostMetrics> = mutableMapOf()
- private val SLICE_LENGTH: Long = 5 * 60L
+ private val sliceLength: Long = 5 * 60L
private data class AggregateHostMetrics(
val totalActiveTime: Long = 0L,
@@ -67,14 +68,14 @@ internal class WebComputeMonitor : ComputeMonitor {
val totalLostTime: Long = 0L,
val totalPowerDraw: Double = 0.0,
val totalFailureSlices: Double = 0.0,
- val totalFailureVmSlices: Double = 0.0
+ val totalFailureVmSlices: Double = 0.0,
)
private data class HostMetrics(
val cpuUsage: Double,
val cpuDemand: Double,
val instanceCount: Long,
- val count: Long
+ val count: Long,
)
private lateinit var serviceData: ServiceData
@@ -106,7 +107,7 @@ internal class WebComputeMonitor : ComputeMonitor {
serviceData.serversTotal,
serviceData.serversPending,
serviceData.serversTotal - serviceData.serversPending - serviceData.serversActive,
- serviceData.attemptsError + serviceData.attemptsFailure
+ serviceData.attemptsError + serviceData.attemptsFailure,
)
}
@@ -128,6 +129,6 @@ internal class WebComputeMonitor : ComputeMonitor {
val totalVmsSubmitted: Int,
val totalVmsQueued: Int,
val totalVmsFinished: Int,
- val totalVmsFailed: Int
+ val totalVmsFailed: Int,
)
}
diff --git a/opendc-web/opendc-web-server/Dockerfile b/opendc-web/opendc-web-server/Dockerfile
index 8aa54291..bcdb831e 100644
--- a/opendc-web/opendc-web-server/Dockerfile
+++ b/opendc-web/opendc-web-server/Dockerfile
@@ -1,4 +1,4 @@
-FROM openjdk:17-slim
+FROM openjdk:19-slim
MAINTAINER OpenDC Maintainers <opendc@atlarge-research.com>
# Obtain (cache) Gradle wrapper
@@ -19,7 +19,7 @@ ENV OPENDC_AUTH0_DOCS_CLIENT_ID=$OPENDC_AUTH0_DOCS_CLIENT_ID
COPY ./ /app/
RUN ./gradlew --no-daemon :opendc-web:opendc-web-server:quarkusBuild -Dquarkus.profile=docker
-FROM openjdk:17-slim
+FROM openjdk:19-slim
COPY --from=0 /app/opendc-web/opendc-web-server/build/quarkus-app /opt/opendc
WORKDIR /opt/opendc
CMD java -jar quarkus-run.jar
diff --git a/opendc-web/opendc-web-server/build.gradle.kts b/opendc-web/opendc-web-server/build.gradle.kts
index 8a6d8c0b..484e98c0 100644
--- a/opendc-web/opendc-web-server/build.gradle.kts
+++ b/opendc-web/opendc-web-server/build.gradle.kts
@@ -22,7 +22,7 @@
description = "Web server of OpenDC"
-/* Build configuration */
+// Build configuration
plugins {
`quarkus-conventions`
distribution
@@ -34,7 +34,7 @@ dependencies {
implementation(projects.opendcWeb.opendcWebProto)
testImplementation("junit:junit:4.13.1")
testImplementation("junit:junit:4.13.1")
- compileOnly(projects.opendcWeb.opendcWebUiQuarkusDeployment) /* Temporary fix for Quarkus/Gradle issues */
+ compileOnly(projects.opendcWeb.opendcWebUiQuarkusDeployment) // Temporary fix for Quarkus/Gradle issues
compileOnly(projects.opendcWeb.opendcWebRunnerQuarkusDeployment)
implementation(projects.opendcWeb.opendcWebUiQuarkus)
implementation(projects.opendcWeb.opendcWebRunnerQuarkus)
@@ -68,7 +68,7 @@ val createStartScripts by tasks.creating(CreateStartScripts::class) {
applicationName = "opendc-server"
mainClass.set("io.quarkus.bootstrap.runner.QuarkusEntryPoint")
classpath = files("lib/quarkus-run.jar")
- outputDir = project.buildDir.resolve("scripts")
+ outputDir = project.layout.buildDirectory.get().asFile.resolve("scripts")
}
distributions {
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Job.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Job.java
index c5fb208e..a0ac390f 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Job.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Job.java
@@ -22,23 +22,14 @@
package org.opendc.web.server.model;
+import io.hypersistence.utils.hibernate.type.json.JsonType;
import io.quarkus.hibernate.orm.panache.Panache;
-import io.quarkus.hibernate.orm.panache.PanacheEntity;
+import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
import io.quarkus.hibernate.orm.panache.PanacheQuery;
import io.quarkus.panache.common.Parameters;
+import jakarta.persistence.*;
import java.time.Instant;
import java.util.Map;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.FetchType;
-import javax.persistence.ForeignKey;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
import org.hibernate.annotations.Type;
import org.opendc.web.proto.JobState;
@@ -46,7 +37,7 @@ import org.opendc.web.proto.JobState;
* A simulation job to be run by the simulator.
*/
@Entity
-@Table(name = "jobs")
+@Table
@NamedQueries({
@NamedQuery(
name = "Job.updateOne",
@@ -57,7 +48,16 @@ import org.opendc.web.proto.JobState;
WHERE j.id = :id AND j.state = :oldState
""")
})
-public class Job extends PanacheEntity {
+public class Job extends PanacheEntityBase {
+ /**
+ * The main ID of a project.
+ * The value starts at 6 to account for the other 5 projects already made by the loading script.
+ */
+ @Id
+ @SequenceGenerator(name = "jobSeq", sequenceName = "job_id_seq", allocationSize = 1, initialValue = 3)
+ @GeneratedValue(generator = "jobSeq")
+ public Long id;
+
@ManyToOne(optional = false, fetch = FetchType.EAGER)
@JoinColumn(name = "scenario_id", foreignKey = @ForeignKey(name = "fk_jobs_scenario"), nullable = false)
public Scenario scenario;
@@ -83,9 +83,8 @@ public class Job extends PanacheEntity {
/**
* The state of the job.
*/
- @Type(type = "io.hypersistence.utils.hibernate.type.basic.PostgreSQLEnumType")
- @Column(nullable = false, columnDefinition = "enum")
@Enumerated(EnumType.STRING)
+ @Column(nullable = false)
public JobState state = JobState.PENDING;
/**
@@ -97,8 +96,8 @@ public class Job extends PanacheEntity {
/**
* Experiment results in JSON
*/
- @Type(type = "io.hypersistence.utils.hibernate.type.json.JsonType")
@Column(columnDefinition = "jsonb")
+ @Type(JsonType.class)
public Map<String, ?> results = null;
/**
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Portfolio.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Portfolio.java
index 3a406683..c2695192 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Portfolio.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Portfolio.java
@@ -22,23 +22,27 @@
package org.opendc.web.server.model;
-import io.quarkus.hibernate.orm.panache.PanacheEntity;
+import io.hypersistence.utils.hibernate.type.json.JsonType;
+import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
import io.quarkus.hibernate.orm.panache.PanacheQuery;
import io.quarkus.panache.common.Parameters;
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.Id;
+import jakarta.persistence.Index;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.NamedQueries;
+import jakarta.persistence.NamedQuery;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.OrderBy;
+import jakarta.persistence.SequenceGenerator;
+import jakarta.persistence.Table;
+import jakarta.persistence.UniqueConstraint;
import java.util.HashSet;
import java.util.Set;
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Index;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.OneToMany;
-import javax.persistence.OrderBy;
-import javax.persistence.Table;
-import javax.persistence.UniqueConstraint;
import org.hibernate.annotations.Type;
import org.opendc.web.proto.Targets;
@@ -47,7 +51,6 @@ import org.opendc.web.proto.Targets;
*/
@Entity
@Table(
- name = "portfolios",
uniqueConstraints = {
@UniqueConstraint(
name = "uk_portfolios_number",
@@ -60,7 +63,17 @@ import org.opendc.web.proto.Targets;
name = "Portfolio.findOneByProject",
query = "SELECT p FROM Portfolio p WHERE p.project.id = :projectId AND p.number = :number")
})
-public class Portfolio extends PanacheEntity {
+public class Portfolio extends PanacheEntityBase {
+
+ /**
+ * The main ID of a project.
+ * The value starts at 6 to account for the other 5 projects already made by the loading script.
+ */
+ @Id
+ @SequenceGenerator(name = "portfolioSeq", sequenceName = "portfolio_id_seq", allocationSize = 1, initialValue = 4)
+ @GeneratedValue(generator = "portfolioSeq")
+ public Long id;
+
/**
* The {@link Project} this portfolio belongs to.
*/
@@ -83,8 +96,8 @@ public class Portfolio extends PanacheEntity {
/**
* The portfolio targets (metrics, repetitions).
*/
- @Type(type = "io.hypersistence.utils.hibernate.type.json.JsonType")
@Column(columnDefinition = "jsonb", nullable = false, updatable = false)
+ @Type(JsonType.class)
public Targets targets;
/**
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Project.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Project.java
index 5836e33f..f4e5305d 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Project.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Project.java
@@ -23,25 +23,28 @@
package org.opendc.web.server.model;
import io.quarkus.hibernate.orm.panache.Panache;
-import io.quarkus.hibernate.orm.panache.PanacheEntity;
+import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
import io.quarkus.panache.common.Parameters;
+import jakarta.persistence.CascadeType;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.Id;
+import jakarta.persistence.NamedQueries;
+import jakarta.persistence.NamedQuery;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.OrderBy;
+import jakarta.persistence.SequenceGenerator;
+import jakarta.persistence.Table;
import java.time.Instant;
import java.util.HashSet;
import java.util.Set;
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.OneToMany;
-import javax.persistence.OrderBy;
-import javax.persistence.Table;
/**
* A project in OpenDC encapsulates all the datacenter designs and simulation runs for a set of users.
*/
@Entity
-@Table(name = "projects")
+@Table
@NamedQueries({
@NamedQuery(
name = "Project.findByUser",
@@ -49,7 +52,7 @@ import javax.persistence.Table;
"""
SELECT a
FROM ProjectAuthorization a
- WHERE a.key.userId = :userId
+ WHERE a.key.userName = :userName
"""),
@NamedQuery(
name = "Project.allocatePortfolio",
@@ -76,7 +79,17 @@ import javax.persistence.Table;
WHERE p.id = :id AND p.scenariosCreated = :oldState
""")
})
-public class Project extends PanacheEntity {
+public class Project extends PanacheEntityBase {
+
+ /**
+ * The main ID of a project.
+ * The value starts at 6 to account for the other 5 projects already made by the loading script.
+ */
+ @Id
+ @SequenceGenerator(name = "projectSeq", sequenceName = "project_id_seq", allocationSize = 1, initialValue = 7)
+ @GeneratedValue(generator = "projectSeq")
+ public Long id;
+
/**
* The name of the project.
*/
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/ProjectAuthorization.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/ProjectAuthorization.java
index 1238f58d..3776ae12 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/ProjectAuthorization.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/ProjectAuthorization.java
@@ -25,30 +25,29 @@ package org.opendc.web.server.model;
import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
import io.quarkus.hibernate.orm.panache.PanacheQuery;
import io.quarkus.panache.common.Parameters;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.EmbeddedId;
+import jakarta.persistence.Entity;
+import jakarta.persistence.EnumType;
+import jakarta.persistence.Enumerated;
+import jakarta.persistence.FetchType;
+import jakarta.persistence.ForeignKey;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.MapsId;
+import jakarta.persistence.NamedQueries;
+import jakarta.persistence.NamedQuery;
+import jakarta.persistence.Table;
import java.io.Serializable;
import java.util.Objects;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.EmbeddedId;
-import javax.persistence.Entity;
-import javax.persistence.EnumType;
-import javax.persistence.Enumerated;
-import javax.persistence.FetchType;
-import javax.persistence.ForeignKey;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.MapsId;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import org.hibernate.annotations.Type;
import org.opendc.web.proto.user.ProjectRole;
/**
* An authorization for some user to participate in a project.
*/
@Entity
-@Table(name = "project_authorizations")
+@Table
@NamedQueries({
@NamedQuery(
name = "ProjectAuthorization.findByUser",
@@ -56,7 +55,7 @@ import org.opendc.web.proto.user.ProjectRole;
"""
SELECT a
FROM ProjectAuthorization a
- WHERE a.key.userId = :userId
+ WHERE a.key.userName = :userName
"""),
})
public class ProjectAuthorization extends PanacheEntityBase {
@@ -82,16 +81,15 @@ public class ProjectAuthorization extends PanacheEntityBase {
/**
* The role of the user in the project.
*/
- @Type(type = "io.hypersistence.utils.hibernate.type.basic.PostgreSQLEnumType")
- @Column(nullable = false, columnDefinition = "enum")
+ @Column(nullable = false)
@Enumerated(EnumType.STRING)
public ProjectRole role;
/**
* Construct a {@link ProjectAuthorization} object.
*/
- public ProjectAuthorization(Project project, String userId, ProjectRole role) {
- this.key = new ProjectAuthorization.Key(project.id, userId);
+ public ProjectAuthorization(Project project, String userName, ProjectRole role) {
+ this.key = new ProjectAuthorization.Key(project.id, userName);
this.project = project;
this.role = role;
}
@@ -102,25 +100,25 @@ public class ProjectAuthorization extends PanacheEntityBase {
protected ProjectAuthorization() {}
/**
- * List all projects for the user with the specified <code>userId</code>.
+ * List all projects for the user with the specified <code>userName</code>.
*
- * @param userId The identifier of the user that is requesting the list of projects.
+ * @param userName The identifier of the user that is requesting the list of projects.
* @return A query returning projects that the user has received authorization for.
*/
- public static PanacheQuery<ProjectAuthorization> findByUser(String userId) {
- return find("#ProjectAuthorization.findByUser", Parameters.with("userId", userId));
+ public static PanacheQuery<ProjectAuthorization> findByUser(String userName) {
+ return find("#ProjectAuthorization.findByUser", Parameters.with("userName", userName));
}
/**
- * Find the project with <code>id</code> for the user with the specified <code>userId</code>.
+ * Find the project with <code>id</code> for the user with the specified <code>userName</code>.
*
- * @param userId The identifier of the user that is requesting the list of projects.
- * @param id The unique identifier of the project.
+ * @param userName The identifier of the user that is requesting the list of projects.
+ * @param project_id The unique identifier of the project.
* @return The project with the specified identifier or <code>null</code> if it does not exist or is not accessible
* to the user with the specified identifier.
*/
- public static ProjectAuthorization findByUser(String userId, long id) {
- return findById(new ProjectAuthorization.Key(id, userId));
+ public static ProjectAuthorization findByUser(String userName, long project_id) {
+ return findById(new ProjectAuthorization.Key(project_id, userName));
}
/**
@@ -148,12 +146,12 @@ public class ProjectAuthorization extends PanacheEntityBase {
@Column(name = "project_id", nullable = false)
public long projectId;
- @Column(name = "user_id", nullable = false)
- public String userId;
+ @Column(name = "user_name", nullable = false)
+ public String userName;
- public Key(long projectId, String userId) {
+ public Key(long projectId, String userName) {
this.projectId = projectId;
- this.userId = userId;
+ this.userName = userName;
}
protected Key() {}
@@ -163,12 +161,12 @@ public class ProjectAuthorization extends PanacheEntityBase {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Key key = (Key) o;
- return projectId == key.projectId && userId.equals(key.userId);
+ return projectId == key.projectId && userName.equals(key.userName);
}
@Override
public int hashCode() {
- return Objects.hash(projectId, userId);
+ return Objects.hash(projectId, userName);
}
}
}
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Scenario.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Scenario.java
index 016e931b..c79ef5bb 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Scenario.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Scenario.java
@@ -22,25 +22,13 @@
package org.opendc.web.server.model;
-import io.quarkus.hibernate.orm.panache.PanacheEntity;
+import io.hypersistence.utils.hibernate.type.json.JsonType;
+import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
import io.quarkus.hibernate.orm.panache.PanacheQuery;
import io.quarkus.panache.common.Parameters;
+import jakarta.persistence.*;
import java.util.ArrayList;
import java.util.List;
-import javax.persistence.CascadeType;
-import javax.persistence.Column;
-import javax.persistence.Embedded;
-import javax.persistence.Entity;
-import javax.persistence.FetchType;
-import javax.persistence.ForeignKey;
-import javax.persistence.Index;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.OneToMany;
-import javax.persistence.Table;
-import javax.persistence.UniqueConstraint;
import org.hibernate.annotations.Type;
import org.opendc.web.proto.OperationalPhenomena;
@@ -49,7 +37,6 @@ import org.opendc.web.proto.OperationalPhenomena;
*/
@Entity
@Table(
- name = "scenarios",
uniqueConstraints = {
@UniqueConstraint(
name = "uk_scenarios_number",
@@ -71,7 +58,16 @@ import org.opendc.web.proto.OperationalPhenomena;
name = "Scenario.findOneByProject",
query = "SELECT s FROM Scenario s WHERE s.project.id = :projectId AND s.number = :number")
})
-public class Scenario extends PanacheEntity {
+public class Scenario extends PanacheEntityBase {
+ /**
+ * The main ID of a Scenario.
+ * The value starts at 3 to account for the other 2 scenarios already made by the loading script.
+ */
+ @Id
+ @SequenceGenerator(name = "scenarioSeq", sequenceName = "scenario_id_seq", allocationSize = 1, initialValue = 3)
+ @GeneratedValue(generator = "scenarioSeq")
+ public Long id;
+
/**
* The {@link Project} to which this scenario belongs.
*/
@@ -113,9 +109,11 @@ public class Scenario extends PanacheEntity {
/**
* Operational phenomena activated in the scenario.
+ * @Column(columnDefinition = "jsonb", nullable = false, updatable = false)
+ * @Type(JsonType.class)
*/
- @Type(type = "io.hypersistence.utils.hibernate.type.json.JsonType")
@Column(columnDefinition = "jsonb", nullable = false, updatable = false)
+ @Type(JsonType.class)
public OperationalPhenomena phenomena;
/**
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Topology.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Topology.java
index 05a1ac12..8a4e2ae2 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Topology.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Topology.java
@@ -22,20 +22,24 @@
package org.opendc.web.server.model;
-import io.quarkus.hibernate.orm.panache.PanacheEntity;
+import io.hypersistence.utils.hibernate.type.json.JsonType;
+import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
import io.quarkus.hibernate.orm.panache.PanacheQuery;
import io.quarkus.panache.common.Parameters;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.Id;
+import jakarta.persistence.Index;
+import jakarta.persistence.JoinColumn;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.NamedQueries;
+import jakarta.persistence.NamedQuery;
+import jakarta.persistence.SequenceGenerator;
+import jakarta.persistence.Table;
+import jakarta.persistence.UniqueConstraint;
import java.time.Instant;
import java.util.List;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Index;
-import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
-import javax.persistence.UniqueConstraint;
import org.hibernate.annotations.Type;
import org.opendc.web.proto.Room;
@@ -44,7 +48,6 @@ import org.opendc.web.proto.Room;
*/
@Entity
@Table(
- name = "topologies",
uniqueConstraints = {
@UniqueConstraint(
name = "uk_topologies_number",
@@ -57,7 +60,16 @@ import org.opendc.web.proto.Room;
name = "Topology.findOneByProject",
query = "SELECT t FROM Topology t WHERE t.project.id = :projectId AND t.number = :number")
})
-public class Topology extends PanacheEntity {
+public class Topology extends PanacheEntityBase {
+ /**
+ * The main ID of a project.
+ * The value starts at 6 to account for the other 5 projects already made by the loading script.
+ */
+ @Id
+ @SequenceGenerator(name = "topologySeq", sequenceName = "topology_id_seq", allocationSize = 1, initialValue = 5)
+ @GeneratedValue(generator = "topologySeq")
+ public Long id;
+
/**
* The {@link Project} to which the topology belongs.
*/
@@ -91,9 +103,11 @@ public class Topology extends PanacheEntity {
/**
* Datacenter design in JSON
+ * @Column(columnDefinition = "jsonb", nullable = false)
+ * @Type(JsonType.class)
*/
- @Type(type = "io.hypersistence.utils.hibernate.type.json.JsonType")
@Column(columnDefinition = "jsonb", nullable = false)
+ @Type(JsonType.class)
public List<Room> rooms;
/**
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Trace.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Trace.java
index 36d27abc..71c647bc 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Trace.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Trace.java
@@ -23,16 +23,16 @@
package org.opendc.web.server.model;
import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.Table;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
/**
* A workload trace available for simulation.
*/
@Entity
-@Table(name = "traces")
+@Table
public class Trace extends PanacheEntityBase {
/**
* The unique identifier of the trace.
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/UserAccounting.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/UserAccounting.java
index fda4302f..10a10ef9 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/UserAccounting.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/UserAccounting.java
@@ -24,19 +24,19 @@ package org.opendc.web.server.model;
import io.quarkus.hibernate.orm.panache.PanacheEntityBase;
import io.quarkus.panache.common.Parameters;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.NamedQueries;
+import jakarta.persistence.NamedQuery;
+import jakarta.persistence.Table;
import java.time.LocalDate;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.NamedQueries;
-import javax.persistence.NamedQuery;
-import javax.persistence.Table;
/**
* Entity to track the number of simulation minutes used by a user.
*/
@Entity
-@Table(name = "user_accounting")
+@Table
@NamedQueries({
@NamedQuery(
name = "UserAccounting.consumeBudget",
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Workload.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Workload.java
index 129fb0c5..fd7010d2 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Workload.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/model/Workload.java
@@ -22,9 +22,9 @@
package org.opendc.web.server.model;
-import javax.persistence.Column;
-import javax.persistence.Embeddable;
-import javax.persistence.ManyToOne;
+import jakarta.persistence.Column;
+import jakarta.persistence.Embeddable;
+import jakarta.persistence.ManyToOne;
/**
* Specification of the workload for a {@link Scenario}
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/SchedulerResource.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/SchedulerResource.java
index 0fd58182..d7bb8f69 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/SchedulerResource.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/SchedulerResource.java
@@ -22,10 +22,10 @@
package org.opendc.web.server.rest;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
import java.util.List;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
/**
* A resource representing the available schedulers that can be used during experiments.
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/TraceResource.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/TraceResource.java
index 7316c93f..daec01cd 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/TraceResource.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/TraceResource.java
@@ -22,13 +22,13 @@
package org.opendc.web.server.rest;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.WebApplicationException;
import java.util.List;
import java.util.stream.Stream;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.WebApplicationException;
import org.opendc.web.server.model.Trace;
/**
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/error/MissingKotlinParameterExceptionMapper.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/error/MissingKotlinParameterExceptionMapper.java
index 3b6be42e..345acdfe 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/error/MissingKotlinParameterExceptionMapper.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/error/MissingKotlinParameterExceptionMapper.java
@@ -23,10 +23,10 @@
package org.opendc.web.server.rest.error;
import com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.ext.ExceptionMapper;
-import javax.ws.rs.ext.Provider;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.ExceptionMapper;
+import jakarta.ws.rs.ext.Provider;
import org.opendc.web.proto.ProtocolError;
/**
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/error/WebApplicationExceptionMapper.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/error/WebApplicationExceptionMapper.java
index ad1bb05e..e027e559 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/error/WebApplicationExceptionMapper.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/error/WebApplicationExceptionMapper.java
@@ -22,11 +22,11 @@
package org.opendc.web.server.rest.error;
-import javax.ws.rs.WebApplicationException;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.ext.ExceptionMapper;
-import javax.ws.rs.ext.Provider;
+import jakarta.ws.rs.WebApplicationException;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.ext.ExceptionMapper;
+import jakarta.ws.rs.ext.Provider;
import org.opendc.web.proto.ProtocolError;
/**
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/runner/JobResource.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/runner/JobResource.java
index dff52526..4dde8654 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/runner/JobResource.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/runner/JobResource.java
@@ -22,17 +22,17 @@
package org.opendc.web.server.rest.runner;
+import jakarta.annotation.security.RolesAllowed;
+import jakarta.transaction.Transactional;
+import jakarta.validation.Valid;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.WebApplicationException;
import java.util.List;
-import javax.annotation.security.RolesAllowed;
-import javax.transaction.Transactional;
-import javax.validation.Valid;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.WebApplicationException;
import org.opendc.web.proto.JobState;
import org.opendc.web.server.model.Job;
import org.opendc.web.server.service.JobService;
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/PortfolioResource.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/PortfolioResource.java
index d1fc980d..2a3a40f4 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/PortfolioResource.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/PortfolioResource.java
@@ -23,19 +23,19 @@
package org.opendc.web.server.rest.user;
import io.quarkus.security.identity.SecurityIdentity;
+import jakarta.annotation.security.RolesAllowed;
+import jakarta.transaction.Transactional;
+import jakarta.validation.Valid;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.WebApplicationException;
import java.time.Instant;
import java.util.List;
-import javax.annotation.security.RolesAllowed;
-import javax.transaction.Transactional;
-import javax.validation.Valid;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.WebApplicationException;
import org.opendc.web.server.model.Portfolio;
import org.opendc.web.server.model.ProjectAuthorization;
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/PortfolioScenarioResource.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/PortfolioScenarioResource.java
index a058cd31..789808c8 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/PortfolioScenarioResource.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/PortfolioScenarioResource.java
@@ -23,18 +23,18 @@
package org.opendc.web.server.rest.user;
import io.quarkus.security.identity.SecurityIdentity;
+import jakarta.annotation.security.RolesAllowed;
+import jakarta.transaction.Transactional;
+import jakarta.validation.Valid;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.WebApplicationException;
import java.time.Instant;
import java.util.List;
-import javax.annotation.security.RolesAllowed;
-import javax.transaction.Transactional;
-import javax.validation.Valid;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.WebApplicationException;
import org.opendc.web.proto.JobState;
import org.opendc.web.server.model.Job;
import org.opendc.web.server.model.Portfolio;
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/ProjectResource.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/ProjectResource.java
index da47c3ff..ae1c959e 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/ProjectResource.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/ProjectResource.java
@@ -23,19 +23,19 @@
package org.opendc.web.server.rest.user;
import io.quarkus.security.identity.SecurityIdentity;
+import jakarta.annotation.security.RolesAllowed;
+import jakarta.transaction.Transactional;
+import jakarta.validation.Valid;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.WebApplicationException;
import java.time.Instant;
import java.util.List;
-import javax.annotation.security.RolesAllowed;
-import javax.transaction.Transactional;
-import javax.validation.Valid;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.WebApplicationException;
import org.opendc.web.proto.user.ProjectRole;
import org.opendc.web.server.model.Project;
import org.opendc.web.server.model.ProjectAuthorization;
@@ -96,9 +96,9 @@ public final class ProjectResource {
*/
@GET
@Path("{project}")
- public org.opendc.web.proto.user.Project get(@PathParam("project") long id) {
+ public org.opendc.web.proto.user.Project get(@PathParam("project") long project_id) {
ProjectAuthorization auth =
- ProjectAuthorization.findByUser(identity.getPrincipal().getName(), id);
+ ProjectAuthorization.findByUser(identity.getPrincipal().getName(), project_id);
if (auth == null) {
throw new WebApplicationException("Project not found", 404);
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/ScenarioResource.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/ScenarioResource.java
index cf933c32..bb3eb89b 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/ScenarioResource.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/ScenarioResource.java
@@ -23,15 +23,15 @@
package org.opendc.web.server.rest.user;
import io.quarkus.security.identity.SecurityIdentity;
+import jakarta.annotation.security.RolesAllowed;
+import jakarta.transaction.Transactional;
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.WebApplicationException;
import java.util.List;
-import javax.annotation.security.RolesAllowed;
-import javax.transaction.Transactional;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.WebApplicationException;
import org.opendc.web.server.model.ProjectAuthorization;
import org.opendc.web.server.model.Scenario;
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/TopologyResource.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/TopologyResource.java
index 71491801..b8c542d3 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/TopologyResource.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/TopologyResource.java
@@ -24,21 +24,21 @@ package org.opendc.web.server.rest.user;
import io.quarkus.hibernate.orm.panache.Panache;
import io.quarkus.security.identity.SecurityIdentity;
+import jakarta.annotation.security.RolesAllowed;
+import jakarta.persistence.PersistenceException;
+import jakarta.transaction.Transactional;
+import jakarta.validation.Valid;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.WebApplicationException;
import java.time.Instant;
import java.util.List;
-import javax.annotation.security.RolesAllowed;
-import javax.persistence.PersistenceException;
-import javax.transaction.Transactional;
-import javax.validation.Valid;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.GET;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
-import javax.ws.rs.WebApplicationException;
import org.opendc.web.server.model.Project;
import org.opendc.web.server.model.ProjectAuthorization;
import org.opendc.web.server.model.Topology;
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/UserResource.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/UserResource.java
index c3fb2866..c8cda2b7 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/UserResource.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/UserResource.java
@@ -23,10 +23,10 @@
package org.opendc.web.server.rest.user;
import io.quarkus.security.identity.SecurityIdentity;
-import javax.annotation.security.RolesAllowed;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
+import jakarta.annotation.security.RolesAllowed;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
import org.opendc.web.proto.user.User;
import org.opendc.web.proto.user.UserAccounting;
import org.opendc.web.server.service.UserAccountingService;
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/JobService.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/JobService.java
index ed0eaf9c..70933520 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/JobService.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/JobService.java
@@ -22,9 +22,9 @@
package org.opendc.web.server.service;
+import jakarta.enterprise.context.ApplicationScoped;
import java.time.Instant;
import java.util.Map;
-import javax.enterprise.context.ApplicationScoped;
import org.opendc.web.proto.JobState;
import org.opendc.web.server.model.Job;
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/UserAccountingService.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/UserAccountingService.java
index e5003cb4..73fa2a3e 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/UserAccountingService.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/UserAccountingService.java
@@ -22,11 +22,11 @@
package org.opendc.web.server.service;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.persistence.EntityExistsException;
import java.time.Duration;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
-import javax.enterprise.context.ApplicationScoped;
-import javax.persistence.EntityExistsException;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.opendc.web.server.model.UserAccounting;
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/DevSecurityOverrideFilter.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/DevSecurityOverrideFilter.java
index de4478cb..103f868d 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/DevSecurityOverrideFilter.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/DevSecurityOverrideFilter.java
@@ -23,12 +23,12 @@
package org.opendc.web.server.util;
import io.quarkus.arc.properties.IfBuildProperty;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.container.ContainerRequestFilter;
+import jakarta.ws.rs.container.PreMatching;
+import jakarta.ws.rs.core.SecurityContext;
+import jakarta.ws.rs.ext.Provider;
import java.security.Principal;
-import javax.ws.rs.container.ContainerRequestContext;
-import javax.ws.rs.container.ContainerRequestFilter;
-import javax.ws.rs.container.PreMatching;
-import javax.ws.rs.core.SecurityContext;
-import javax.ws.rs.ext.Provider;
/**
* Helper class to disable security for the OpenDC web API when in development mode.
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/KotlinModuleCustomizer.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/KotlinModuleCustomizer.java
index c30edcbf..ff3ba1cd 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/KotlinModuleCustomizer.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/KotlinModuleCustomizer.java
@@ -25,7 +25,7 @@ package org.opendc.web.server.util;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.module.kotlin.KotlinModule;
import io.quarkus.jackson.ObjectMapperCustomizer;
-import javax.inject.Singleton;
+import jakarta.inject.Singleton;
/**
* Helper class to register the Kotlin Jackson module.
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/QuarkusObjectMapperSupplier.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/QuarkusObjectMapperSupplier.java
index e46c74ed..60ca77e5 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/QuarkusObjectMapperSupplier.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/QuarkusObjectMapperSupplier.java
@@ -25,7 +25,7 @@ package org.opendc.web.server.util;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.hypersistence.utils.hibernate.type.util.ObjectMapperSupplier;
import io.quarkus.runtime.annotations.RegisterForReflection;
-import javax.enterprise.inject.spi.CDI;
+import jakarta.enterprise.inject.spi.CDI;
/**
* A supplier for an {@link ObjectMapper} used by the Hypersistence utilities.
diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/runner/QuarkusJobManager.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/runner/QuarkusJobManager.java
index 0331eacf..47d397f3 100644
--- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/runner/QuarkusJobManager.java
+++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/runner/QuarkusJobManager.java
@@ -22,9 +22,9 @@
package org.opendc.web.server.util.runner;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.transaction.Transactional;
import java.util.Map;
-import javax.enterprise.context.ApplicationScoped;
-import javax.transaction.Transactional;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.opendc.web.proto.JobState;
diff --git a/opendc-web/opendc-web-server/src/main/resources/application-test.properties b/opendc-web/opendc-web-server/src/main/resources/application-test.properties
index bee17221..4e3063e4 100644
--- a/opendc-web/opendc-web-server/src/main/resources/application-test.properties
+++ b/opendc-web/opendc-web-server/src/main/resources/application-test.properties
@@ -37,3 +37,7 @@ quarkus.swagger-ui.enable=false
# Disable OpenDC web UI and runner
quarkus.opendc-ui.include=false
quarkus.opendc-runner.include=false
+
+# Create new tables and fill them
+quarkus.hibernate-orm.database.generation=drop-and-create
+quarkus.hibernate-orm.sql-load-script=load_data.sql
diff --git a/opendc-web/opendc-web-server/src/main/resources/db/migration/V3.0__core.sql b/opendc-web/opendc-web-server/src/main/resources/db/migration/V3.0__core.sql
deleted file mode 100644
index 40654b6b..00000000
--- a/opendc-web/opendc-web-server/src/main/resources/db/migration/V3.0__core.sql
+++ /dev/null
@@ -1,160 +0,0 @@
--- Hibernate sequence for unique identifiers
-create sequence hibernate_sequence start with 1 increment by 1;
-
--- Projects
-create table projects
-(
- id bigint not null,
- created_at timestamp not null,
- name varchar(255) not null,
- portfolios_created integer not null default 0,
- scenarios_created integer not null default 0,
- topologies_created integer not null default 0,
- updated_at timestamp not null,
- primary key (id)
-);
-
-create type project_role as enum ('OWNER', 'EDITOR', 'VIEWER');
-
--- Project authorizations authorize users specific permissions to a project.
-create table project_authorizations
-(
- project_id bigint not null,
- user_id varchar(255) not null,
- role project_role not null,
- primary key (project_id, user_id)
-);
-
--- Topologies represent the datacenter designs created by users.
-create table topologies
-(
- id bigint not null,
- created_at timestamp not null,
- name varchar(255) not null,
- number integer not null,
- rooms jsonb not null,
- updated_at timestamp not null,
- project_id bigint not null,
- primary key (id)
-);
-
--- Portfolios
-create table portfolios
-(
- id bigint not null,
- name varchar(255) not null,
- number integer not null,
- targets jsonb not null,
- project_id bigint not null,
- primary key (id)
-);
-
-create table scenarios
-(
- id bigint not null,
- name varchar(255) not null,
- number integer not null,
- phenomena jsonb not null,
- scheduler_name varchar(255) not null,
- sampling_fraction double precision not null,
- portfolio_id bigint not null,
- project_id bigint not null,
- topology_id bigint not null,
- trace_id varchar(255) not null,
- primary key (id)
-);
-
-create type job_state as enum ('PENDING', 'CLAIMED', 'RUNNING', 'FINISHED', 'FAILED');
-
-create table jobs
-(
- id bigint not null,
- created_by varchar(255) not null,
- created_at timestamp not null,
- repeats integer not null,
- results jsonb,
- state job_state not null default 'PENDING',
- runtime integer not null default 0,
- updated_at timestamp not null,
- scenario_id bigint not null,
- primary key (id)
-);
-
--- User accounting
-create table user_accounting
-(
- user_id varchar(255) not null,
- period_end date not null,
- simulation_time integer not null,
- simulation_time_budget integer not null,
- primary key (user_id)
-);
-
--- Workload traces available to the user.
-create table traces
-(
- id varchar(255) not null,
- name varchar(255) not null,
- type varchar(255) not null,
- primary key (id)
-);
-
--- Relations
-alter table project_authorizations
- add constraint fk_project_authorizations
- foreign key (project_id)
- references projects;
-
-create index ux_topologies_number on topologies (project_id, number);
-
-alter table topologies
- add constraint uk_topologies_number unique (project_id, number);
-
-alter table topologies
- add constraint fk_topologies_project
- foreign key (project_id)
- references projects;
-
-create index ux_portfolios_number on portfolios (project_id, number);
-
-alter table portfolios
- add constraint fk_portfolios_project
- foreign key (project_id)
- references projects;
-
-alter table portfolios
- add constraint uk_portfolios_number unique (project_id, number);
-
-create index ux_scenarios_number on scenarios (project_id, number);
-
-alter table scenarios
- add constraint uk_scenarios_number unique (project_id, number);
-
-alter table scenarios
- add constraint fk_scenarios_project
- foreign key (project_id)
- references projects;
-
-alter table scenarios
- add constraint fk_scenarios_topology
- foreign key (topology_id)
- references topologies;
-
-alter table scenarios
- add constraint fk_scenarios_portfolio
- foreign key (portfolio_id)
- references portfolios;
-
-alter table scenarios
- add constraint fk_scenarios_trace
- foreign key (trace_id)
- references traces;
-
-alter table jobs
- add constraint fk_scenarios_job
- foreign key (scenario_id)
- references scenarios;
-
--- Initial data
-insert into traces (id, name, type)
-values ('bitbrains-small', 'Bitbrains Small', 'vm');
diff --git a/opendc-web/opendc-web-server/src/main/resources/db/testing/V3.0.1__entities.sql b/opendc-web/opendc-web-server/src/main/resources/db/testing/V3.0.1__entities.sql
deleted file mode 100644
index 1b702f4e..00000000
--- a/opendc-web/opendc-web-server/src/main/resources/db/testing/V3.0.1__entities.sql
+++ /dev/null
@@ -1,24 +0,0 @@
--- Test entities
-
-alter sequence hibernate_sequence restart with 500;
-
-insert into projects (id, created_at, name, portfolios_created, scenarios_created, topologies_created, updated_at)
-values (1, current_timestamp(), 'Test Project', 1, 2, 1, current_timestamp());
-insert into project_authorizations (project_id, user_id, role)
-values (1, 'owner', 'OWNER'),
- (1, 'editor', 'EDITOR'),
- (1, 'viewer', 'VIEWER');
-
-insert into portfolios (id, name, number, targets, project_id)
-values (1, 'Test Portfolio', 1, '{ "metrics": [] }' format json, 1);
-
-insert into topologies (id, created_at, name, number, rooms, updated_at, project_id)
-values (1, current_timestamp(), 'Test Topology', 1, '[]' format json, current_timestamp(), 1);
-
-insert into scenarios (id, name, number, phenomena, scheduler_name, sampling_fraction, portfolio_id, project_id, topology_id, trace_id)
-values (1, 'Test Scenario', 1, '{ "failures": false, "interference": false }' format json, 'mem', 1.0, 1, 1, 1, 'bitbrains-small'),
- (2, 'Test Scenario', 2, '{ "failures": false, "interference": false }' format json, 'mem', 1.0, 1, 1, 1, 'bitbrains-small');
-
-insert into jobs (id, created_by, created_at, repeats, updated_at, scenario_id)
-values (1, 'owner', current_timestamp(), 1, current_timestamp(), 1),
- (2, 'owner', current_timestamp(), 1, current_timestamp(), 2);
diff --git a/opendc-web/opendc-web-server/src/main/resources/load_data.sql b/opendc-web/opendc-web-server/src/main/resources/load_data.sql
new file mode 100644
index 00000000..72396cef
--- /dev/null
+++ b/opendc-web/opendc-web-server/src/main/resources/load_data.sql
@@ -0,0 +1,124 @@
+
+-- Insert data
+
+INSERT INTO PROJECT (created_at, name, portfolios_created, scenarios_created, topologies_created, updated_at, id)
+ VALUES ('2024-03-01T15:31:41.579969Z', 'Test Project 1', 0, 0, 0, '2024-03-01T15:31:41.579969Z', 1);
+
+INSERT INTO PROJECTAUTHORIZATION (role, project_id, user_name)
+VALUES ('OWNER', 1, 'test_user_1');
+
+-- Add test user 2 as a viewer for project 1
+
+INSERT INTO PROJECTAUTHORIZATION (role, project_id, user_name)
+VALUES ('VIEWER', 1, 'test_user_2');
+
+-- Add test user 3 as an editor for project 1
+
+INSERT INTO PROJECTAUTHORIZATION (role, project_id, user_name)
+VALUES ('EDITOR', 1, 'test_user_3');
+
+-- Create a project for test user 2
+
+INSERT INTO PROJECT (created_at, name, portfolios_created, scenarios_created, topologies_created, updated_at, id)
+VALUES ('2024-03-01T15:31:41.579969Z', 'Test Project 2', 0, 0, 0, '2024-03-01T15:31:41.579969Z', 2);
+
+INSERT INTO PROJECTAUTHORIZATION (role, project_id, user_name)
+VALUES ('OWNER', 2, 'test_user_2');
+
+-- Create three projects for test user 3. User 3 has multiple projects to test getAll
+
+INSERT INTO PROJECT (created_at, name, portfolios_created, scenarios_created, topologies_created, updated_at, id)
+VALUES ('2024-03-01T15:31:41.579969Z', 'Test Project 3', 0, 0, 0, '2024-03-01T15:31:41.579969Z', 3);
+
+INSERT INTO PROJECTAUTHORIZATION (role, project_id, user_name)
+VALUES ('OWNER', 3, 'test_user_3');
+
+INSERT INTO PROJECT (created_at, name, portfolios_created, scenarios_created, topologies_created, updated_at, id)
+VALUES ('2024-03-01T15:31:41.579969Z', 'Test Project 4', 0, 0, 0, '2024-03-01T15:31:41.579969Z', 4);
+
+INSERT INTO PROJECTAUTHORIZATION (role, project_id, user_name)
+VALUES ('OWNER', 4, 'test_user_3');
+
+INSERT INTO PROJECT (created_at, name, portfolios_created, scenarios_created, topologies_created, updated_at, id)
+VALUES ('2024-03-01T15:31:41.579969Z', 'Test Project 5', 0, 0, 0, '2024-03-01T15:31:41.579969Z', 5);
+
+INSERT INTO PROJECTAUTHORIZATION (role, project_id, user_name)
+VALUES ('OWNER', 5, 'test_user_3');
+
+-- Project to delete
+
+INSERT INTO PROJECT (created_at, name, portfolios_created, scenarios_created, topologies_created, updated_at, id)
+VALUES ('2024-03-01T15:31:41.579969Z', 'Test Project Delete', 0, 0, 0, '2024-03-01T15:31:41.579969Z', 6);
+
+INSERT INTO PROJECTAUTHORIZATION (role, project_id, user_name)
+VALUES ('OWNER', 6, 'test_user_1');
+
+-- --------------------------------------------------------------------------------
+-- PortFolios
+-- --------------------------------------------------------------------------------
+
+-- Add Portfolio to project 1
+INSERT INTO PORTFOLIO (name, number, project_id, targets, id)
+VALUES ('Test PortFolio Base', 1, 1, '{"metrics": [], "repeats":1}' FORMAT JSON, 1);
+
+INSERT INTO PORTFOLIO (name, number, project_id, targets, id)
+VALUES ('Test PortFolio Delete', 2, 1, '{"metrics": [], "repeats":1}' FORMAT JSON, 2);
+
+INSERT INTO PORTFOLIO (name, number, project_id, targets, id)
+VALUES ('Test PortFolio DeleteEditor', 3, 1, '{"metrics": [], "repeats":1}' FORMAT JSON, 3);
+
+UPDATE Project p
+SET p.portfolios_created = 3, p.updated_at = '2024-03-01T15:31:41.579969Z'
+WHERE p.id = 1;
+
+-- --------------------------------------------------------------------------------
+-- Topologies
+-- --------------------------------------------------------------------------------
+
+INSERT INTO TOPOLOGY (created_at, name, number, project_id, rooms, updated_at, id)
+VALUES ('2024-03-01T15:31:41.579969Z', 'Test Topology testUpdate', 1, 1, '[]' FORMAT JSON, '2024-03-01T15:31:41.579969Z', 1);
+
+INSERT INTO TOPOLOGY (created_at, name, number, project_id, rooms, updated_at, id)
+VALUES ('2024-03-01T15:31:41.579969Z', 'Test Topology testDeleteAsEditor', 2, 1, '[]' FORMAT JSON, '2024-03-01T15:31:41.579969Z', 2);
+
+INSERT INTO TOPOLOGY (created_at, name, number, project_id, rooms, updated_at, id)
+VALUES ('2024-03-01T15:31:41.579969Z', 'Test Topology testDelete', 3, 1, '[]' FORMAT JSON, '2024-03-01T15:31:41.579969Z', 3);
+
+INSERT INTO TOPOLOGY (created_at, name, number, project_id, rooms, updated_at, id)
+VALUES ('2024-03-01T15:31:41.579969Z', 'Test Topology testDeleteUsed', 4, 1, '[]' FORMAT JSON, '2024-03-01T15:31:41.579969Z', 4);
+
+UPDATE Project p
+SET p.topologies_created = 4, p.updated_at = '2024-03-01T15:31:41.579969Z'
+WHERE p.id = 1;
+
+-- --------------------------------------------------------------------------------
+-- Traces
+-- --------------------------------------------------------------------------------
+
+INSERT INTO TRACE (id, name, type)
+VALUES ('bitbrains-small', 'Bitbrains Small', 'small');
+
+-- --------------------------------------------------------------------------------
+-- Scenario
+-- --------------------------------------------------------------------------------
+
+INSERT INTO SCENARIO (name, number, phenomena, portfolio_id, project_id, scheduler_name, topology_id, sampling_fraction, trace_id, id)
+VALUES ('Test Scenario testDelete', 1, '{"failures": false, "interference": false}' FORMAT JSON, 1, 1, 'test', 1, 1.0, 'bitbrains-small', 1);
+
+INSERT INTO SCENARIO (name, number, phenomena, portfolio_id, project_id, scheduler_name, topology_id, sampling_fraction, trace_id, id)
+VALUES ('Test Scenario testDeleteUsed', 2, '{"failures": false, "interference": false}' FORMAT JSON, 1, 1, 'test', 4, 1.0, 'bitbrains-small', 2);
+
+
+UPDATE Project p
+SET p.scenarios_created = 2, p.updated_at = '2024-03-01T15:31:41.579969Z'
+WHERE p.id = 1;
+
+-- --------------------------------------------------------------------------------
+-- Job
+-- --------------------------------------------------------------------------------
+
+INSERT INTO JOB (scenario_id, created_by, created_at, repeats, updated_at, state, runtime, results, id)
+VALUES (1, 'test_user_1', '2024-03-01T15:31:41.579969Z', 1, '2024-03-01T15:31:41.579969Z', 'PENDING', 1, '{}' FORMAT JSON, 1);
+
+INSERT INTO JOB (scenario_id, created_by, created_at, repeats, updated_at, state, runtime, results, id)
+VALUES (1, 'test_user_1', '2024-03-01T15:31:41.579969Z', 1, '2024-03-01T15:31:41.579969Z', 'PENDING', 1, '{}' FORMAT JSON, 2);
diff --git a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/SchedulerResourceTest.java b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/SchedulerResourceTest.java
index feeac4d3..f52ede3a 100644
--- a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/SchedulerResourceTest.java
+++ b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/SchedulerResourceTest.java
@@ -22,11 +22,10 @@
package org.opendc.web.server.rest;
-import static io.restassured.RestAssured.when;
+import static io.restassured.RestAssured.given;
import io.quarkus.test.common.http.TestHTTPEndpoint;
import io.quarkus.test.junit.QuarkusTest;
-import io.restassured.http.ContentType;
import org.junit.jupiter.api.Test;
/**
@@ -40,6 +39,6 @@ public final class SchedulerResourceTest {
*/
@Test
public void testGetSchedulers() {
- when().get().then().statusCode(200).contentType(ContentType.JSON);
+ given().get().then().statusCode(200);
}
}
diff --git a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/TraceResourceTest.java b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/TraceResourceTest.java
index 5c5976db..9da26059 100644
--- a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/TraceResourceTest.java
+++ b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/TraceResourceTest.java
@@ -41,7 +41,7 @@ public final class TraceResourceTest {
*/
@Test
public void testGetAllEmpty() {
- when().get().then().statusCode(200).contentType(ContentType.JSON);
+ when().get().then().statusCode(200);
}
/**
@@ -49,7 +49,7 @@ public final class TraceResourceTest {
*/
@Test
public void testGetNonExisting() {
- when().get("/unknown").then().statusCode(404).contentType(ContentType.JSON);
+ when().get("/unknown").then().statusCode(404);
}
/**
diff --git a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/runner/JobResourceTest.java b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/runner/JobResourceTest.java
index 94b2cef0..09f60c0a 100644
--- a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/runner/JobResourceTest.java
+++ b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/runner/JobResourceTest.java
@@ -23,7 +23,6 @@
package org.opendc.web.server.rest.runner;
import static io.restassured.RestAssured.given;
-import static io.restassured.RestAssured.when;
import static org.hamcrest.Matchers.equalTo;
import io.quarkus.test.common.http.TestHTTPEndpoint;
@@ -44,7 +43,7 @@ public final class JobResourceTest {
*/
@Test
public void testQueryWithoutToken() {
- when().get().then().statusCode(401);
+ given().get().then().statusCode(401);
}
/**
@@ -52,10 +51,10 @@ public final class JobResourceTest {
*/
@Test
@TestSecurity(
- user = "test",
+ user = "test_user_1",
roles = {"openid"})
public void testQueryInvalidScope() {
- when().get().then().statusCode(403);
+ given().get().then().statusCode(403);
}
/**
@@ -63,10 +62,10 @@ public final class JobResourceTest {
*/
@Test
@TestSecurity(
- user = "test",
+ user = "test_user_1",
roles = {"runner"})
public void testQuery() {
- when().get().then().statusCode(200).contentType(ContentType.JSON).body("get(0).state", equalTo("PENDING"));
+ given().get().then().statusCode(200).contentType(ContentType.JSON).body("get(0).state", equalTo("PENDING"));
}
/**
@@ -74,10 +73,10 @@ public final class JobResourceTest {
*/
@Test
@TestSecurity(
- user = "test",
+ user = "test_user_1",
roles = {"runner"})
public void testGetNonExisting() {
- when().get("/0").then().statusCode(404).contentType(ContentType.JSON);
+ given().get("/0").then().statusCode(404);
}
/**
@@ -85,10 +84,10 @@ public final class JobResourceTest {
*/
@Test
@TestSecurity(
- user = "test",
+ user = "test_user_1",
roles = {"runner"})
public void testGetExisting() {
- when().get("/1").then().statusCode(200).contentType(ContentType.JSON).body("id", equalTo(1));
+ given().get("/1").then().statusCode(200).contentType(ContentType.JSON).body("id", equalTo(1));
}
/**
@@ -96,7 +95,7 @@ public final class JobResourceTest {
*/
@Test
@TestSecurity(
- user = "test",
+ user = "test_user_1",
roles = {"runner"})
public void testUpdateNonExistent() {
given().body(new org.opendc.web.proto.runner.Job.Update(JobState.PENDING, 0, null))
@@ -113,7 +112,7 @@ public final class JobResourceTest {
*/
@Test
@TestSecurity(
- user = "test",
+ user = "test_user_1",
roles = {"runner"})
public void testUpdateState() {
given().body(new org.opendc.web.proto.runner.Job.Update(JobState.CLAIMED, 0, null))
@@ -131,7 +130,7 @@ public final class JobResourceTest {
*/
@Test
@TestSecurity(
- user = "test",
+ user = "test_user_1",
roles = {"runner"})
public void testUpdateInvalidInput() {
given().body("{ \"test\": \"test\" }")
diff --git a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/PortfolioResourceTest.java b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/PortfolioResourceTest.java
index a952d83f..f23b4fc4 100644
--- a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/PortfolioResourceTest.java
+++ b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/PortfolioResourceTest.java
@@ -40,33 +40,55 @@ import org.opendc.web.proto.Targets;
@TestHTTPEndpoint(PortfolioResource.class)
public final class PortfolioResourceTest {
/**
- * Test that tries to obtain the list of portfolios belonging to a project.
+ * Test that tries to obtain the list of all portfolios belonging to a project.
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
- public void testGetForProject() {
- given().pathParam("project", 1).when().get().then().statusCode(200).contentType(ContentType.JSON);
+ public void testGetAllForProject() {
+ given().pathParam("project", 1).when().get().then().statusCode(200);
}
/**
- * Test that tries to obtain the list of portfolios belonging to a project without authorization.
+ * Test that tries to obtain the list of all portfolios belonging to a project
+ * without authorization.
+ *
+ * TODO: Why is this an empty list, and not a 403 message?
*/
@Test
@TestSecurity(
- user = "unknown",
+ user = "test_user_1",
roles = {"openid"})
- public void testGetForProjectNoAuthorization() {
- given().pathParam("project", 1).when().get().then().statusCode(200).contentType(ContentType.JSON);
+ public void testGetAllForProjectNoAuthorization() {
+ given().pathParam("project", 1).when().get().then().statusCode(200);
}
/**
- * Test that tries to create a topology for a project.
+ * Test that tries to create a portfolio for a project that exists and user has permission.
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
+ roles = {"openid"})
+ public void testCreate() {
+ given().pathParam("project", "1")
+ .body(new org.opendc.web.proto.user.Portfolio.Create("Test Portfolio New", new Targets(Set.of(), 1)))
+ .contentType(ContentType.JSON)
+ .when()
+ .post()
+ .then()
+ .statusCode(200)
+ .contentType(ContentType.JSON)
+ .body("name", equalTo("Test Portfolio New"));
+ }
+
+ /**
+ * Test that tries to create a topology for a project that does not exist.
+ */
+ @Test
+ @TestSecurity(
+ user = "test_user_1",
roles = {"openid"})
public void testCreateNonExistent() {
given().pathParam("project", "0")
@@ -75,45 +97,42 @@ public final class PortfolioResourceTest {
.when()
.post()
.then()
- .statusCode(404)
- .contentType(ContentType.JSON);
+ .statusCode(404);
}
/**
- * Test that tries to create a topology for a project.
+ * Test that tries to create a portfolio for a project that does exist but the user does not have permission.
*/
@Test
@TestSecurity(
- user = "viewer",
+ user = "test_user_2",
roles = {"openid"})
- public void testCreateNotPermitted() {
+ public void testCreateViewer() {
given().pathParam("project", "1")
.body(new org.opendc.web.proto.user.Portfolio.Create("test", new Targets(Set.of(), 1)))
.contentType(ContentType.JSON)
.when()
.post()
.then()
- .statusCode(403)
- .contentType(ContentType.JSON);
+ .statusCode(403);
}
/**
- * Test that tries to create a portfolio for a project.
+ * Test that tries to create a portfolio for a project that does exist but the user does not have permission.
+ * TODO: This should return 403 but does not because there is no user class
*/
@Test
@TestSecurity(
- user = "editor",
+ user = "test_user_1",
roles = {"openid"})
- public void testCreate() {
- given().pathParam("project", "1")
+ public void testCreateNotPermitted() {
+ given().pathParam("project", "3")
.body(new org.opendc.web.proto.user.Portfolio.Create("test", new Targets(Set.of(), 1)))
.contentType(ContentType.JSON)
.when()
.post()
.then()
- .statusCode(200)
- .contentType(ContentType.JSON)
- .body("name", equalTo("test"));
+ .statusCode(404);
}
/**
@@ -121,7 +140,7 @@ public final class PortfolioResourceTest {
*/
@Test
@TestSecurity(
- user = "editor",
+ user = "test_user_1",
roles = {"openid"})
public void testCreateEmpty() {
given().pathParam("project", "1")
@@ -130,8 +149,7 @@ public final class PortfolioResourceTest {
.when()
.post()
.then()
- .statusCode(400)
- .contentType(ContentType.JSON);
+ .statusCode(400);
}
/**
@@ -139,7 +157,7 @@ public final class PortfolioResourceTest {
*/
@Test
@TestSecurity(
- user = "editor",
+ user = "test_user_1",
roles = {"openid"})
public void testCreateBlankName() {
given().pathParam("project", "1")
@@ -148,8 +166,7 @@ public final class PortfolioResourceTest {
.when()
.post()
.then()
- .statusCode(400)
- .contentType(ContentType.JSON);
+ .statusCode(400);
}
/**
@@ -165,7 +182,7 @@ public final class PortfolioResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"runner"})
public void testGetInvalidToken() {
given().pathParam("project", "1").when().get("/1").then().statusCode(403);
@@ -176,15 +193,10 @@ public final class PortfolioResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testGetNonExisting() {
- given().pathParam("project", "1")
- .when()
- .get("/0")
- .then()
- .statusCode(404)
- .contentType(ContentType.JSON);
+ given().pathParam("project", "1").when().get("/0").then().statusCode(404);
}
/**
@@ -192,15 +204,10 @@ public final class PortfolioResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testGetNonExistingProject() {
- given().pathParam("project", "0")
- .when()
- .get("/1")
- .then()
- .statusCode(404)
- .contentType(ContentType.JSON);
+ given().pathParam("project", "0").when().get("/1").then().statusCode(404);
}
/**
@@ -208,7 +215,7 @@ public final class PortfolioResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testGetExisting() {
given().pathParam("project", "1")
@@ -225,7 +232,7 @@ public final class PortfolioResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testDeleteNonExistent() {
given().pathParam("project", "1").when().delete("/0").then().statusCode(404);
@@ -236,7 +243,7 @@ public final class PortfolioResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testDeleteNonExistentProject() {
given().pathParam("project", "0").when().delete("/1").then().statusCode(404);
@@ -247,26 +254,21 @@ public final class PortfolioResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testDelete() {
- int number = given().pathParam("project", "1")
- .body(new org.opendc.web.proto.user.Portfolio.Create("Delete Portfolio", new Targets(Set.of(), 1)))
- .contentType(ContentType.JSON)
- .when()
- .post()
- .then()
- .statusCode(200)
- .contentType(ContentType.JSON)
- .extract()
- .path("number");
+ given().pathParam("project", "1").when().delete("/2").then().statusCode(200);
+ }
- given().pathParam("project", "1")
- .when()
- .delete("/" + number)
- .then()
- .statusCode(200)
- .contentType(ContentType.JSON);
+ /**
+ * Test to delete a portfolio as an editor.
+ */
+ @Test
+ @TestSecurity(
+ user = "test_user_3",
+ roles = {"openid"})
+ public void testDeleteEditor() {
+ given().pathParam("project", "1").when().delete("/3").then().statusCode(200);
}
/**
@@ -274,14 +276,9 @@ public final class PortfolioResourceTest {
*/
@Test
@TestSecurity(
- user = "viewer",
+ user = "test_user_2",
roles = {"openid"})
public void testDeleteAsViewer() {
- given().pathParam("project", "1")
- .when()
- .delete("/1")
- .then()
- .statusCode(403)
- .contentType(ContentType.JSON);
+ given().pathParam("project", "1").when().delete("/1").then().statusCode(403);
}
}
diff --git a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/PortfolioScenarioResourceTest.java b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/PortfolioScenarioResourceTest.java
index 58042833..270dbae9 100644
--- a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/PortfolioScenarioResourceTest.java
+++ b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/PortfolioScenarioResourceTest.java
@@ -43,7 +43,7 @@ public final class PortfolioScenarioResourceTest {
/**
* Test that tries to obtain a portfolio without token.
*/
- // @Test
+ @Test
public void testGetWithoutToken() {
given().pathParam("project", "1")
.pathParam("portfolio", "1")
@@ -58,7 +58,7 @@ public final class PortfolioScenarioResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"runner"})
public void testGetInvalidToken() {
given().pathParam("project", "1")
@@ -72,12 +72,12 @@ public final class PortfolioScenarioResourceTest {
/**
* Test that tries to obtain a scenario without authorization.
*/
- // @Test
- // @TestSecurity(
- // user = "unknown",
- // roles = {"openid"})
+ @Test
+ @TestSecurity(
+ user = "test_user_1",
+ roles = {"openid"})
public void testGetUnauthorized() {
- given().pathParam("project", "1")
+ given().pathParam("project", "2")
.pathParam("portfolio", "1")
.when()
.get()
@@ -88,28 +88,28 @@ public final class PortfolioScenarioResourceTest {
/**
* Test that tries to obtain a scenario.
+ * TODO: shouldn't this be all scenarios?
*/
- // @Test
- // @TestSecurity(
- // user = "owner",
- // roles = {"openid"})
+ @Test
+ @TestSecurity(
+ user = "test_user_1",
+ roles = {"openid"})
public void testGet() {
given().pathParam("project", "1")
.pathParam("portfolio", "1")
.when()
.get()
.then()
- .statusCode(200)
- .contentType(ContentType.JSON);
+ .statusCode(200);
}
/**
- * Test that tries to create a scenario for a portfolio.
+ * Test that tries to create a scenario for a portfolio that does not exist in a project that can be accessed.
*/
- // @Test
- // @TestSecurity(
- // user = "owner",
- // roles = {"openid"})
+ @Test
+ @TestSecurity(
+ user = "test_user_1",
+ roles = {"openid"})
public void testCreateNonExistent() {
given().pathParam("project", "1")
.pathParam("portfolio", "0")
@@ -126,13 +126,13 @@ public final class PortfolioScenarioResourceTest {
/**
* Test that tries to create a scenario for a portfolio without authorization.
*/
- // @Test
- // @TestSecurity(
- // user = "unknown",
- // roles = {"openid"})
+ @Test
+ @TestSecurity(
+ user = "test_user_1",
+ roles = {"openid"})
public void testCreateUnauthorized() {
- given().pathParam("project", "1")
- .pathParam("portfolio", "0")
+ given().pathParam("project", "2")
+ .pathParam("portfolio", "1")
.body(new Scenario.Create(
"test", new Workload.Spec("test", 1.0), 1, new OperationalPhenomena(false, false), "test"))
.contentType(ContentType.JSON)
@@ -146,13 +146,13 @@ public final class PortfolioScenarioResourceTest {
/**
* Test that tries to create a scenario for a portfolio as a viewer.
*/
- // @Test
- // @TestSecurity(
- // user = "viewer",
- // roles = {"openid"})
+ @Test
+ @TestSecurity(
+ user = "test_user_2",
+ roles = {"openid"})
public void testCreateAsViewer() {
given().pathParam("project", "1")
- .pathParam("portfolio", "0")
+ .pathParam("portfolio", "1")
.body(new Scenario.Create(
"test", new Workload.Spec("test", 1.0), 1, new OperationalPhenomena(false, false), "test"))
.contentType(ContentType.JSON)
@@ -166,15 +166,15 @@ public final class PortfolioScenarioResourceTest {
/**
* Test that tries to create a scenario for a portfolio.
*/
- // @Test
- // @TestSecurity(
- // user = "owner",
- // roles = {"openid"})
+ @Test
+ @TestSecurity(
+ user = "test_user_1",
+ roles = {"openid"})
public void testCreate() {
given().pathParam("project", "1")
.pathParam("portfolio", "1")
.body(new Scenario.Create(
- "test",
+ "Test Scenario New",
new Workload.Spec("bitbrains-small", 1.0),
1,
new OperationalPhenomena(false, false),
@@ -185,16 +185,16 @@ public final class PortfolioScenarioResourceTest {
.then()
.statusCode(200)
.contentType(ContentType.JSON)
- .body("name", equalTo("test"));
+ .body("name", equalTo("Test Scenario New"));
}
/**
* Test to create a project with an empty body.
*/
- // @Test
- // @TestSecurity(
- // user = "owner",
- // roles = {"openid"})
+ @Test
+ @TestSecurity(
+ user = "test_user_1",
+ roles = {"openid"})
public void testCreateEmpty() {
given().pathParam("project", "1")
.pathParam("portfolio", "1")
@@ -210,10 +210,10 @@ public final class PortfolioScenarioResourceTest {
/**
* Test to create a project with a blank name.
*/
- // @Test
- // @TestSecurity(
- // user = "owner",
- // roles = {"openid"})
+ @Test
+ @TestSecurity(
+ user = "test_user_1",
+ roles = {"openid"})
public void testCreateBlankName() {
given().pathParam("project", "1")
.pathParam("portfolio", "1")
@@ -228,12 +228,12 @@ public final class PortfolioScenarioResourceTest {
}
/**
- * Test that tries to create a scenario for a portfolio.
+ * Test that tries to create a scenario for a portfolio with an unknown Topology.
*/
- // @Test
- // @TestSecurity(
- // user = "owner",
- // roles = {"openid"})
+ @Test
+ @TestSecurity(
+ user = "test_user_1",
+ roles = {"openid"})
public void testCreateUnknownTopology() {
given().pathParam("project", "1")
.pathParam("portfolio", "1")
@@ -252,12 +252,12 @@ public final class PortfolioScenarioResourceTest {
}
/**
- * Test that tries to create a scenario for a portfolio.
+ * Test that tries to create a scenario for a portfolio with an unknown Trace.
*/
- // @Test
- // @TestSecurity(
- // user = "owner",
- // roles = {"openid"})
+ @Test
+ @TestSecurity(
+ user = "test_user_1",
+ roles = {"openid"})
public void testCreateUnknownTrace() {
given().pathParam("project", "1")
.pathParam("portfolio", "1")
diff --git a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/ProjectResourceTest.java b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/ProjectResourceTest.java
index bd7cff9b..450c0c0c 100644
--- a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/ProjectResourceTest.java
+++ b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/ProjectResourceTest.java
@@ -24,7 +24,7 @@ package org.opendc.web.server.rest.user;
import static io.restassured.RestAssured.given;
import static io.restassured.RestAssured.when;
-import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.*;
import io.quarkus.test.common.http.TestHTTPEndpoint;
import io.quarkus.test.junit.QuarkusTest;
@@ -41,7 +41,7 @@ public final class ProjectResourceTest {
/**
* Test that tries to obtain all projects without token.
*/
- // @Test
+ @Test
public void testGetAllWithoutToken() {
when().get().then().statusCode(401);
}
@@ -51,30 +51,41 @@ public final class ProjectResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"runner"})
public void testGetAllWithInvalidScope() {
when().get().then().statusCode(403);
}
/**
+ * Test that tries to obtain when no projects have yet been made.
+ */
+ @Test
+ @TestSecurity(
+ user = "test_user_4",
+ roles = {"openid"})
+ public void testGetAllWithNoAvailableProjects() {
+ when().get().then().statusCode(200).contentType(ContentType.JSON).body("", empty());
+ }
+
+ /**
* Test that tries to obtain all project for a user.
*/
- // @Test
- // @TestSecurity(
- // user = "owner",
- // roles = {"openid"})
+ @Test
+ @TestSecurity(
+ user = "test_user_3",
+ roles = {"openid"})
public void testGetAll() {
- when().get().then().statusCode(200).contentType(ContentType.JSON).body("get(0).name", equalTo("Test Project"));
+ given().get().then().statusCode(200).contentType(ContentType.JSON).body("", hasSize(4));
}
/**
* Test that tries to obtain a non-existent project.
*/
- // @Test
- // @TestSecurity(
- // user = "owner",
- // roles = {"openid"})
+ @Test
+ @TestSecurity(
+ user = "test_user_1",
+ roles = {"openid"})
public void testGetNonExisting() {
when().get("/0").then().statusCode(404).contentType(ContentType.JSON);
}
@@ -82,106 +93,104 @@ public final class ProjectResourceTest {
/**
* Test that tries to obtain a project.
*/
- // @Test
- // @TestSecurity(
- // user = "owner",
- // roles = {"openid"})
+ @Test
+ @TestSecurity(
+ user = "test_user_1",
+ roles = {"openid"})
public void testGetExisting() {
- when().get("/1").then().statusCode(200).contentType(ContentType.JSON).body("id", equalTo(1));
+ // Try to get the project
+ given().get("/1").then().statusCode(200).contentType(ContentType.JSON).body("id", equalTo(1));
}
/**
* Test that tries to create a project.
*/
- // @Test
- // @TestSecurity(
- // user = "owner",
- // roles = {"openid"})
+ @Test
+ @TestSecurity(
+ user = "test_user_1",
+ roles = {"openid"})
public void testCreate() {
- given().body(new org.opendc.web.proto.user.Project.Create("test"))
+ given().body(new org.opendc.web.proto.user.Project.Create("Test Project New"))
.contentType(ContentType.JSON)
.when()
.post()
.then()
.statusCode(200)
.contentType(ContentType.JSON)
- .body("name", equalTo("test"));
+ .body("name", equalTo("Test Project New"));
}
/**
* Test to create a project with an empty body.
*/
- // @Test
- // @TestSecurity(
- // user = "owner",
- // roles = {"openid"})
+ @Test
+ @TestSecurity(
+ user = "test_user_1",
+ roles = {"openid"})
public void testCreateEmpty() {
- given().body("{}")
- .contentType(ContentType.JSON)
- .when()
- .post()
- .then()
- .statusCode(400)
- .contentType(ContentType.JSON);
+ given().body("{}").contentType(ContentType.JSON).when().post().then().statusCode(400);
}
/**
* Test to create a project with a blank name.
*/
- // @Test
- // @TestSecurity(
- // user = "owner",
- // roles = {"openid"})
+ @Test
+ @TestSecurity(
+ user = "test_user_1",
+ roles = {"openid"})
public void testCreateBlankName() {
given().body(new org.opendc.web.proto.user.Project.Create(""))
.contentType(ContentType.JSON)
.when()
.post()
.then()
- .statusCode(400)
- .contentType(ContentType.JSON);
+ .statusCode(400);
+ }
+
+ /**
+ * Test to delete a project that is owned by the user.
+ */
+ @Test
+ @TestSecurity(
+ user = "test_user_1",
+ roles = {"openid"})
+ public void testDelete() {
+ given().delete("/6").then().statusCode(200);
}
/**
* Test to delete a non-existent project.
*/
- // @Test
- // @TestSecurity(
- // user = "owner",
- // roles = {"openid"})
+ @Test
+ @TestSecurity(
+ user = "test_user_1",
+ roles = {"openid"})
public void testDeleteNonExistent() {
- when().delete("/0").then().statusCode(404).contentType(ContentType.JSON);
+ when().delete("/0").then().statusCode(404);
}
/**
- * Test to delete a project.
+ * Test to delete a project which is not connected to the user.
+ * test_user_3 is not connected to project 1.
*/
- // @Test
- // @TestSecurity(
- // user = "owner",
- // roles = {"openid"})
- public void testDelete() {
- int id = given().body(new org.opendc.web.proto.user.Project.Create("Delete Project"))
- .contentType(ContentType.JSON)
- .when()
- .post()
- .then()
- .statusCode(200)
- .contentType(ContentType.JSON)
- .extract()
- .path("id");
-
- when().delete("/" + id).then().statusCode(200).contentType(ContentType.JSON);
+ @Test
+ @TestSecurity(
+ user = "test_user_3",
+ roles = {"openid"})
+ public void testDeleteNotConnected() {
+ when().delete("/1").then().statusCode(403);
}
/**
* Test to delete a project which the user does not own.
+ * project 1 is owned by test_user_1, test_user_2 is a viewer
+ * should not be able to delete it
*/
- // @Test
- // @TestSecurity(
- // user = "viewer",
- // roles = {"openid"})
+ @Test
+ @TestSecurity(
+ user = "test_user_2",
+ roles = {"openid"})
public void testDeleteNonOwner() {
- when().delete("/1").then().statusCode(403).contentType(ContentType.JSON);
+ when().delete("/1").then().statusCode(403);
}
}
diff --git a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/ScenarioResourceTest.java b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/ScenarioResourceTest.java
index a980e4e2..d81f9655 100644
--- a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/ScenarioResourceTest.java
+++ b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/ScenarioResourceTest.java
@@ -28,13 +28,8 @@ import static org.hamcrest.Matchers.equalTo;
import io.quarkus.test.common.http.TestHTTPEndpoint;
import io.quarkus.test.junit.QuarkusTest;
import io.quarkus.test.security.TestSecurity;
-import io.restassured.builder.RequestSpecBuilder;
import io.restassured.http.ContentType;
-import io.restassured.specification.RequestSpecification;
import org.junit.jupiter.api.Test;
-import org.opendc.web.proto.OperationalPhenomena;
-import org.opendc.web.proto.Workload;
-import org.opendc.web.proto.user.Scenario;
/**
* Test suite for {@link ScenarioResource}.
@@ -47,10 +42,10 @@ public final class ScenarioResourceTest {
*/
@Test
@TestSecurity(
- user = "unknown",
+ user = "test_user_1",
roles = {"openid"})
public void testGetAllUnauthorized() {
- given().pathParam("project", "1").when().get().then().statusCode(404).contentType(ContentType.JSON);
+ given().pathParam("project", "2").when().get().then().statusCode(404);
}
/**
@@ -58,10 +53,10 @@ public final class ScenarioResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testGetAll() {
- given().pathParam("project", "1").when().get().then().statusCode(200).contentType(ContentType.JSON);
+ given().pathParam("project", "1").when().get().then().statusCode(200);
}
/**
@@ -77,7 +72,7 @@ public final class ScenarioResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"runner"})
public void testGetInvalidToken() {
given().pathParam("project", "1").when().get("/1").then().statusCode(403);
@@ -88,7 +83,7 @@ public final class ScenarioResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testGetNonExisting() {
given().pathParam("project", "1")
@@ -100,14 +95,14 @@ public final class ScenarioResourceTest {
}
/**
- * Test that tries to obtain a scenario.
+ * Test that tries to obtain a scenario when it does not have authority to get to the project.
*/
@Test
@TestSecurity(
- user = "unknown",
+ user = "test_user_1",
roles = {"openid"})
public void testGetExistingUnauthorized() {
- given().pathParam("project", "1")
+ given().pathParam("project", "2")
.when()
.get("/1")
.then()
@@ -120,7 +115,7 @@ public final class ScenarioResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testGetExisting() {
given().pathParam("project", "1")
@@ -137,7 +132,7 @@ public final class ScenarioResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testDeleteNonExistent() {
given().pathParam("project", "1").when().delete("/0").then().statusCode(404);
@@ -148,10 +143,10 @@ public final class ScenarioResourceTest {
*/
@Test
@TestSecurity(
- user = "unknown",
+ user = "test_user_1",
roles = {"openid"})
public void testDeleteUnauthorized() {
- given().pathParam("project", "1").when().delete("/1").then().statusCode(404);
+ given().pathParam("project", "2").when().delete("/1").then().statusCode(404);
}
/**
@@ -159,7 +154,7 @@ public final class ScenarioResourceTest {
*/
@Test
@TestSecurity(
- user = "viewer",
+ user = "test_user_2",
roles = {"openid"})
public void testDeleteAsViewer() {
given().pathParam("project", "1").when().delete("/1").then().statusCode(403);
@@ -170,32 +165,12 @@ public final class ScenarioResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testDelete() {
- RequestSpecification spec = new RequestSpecBuilder()
- .setBasePath("/projects/1/portfolios/1/scenarios")
- .build();
-
- int number = given(spec)
- .body(new Scenario.Create(
- "test",
- new Workload.Spec("bitbrains-small", 1.0),
- 1,
- new OperationalPhenomena(false, false),
- "test"))
- .contentType(ContentType.JSON)
- .when()
- .post()
- .then()
- .statusCode(200)
- .contentType(ContentType.JSON)
- .extract()
- .path("number");
-
given().pathParam("project", "1")
.when()
- .delete("/" + number)
+ .delete("/1")
.then()
.statusCode(200)
.contentType(ContentType.JSON);
diff --git a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/TopologyResourceTest.java b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/TopologyResourceTest.java
index c0746e7a..277376e5 100644
--- a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/TopologyResourceTest.java
+++ b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/rest/user/TopologyResourceTest.java
@@ -44,7 +44,7 @@ public final class TopologyResourceTest {
*/
@Test
@TestSecurity(
- user = "unknown",
+ user = "test_user_4",
roles = {"openid"})
public void testGetAllWithoutAuth() {
given().pathParam("project", "1")
@@ -58,21 +58,22 @@ public final class TopologyResourceTest {
/**
* Test that tries to obtain the list of topologies belonging to a project.
+ * TODO: check if any topology comes back
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testGetAll() {
- given().pathParam("project", "1").when().get().then().statusCode(200).contentType(ContentType.JSON);
+ given().pathParam("project", "1").when().get().then().statusCode(200);
}
/**
- * Test that tries to create a topology for a project.
+ * Test that tries to create a topology for a project that does not exist.
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testCreateNonExistent() {
given().pathParam("project", "0")
@@ -81,26 +82,25 @@ public final class TopologyResourceTest {
.when()
.post()
.then()
- .statusCode(404)
- .contentType(ContentType.JSON);
+ .statusCode(404);
}
/**
- * Test that tries to create a topology for a project as viewer.
+ * Test that tries to create a topology for a project while not authorized.
+ * TODO: should probably return 403, but this does not work in the current system
*/
@Test
@TestSecurity(
- user = "viewer",
+ user = "test_user_1",
roles = {"openid"})
public void testCreateUnauthorized() {
- given().pathParam("project", "1")
+ given().pathParam("project", "2")
.body(new Topology.Create("test", List.of()))
.contentType(ContentType.JSON)
.when()
.post()
.then()
- .statusCode(403)
- .contentType(ContentType.JSON);
+ .statusCode(404);
}
/**
@@ -108,18 +108,18 @@ public final class TopologyResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testCreate() {
given().pathParam("project", "1")
- .body(new Topology.Create("test", List.of()))
+ .body(new Topology.Create("Test Topology New", List.of()))
.contentType(ContentType.JSON)
.when()
.post()
.then()
.statusCode(200)
.contentType(ContentType.JSON)
- .body("name", equalTo("test"));
+ .body("name", equalTo("Test Topology New"));
}
/**
@@ -127,7 +127,7 @@ public final class TopologyResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testCreateEmpty() {
given().pathParam("project", "1")
@@ -136,8 +136,7 @@ public final class TopologyResourceTest {
.when()
.post()
.then()
- .statusCode(400)
- .contentType(ContentType.JSON);
+ .statusCode(400);
}
/**
@@ -145,7 +144,7 @@ public final class TopologyResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testCreateBlankName() {
given().pathParam("project", "1")
@@ -154,8 +153,7 @@ public final class TopologyResourceTest {
.when()
.post()
.then()
- .statusCode(400)
- .contentType(ContentType.JSON);
+ .statusCode(400);
}
/**
@@ -171,7 +169,7 @@ public final class TopologyResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"runner"})
public void testGetInvalidToken() {
given().pathParam("project", "1").when().get("/1").then().statusCode(403);
@@ -182,15 +180,10 @@ public final class TopologyResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testGetNonExisting() {
- given().pathParam("project", "1")
- .when()
- .get("/0")
- .then()
- .statusCode(404)
- .contentType(ContentType.JSON);
+ given().pathParam("project", "1").when().get("/0").then().statusCode(404);
}
/**
@@ -198,15 +191,10 @@ public final class TopologyResourceTest {
*/
@Test
@TestSecurity(
- user = "unknown",
+ user = "test_user_1",
roles = {"openid"})
public void testGetUnauthorized() {
- given().pathParam("project", "1")
- .when()
- .get("/1")
- .then()
- .statusCode(404)
- .contentType(ContentType.JSON);
+ given().pathParam("project", "2").when().get("/1").then().statusCode(404);
}
/**
@@ -214,7 +202,7 @@ public final class TopologyResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testGetExisting() {
given().pathParam("project", "1")
@@ -231,7 +219,7 @@ public final class TopologyResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testUpdateNonExistent() {
given().pathParam("project", "1")
@@ -248,10 +236,10 @@ public final class TopologyResourceTest {
*/
@Test
@TestSecurity(
- user = "unknown",
+ user = "test_user_1",
roles = {"openid"})
public void testUpdateUnauthorized() {
- given().pathParam("project", "1")
+ given().pathParam("project", "2")
.body(new Topology.Update(List.of()))
.contentType(ContentType.JSON)
.when()
@@ -262,10 +250,11 @@ public final class TopologyResourceTest {
/**
* Test to update a topology as a viewer.
+ * TODO: should return 403, but currently returns 404
*/
@Test
@TestSecurity(
- user = "viewer",
+ user = "test_user_2",
roles = {"openid"})
public void testUpdateAsViewer() {
given().pathParam("project", "1")
@@ -283,7 +272,7 @@ public final class TopologyResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testUpdate() {
given().pathParam("project", "1")
@@ -292,8 +281,7 @@ public final class TopologyResourceTest {
.when()
.put("/1")
.then()
- .statusCode(200)
- .contentType(ContentType.JSON);
+ .statusCode(200);
}
/**
@@ -301,7 +289,7 @@ public final class TopologyResourceTest {
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testDeleteNonExistent() {
given().pathParam("project", "1").when().delete("/0").then().statusCode(404);
@@ -312,10 +300,10 @@ public final class TopologyResourceTest {
*/
@Test
@TestSecurity(
- user = "unknown",
+ user = "test_user_1",
roles = {"openid"})
public void testDeleteUnauthorized() {
- given().pathParam("project", "1").when().delete("/1").then().statusCode(404);
+ given().pathParam("project", "2").when().delete("/1").then().statusCode(404);
}
/**
@@ -323,50 +311,46 @@ public final class TopologyResourceTest {
*/
@Test
@TestSecurity(
- user = "viewer",
+ user = "test_user_2",
roles = {"openid"})
public void testDeleteAsViewer() {
given().pathParam("project", "1").when().delete("/1").then().statusCode(403);
}
/**
+ * Test to delete a topology as a viewer.
+ */
+ @Test
+ @TestSecurity(
+ user = "test_user_3",
+ roles = {"openid"})
+ public void testDeleteAsEditor() {
+ given().pathParam("project", "1").when().delete("/2").then().statusCode(200);
+ }
+
+ /**
* Test to delete a topology.
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testDelete() {
- int number = given().pathParam("project", "1")
- .body(new Topology.Create("Delete Topology", List.of()))
- .contentType(ContentType.JSON)
- .when()
- .post()
- .then()
- .statusCode(200)
- .contentType(ContentType.JSON)
- .extract()
- .path("number");
-
- given().pathParam("project", "1")
- .when()
- .delete("/" + number)
- .then()
- .statusCode(200)
- .contentType(ContentType.JSON);
+ given().pathParam("project", "1").when().delete("/3").then().statusCode(200);
}
/**
* Test to delete a topology that is still being used by a scenario.
+ * TODO: fix later
*/
@Test
@TestSecurity(
- user = "owner",
+ user = "test_user_1",
roles = {"openid"})
public void testDeleteUsed() {
given().pathParam("project", "1")
.when()
- .delete("/1") // Topology 1 is still used by scenario 1 and 2
+ .delete("/4") // Topology 1 is still used by scenario 1 and 2
.then()
.statusCode(403)
.contentType(ContentType.JSON);
diff --git a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/service/UserAccountingServiceTest.java b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/service/UserAccountingServiceTest.java
index d1d82097..91e3eb66 100644
--- a/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/service/UserAccountingServiceTest.java
+++ b/opendc-web/opendc-web-server/src/test/java/org/opendc/web/server/service/UserAccountingServiceTest.java
@@ -33,9 +33,9 @@ import static org.mockito.ArgumentMatchers.anyString;
import io.quarkus.panache.mock.PanacheMock;
import io.quarkus.test.junit.QuarkusTest;
+import jakarta.persistence.EntityExistsException;
import java.time.Duration;
import java.time.LocalDate;
-import javax.persistence.EntityExistsException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
diff --git a/opendc-web/opendc-web-ui-quarkus-deployment/build.gradle.kts b/opendc-web/opendc-web-ui-quarkus-deployment/build.gradle.kts
index 5a42aaea..6be49e22 100644
--- a/opendc-web/opendc-web-ui-quarkus-deployment/build.gradle.kts
+++ b/opendc-web/opendc-web-ui-quarkus-deployment/build.gradle.kts
@@ -22,7 +22,7 @@
description = "Quarkus extension for serving OpenDC web interface"
-/* Build configuration */
+// Build configuration
plugins {
`java-library-conventions`
}
diff --git a/opendc-web/opendc-web-ui/build.gradle.kts b/opendc-web/opendc-web-ui/build.gradle.kts
index 79160a2e..777098d4 100644
--- a/opendc-web/opendc-web-ui/build.gradle.kts
+++ b/opendc-web/opendc-web-ui/build.gradle.kts
@@ -43,27 +43,29 @@ node {
version.set(libs.versions.node.get())
}
-val formatTask = tasks.register<NpmTask>("prettierFormat") {
- group = "formatting"
- description = "Use Prettier to format the JavaScript codebase"
-
- args.set(listOf("run", "format"))
- dependsOn(tasks.npmInstall)
- inputs.dir("src")
- inputs.files("package.json", "next.config.js", ".prettierrc.yaml")
- outputs.upToDateWhen { true }
-}
+val formatTask =
+ tasks.register<NpmTask>("prettierFormat") {
+ group = "formatting"
+ description = "Use Prettier to format the JavaScript codebase"
+
+ args.set(listOf("run", "format"))
+ dependsOn(tasks.npmInstall)
+ inputs.dir("src")
+ inputs.files("package.json", "next.config.js", ".prettierrc.yaml")
+ outputs.upToDateWhen { true }
+ }
-val lintTask = tasks.register<NpmTask>("nextLint") {
- group = "verification"
- description = "Use ESLint to check for problems"
+val lintTask =
+ tasks.register<NpmTask>("nextLint") {
+ group = "verification"
+ description = "Use ESLint to check for problems"
- args.set(listOf("run", "lint"))
- dependsOn(tasks.npmInstall)
- inputs.dir("src")
- inputs.files("package.json", "next.config.js", ".eslintrc")
- outputs.upToDateWhen { true }
-}
+ args.set(listOf("run", "lint"))
+ dependsOn(tasks.npmInstall)
+ inputs.dir("src")
+ inputs.files("package.json", "next.config.js", ".eslintrc")
+ outputs.upToDateWhen { true }
+ }
tasks.register<NpmTask>("nextDev") {
group = "build"
@@ -77,30 +79,32 @@ tasks.register<NpmTask>("nextDev") {
outputs.upToDateWhen { true }
}
-val buildTask = tasks.register<NpmTask>("nextBuild") {
- group = "build"
- description = "Build the Next.js project"
-
- args.set(listOf("run", "build"))
-
- val env = listOf(
- "NEXT_PUBLIC_API_BASE_URL",
- "NEXT_PUBLIC_SENTRY_DSN",
- "NEXT_PUBLIC_AUTH0_DOMAIN",
- "NEXT_PUBLIC_AUTH0_CLIENT_ID",
- "NEXT_PUBLIC_AUTH0_AUDIENCE"
- )
- for (envvar in env) {
- environment.put(envvar, "%%$envvar%%")
+val buildTask =
+ tasks.register<NpmTask>("nextBuild") {
+ group = "build"
+ description = "Build the Next.js project"
+
+ args.set(listOf("run", "build"))
+
+ val env =
+ listOf(
+ "NEXT_PUBLIC_API_BASE_URL",
+ "NEXT_PUBLIC_SENTRY_DSN",
+ "NEXT_PUBLIC_AUTH0_DOMAIN",
+ "NEXT_PUBLIC_AUTH0_CLIENT_ID",
+ "NEXT_PUBLIC_AUTH0_AUDIENCE",
+ )
+ for (envvar in env) {
+ environment.put(envvar, "%%$envvar%%")
+ }
+
+ dependsOn(tasks.npmInstall)
+ inputs.dir(project.fileTree("src"))
+ inputs.dir("node_modules")
+ inputs.files("package.json", "next.config.js")
+ outputs.dir(layout.buildDirectory.dir("next"))
}
- dependsOn(tasks.npmInstall)
- inputs.dir(project.fileTree("src"))
- inputs.dir("node_modules")
- inputs.files("package.json", "next.config.js")
- outputs.dir(layout.buildDirectory.dir("next"))
-}
-
tasks.register<NpmTask>("nextStart") {
group = "build"
description = "Build the Next.js project"