summaryrefslogtreecommitdiff
path: root/opendc-web/opendc-web-client/src/main/kotlin
diff options
context:
space:
mode:
Diffstat (limited to 'opendc-web/opendc-web-client/src/main/kotlin')
-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
11 files changed, 158 insertions, 74 deletions
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?
}