Fix production health build identification
Mount the versioned health route instead of the legacy shadowing handler so deployments can verify the exact running image.
This commit is contained in:
@@ -108,6 +108,7 @@ import com.osglab.account.features.gateway.services.GatewayBearerIdentity
|
||||
import com.osglab.account.features.gateway.services.GatewayGrantService
|
||||
import com.osglab.account.features.gateway.services.GatewayReconciliationService
|
||||
import com.osglab.account.features.gateway.services.GatewayService
|
||||
import com.osglab.account.features.health.healthRoutes
|
||||
import com.osglab.account.features.integrity.AppAttestCrypto
|
||||
import com.osglab.account.features.integrity.AppAttestRepository
|
||||
import com.osglab.account.features.integrity.AppAttestService
|
||||
@@ -152,8 +153,6 @@ import io.ktor.client.engine.cio.CIO
|
||||
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation as ClientContentNegotiation
|
||||
import io.ktor.client.plugins.HttpTimeout
|
||||
import io.ktor.client.plugins.websocket.WebSockets as ClientWebSockets
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.serialization.kotlinx.json.json
|
||||
import io.ktor.server.application.Application
|
||||
import io.ktor.server.application.ApplicationStopped
|
||||
@@ -169,9 +168,6 @@ import io.ktor.server.plugins.ratelimit.RateLimitName
|
||||
import io.ktor.server.plugins.ratelimit.rateLimit
|
||||
import io.ktor.server.request.httpMethod
|
||||
import io.ktor.server.response.respond
|
||||
import io.ktor.server.response.respondText
|
||||
import io.ktor.server.routing.get
|
||||
import io.ktor.server.routing.Route
|
||||
import io.ktor.server.routing.routing
|
||||
import io.ktor.server.websocket.WebSockets
|
||||
import kotlinx.serialization.json.Json
|
||||
@@ -379,22 +375,6 @@ fun Application.module() {
|
||||
}
|
||||
}
|
||||
|
||||
fun Route.healthRoutes(databaseFactory: DatabaseFactory? = null) {
|
||||
get("/health") { call.respondText("""{"status":"UP"}""", ContentType.Application.Json) }
|
||||
get("/health/live") { call.respondText("""{"status":"UP"}""", ContentType.Application.Json) }
|
||||
get("/health/ready") {
|
||||
if (databaseFactory?.isReady() == true) {
|
||||
call.respondText("""{"status":"UP"}""", ContentType.Application.Json)
|
||||
} else {
|
||||
call.respondText(
|
||||
"""{"status":"DOWN"}""",
|
||||
ContentType.Application.Json,
|
||||
HttpStatusCode.ServiceUnavailable,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun accountServerModule(config: AppConfig): Module = module {
|
||||
single { config }
|
||||
single { DatabaseFactory(config.database) }
|
||||
|
||||
@@ -1,16 +1,23 @@
|
||||
package com.osglab.account
|
||||
|
||||
import com.osglab.account.config.AppConfig
|
||||
import com.osglab.account.config.DatabaseFactory
|
||||
import com.osglab.account.features.credits.repositories.BillingTransactionRunner
|
||||
import com.osglab.account.features.credits.repositories.BillingUnitOfWork
|
||||
import com.osglab.account.features.credits.services.CreditOperations
|
||||
import com.osglab.account.features.credits.services.CreditService
|
||||
import com.osglab.account.features.health.healthRoutes
|
||||
import com.osglab.account.features.referrals.services.ReferralOperations
|
||||
import com.osglab.account.features.referrals.services.ReferralService
|
||||
import io.mockk.mockk
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.serialization.kotlinx.json.json
|
||||
import io.ktor.server.application.install
|
||||
import io.ktor.server.config.MapApplicationConfig
|
||||
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation
|
||||
import io.ktor.server.routing.routing
|
||||
import io.ktor.server.testing.testApplication
|
||||
import org.koin.dsl.koinApplication
|
||||
@@ -21,11 +28,23 @@ import kotlin.test.Test
|
||||
class ApplicationTest {
|
||||
@Test
|
||||
fun `liveness endpoint remains independent of external services`() = testApplication {
|
||||
val buildSha = "a".repeat(40)
|
||||
application {
|
||||
routing { healthRoutes() }
|
||||
install(ContentNegotiation) {
|
||||
json()
|
||||
}
|
||||
routing {
|
||||
healthRoutes(
|
||||
databaseFactory = mockk<DatabaseFactory>(relaxed = true),
|
||||
buildSha = buildSha,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
client.get("/health/live").status shouldBe HttpStatusCode.OK
|
||||
client.get("/health/live").apply {
|
||||
status shouldBe HttpStatusCode.OK
|
||||
bodyAsText() shouldBe """{"status":"UP","buildSha":"$buildSha"}"""
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user