Skip to content

Commit

Permalink
Adding a GET /config route to expose the current configuration.
Browse files Browse the repository at this point in the history
  • Loading branch information
jameskbride committed Jun 20, 2024
1 parent cae29b6 commit 819f176
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 18 deletions.
20 changes: 7 additions & 13 deletions src/main/kotlin/com/jameskbride/localsns/Main.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
package com.jameskbride.localsns

import com.fasterxml.jackson.module.kotlin.registerKotlinModule
import com.jameskbride.localsns.models.Configuration
import com.typesafe.config.ConfigFactory
import io.vertx.core.AsyncResult
import io.vertx.core.Vertx
import io.vertx.core.buffer.Buffer
import io.vertx.core.json.JsonObject
import io.vertx.core.json.jackson.DatabindCodec
import org.apache.camel.impl.DefaultCamelContext
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
Expand All @@ -22,7 +19,12 @@ class Main {
fun main(args: Array<String>) {
configureObjectMappers()
val config = ConfigFactory.load()
logger.info("Starting local-sns-${config.getValue("version").unwrapped()}")
val version = config.getValue("version").unwrapped()
logger.info("Starting local-sns-$version")
val httpInterface = getHttpInterface(config)
val port = getPort(config)
logger.info("Health endpoint: http://$httpInterface:$port/health")
logger.info("Configuration endpoint: http://${httpInterface}:$port/config")
val vertx = Vertx.vertx()
val dbPath = getDbPath(config)
vertx.fileSystem()
Expand Down Expand Up @@ -72,18 +74,10 @@ class Main {

private fun readConfiguration(result: AsyncResult<Buffer>): Configuration {
val configFile = result.result()
val jsonConfig = JsonObject(configFile)
val jsonConfig = toJsonConfig(configFile)
logger.info("Loading configuration: $jsonConfig")

return jsonConfig.mapTo(Configuration::class.java)
}

private fun configureObjectMappers() {
val mapper = DatabindCodec.mapper()
mapper.registerKotlinModule()

val prettyMapper = DatabindCodec.prettyMapper()
prettyMapper.registerKotlinModule()
}
}
}
19 changes: 19 additions & 0 deletions src/main/kotlin/com/jameskbride/localsns/routes/configRoute.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.jameskbride.localsns.routes

import com.jameskbride.localsns.getDbOutputPath
import com.jameskbride.localsns.toJsonConfig
import com.typesafe.config.ConfigFactory
import io.vertx.core.Vertx
import io.vertx.ext.web.RoutingContext

val configRoute: (RoutingContext) -> Unit = { ctx: RoutingContext ->
val config = ConfigFactory.load()
val vertx = Vertx.vertx()
val dbPath = getDbOutputPath(config)
val dbFile = vertx.fileSystem().readFileBlocking(dbPath)
val configuration = toJsonConfig(dbFile)
ctx.request().response()
.setStatusCode(200)
.putHeader("context-type", "application/json")
.end(configuration.toString())
}
27 changes: 27 additions & 0 deletions src/main/kotlin/com/jameskbride/localsns/utils.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package com.jameskbride.localsns

import com.fasterxml.jackson.module.kotlin.registerKotlinModule
import com.jameskbride.localsns.models.Subscription
import com.jameskbride.localsns.models.Topic
import com.typesafe.config.Config
import io.vertx.core.Vertx
import io.vertx.core.buffer.Buffer
import io.vertx.core.json.JsonObject
import io.vertx.core.json.jackson.DatabindCodec
import io.vertx.core.shareddata.LocalMap
import io.vertx.ext.web.RoutingContext
import org.apache.logging.log4j.Logger
Expand All @@ -19,12 +23,27 @@ fun getDbPath(config: Config): String? =
fun getDbOutputPath(config: Config): String =
System.getenv("DB_OUTPUT_PATH") ?: config.getString("db.outputPath")

fun toJsonConfig(configFile: Buffer?) = JsonObject(configFile)

fun getAwsAccountId(config: Config): String =
System.getenv("AWS_ACCOUNT_ID") ?: config.getString("aws.accountId")

fun getAwsRegion(config: Config): String =
System.getenv("AWS_DEFAULT_REGION") ?: config.getString("aws.region")

fun getPort(config: Config): Int {
val httpPortEnv = System.getenv("HTTP_PORT")
val port = if (httpPortEnv !== null) {
Integer.parseInt(httpPortEnv)
} else {
config.getInt("http.port")
}
return port
}

fun getHttpInterface(config: Config): String? =
System.getenv("HTTP_INTERFACE") ?: config.getString("http.interface")

fun getTopicsMap(vertx: Vertx): LocalMap<String, Topic>? =
vertx.sharedData().getLocalMap("topics")

Expand All @@ -51,3 +70,11 @@ fun getFormAttribute(
ctx: RoutingContext,
attribute: String
): String? = ctx.request().getFormAttribute(attribute)

fun configureObjectMappers() {
val mapper = DatabindCodec.mapper()
mapper.registerKotlinModule()

val prettyMapper = DatabindCodec.prettyMapper()
prettyMapper.registerKotlinModule()
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.jameskbride.localsns.verticles

import com.jameskbride.localsns.getHttpInterface
import com.jameskbride.localsns.getPort
import com.jameskbride.localsns.routes.configRoute
import com.jameskbride.localsns.routes.getRoute
import com.jameskbride.localsns.routes.healthRoute
import com.typesafe.config.ConfigFactory
Expand All @@ -21,13 +24,11 @@ class MainVerticle : AbstractVerticle() {
router.route().handler(BodyHandler.create())
router.route("/").handler(getRoute)
router.route("/health").handler(healthRoute)
router.route("/config").handler(configRoute)

val config = ConfigFactory.load()
val httpInterface = System.getenv("HTTP_INTERFACE") ?: config.getString("http.interface")
val httpPortEnv = System.getenv("HTTP_PORT")
val port = if (httpPortEnv !== null) {
Integer.parseInt(httpPortEnv)
} else { config.getInt("http.port") }
val httpInterface = getHttpInterface(config)
val port = getPort(config)

val socketAddress = inetSocketAddress(port, httpInterface)

Expand Down
6 changes: 6 additions & 0 deletions src/test/kotlin/com/jameskbride/localsns/BaseTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.jameskbride.localsns
import com.jameskbride.localsns.models.Topic
import com.typesafe.config.ConfigFactory
import khttp.post
import khttp.get
import khttp.responses.Response
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
Expand All @@ -23,6 +24,11 @@ open class BaseTest {
}
}

fun getCurrentConfig(): Response {
val baseUrl = getBaseUrl()
return get("$baseUrl/config")
}

protected fun createValidArn(resourceName: String) =
"arn:aws:sns:us-east-1:123456789012:${resourceName}"

Expand Down
39 changes: 39 additions & 0 deletions src/test/kotlin/com/jameskbride/localsns/ConfigRouteTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.jameskbride.localsns;

import com.jameskbride.localsns.models.Configuration
import com.jameskbride.localsns.verticles.MainVerticle
import io.vertx.core.Vertx
import io.vertx.junit5.VertxExtension
import io.vertx.junit5.VertxTestContext
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith

@ExtendWith(VertxExtension::class)
class ConfigRouteTest: BaseTest() {

@BeforeEach
fun setup(vertx:Vertx, testContext:VertxTestContext) {
configureObjectMappers()
vertx.deployVerticle(MainVerticle(), testContext.succeeding { _ -> testContext.completeNow() })
}

@Test
fun `it returns the configuration`(testContext:VertxTestContext) {
val response = getCurrentConfig()

assertEquals(200, response.statusCode)
val text = response.text
val jsonConfig = io.vertx.core.json.JsonObject(text)
assertTrue(jsonConfig.containsKey("topics"))
assertTrue(jsonConfig.containsKey("subscriptions"))
assertTrue(jsonConfig.containsKey("timestamp"))
assertTrue(jsonConfig.containsKey("version"))

jsonConfig.mapTo(Configuration::class.java)

testContext.completeNow()
}
}

0 comments on commit 819f176

Please sign in to comment.