Compare commits

...
29 Commits
Author SHA1 Message Date
2martens 46b1b32708 Properties must be changeable with setters
continuous-integration/drone/push Build is failing
2023-08-17 01:52:50 +02:00
2martens 519101023c Change message [CI SKIP] 2023-08-17 01:42:01 +02:00
2martens 82b4f51390 Require configserver on prod
continuous-integration/drone/push Build is failing
2023-08-17 01:38:26 +02:00
2martens 3256939ac7 Change message [CI SKIP] 2023-08-17 01:20:17 +02:00
2martens 02e4c5318d Fix bootstrap servers on prod
continuous-integration/drone/push Build is failing
2023-08-17 01:14:03 +02:00
2martens f06abd2838 Add application name
continuous-integration/drone/push Build is failing
2023-08-17 01:12:38 +02:00
2martens f0297f2d2c Changed prod message [CI SKIP] 2023-08-17 01:10:11 +02:00
2martens ec23bd4d32 Connect with kafka using bootstrap servers
continuous-integration/drone/push Build is failing
2023-08-17 00:53:05 +02:00
2martens bab1892673 Added kafka server config
continuous-integration/drone/push Build is failing
2023-08-17 00:42:53 +02:00
2martens 247fe83caa Changed config [CI SKIP] 2023-08-17 00:36:27 +02:00
2martens 5fe6165373 Remove property reload service
continuous-integration/drone/push Build is failing
2023-08-17 00:35:50 +02:00
2martens 64a8f17e6e Change greeting on dev [CI SKIP] 2023-08-17 00:04:56 +02:00
2martens 5eff527c48 Enable config server locally
continuous-integration/drone/push Build is failing
2023-08-17 00:02:57 +02:00
2martens 642713e14c Fixed rest health indicator 2023-08-17 00:02:45 +02:00
2martens ff8b205124 Add Kafka dependency 2023-08-16 23:08:49 +02:00
2martens 8c5f925e36 Change greeting message [CI SKIP] 2023-08-16 22:39:24 +02:00
2martens fe5cd41749 Specify metadata in jar task (likely used by Jib)
continuous-integration/drone/push Build is failing
2023-08-16 22:31:05 +02:00
2martens 3a25e33f3f Prevent NPE 2023-08-16 22:30:50 +02:00
2martens ec625fb7b5 Use service properties to check successful change
continuous-integration/drone/push Build is failing
2023-08-16 22:21:53 +02:00
2martens c8e4474175 Remove configserver import from general configuration
continuous-integration/drone/push Build is failing
2023-08-16 22:09:50 +02:00
2martens 499c85ae49 Load configserver only in production and move refreshable prod properties to wahlrecht-prod
continuous-integration/drone/push Build is failing
2023-08-16 22:08:50 +02:00
2martens e88d98efc1 Dummy change
continuous-integration/drone/push Build is failing
2023-08-16 21:56:57 +02:00
2martens 8d545aa7fb Moved refreshable configuration to config sub-directory
continuous-integration/drone/push Build is failing
2023-08-16 21:54:42 +02:00
2martens a04094bc60 Move configserver import to bootstrap.yaml
continuous-integration/drone/push Build is failing
2023-08-16 21:09:15 +02:00
2martens 7d68612e57 Adjusted path to configserver
continuous-integration/drone/push Build is failing
2023-08-16 20:17:57 +02:00
2martens 64295db0e7 Added environments for http requests
continuous-integration/drone/push Build is failing
2023-08-16 20:08:54 +02:00
2martens 6dcd302ab7 OPTIONS method does not have to be allowed 2023-08-16 20:08:01 +02:00
2martens e50e769e22 Added production domain as allowed origin
continuous-integration/drone/push Build is failing
2023-08-16 12:52:17 +02:00
2martens b7c85e2368 Reversed code format 2023-08-16 01:00:48 +02:00
19 changed files with 66 additions and 73 deletions
@@ -62,7 +62,7 @@ tasks.named("buildAll") {
val formatter: DateTimeFormatter = ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
tasks.bootJar {
tasks.jar {
manifest {
attributes["Implementation-Title"] = rootProject.name
attributes["Implementation-Version"] = archiveVersion.get()
+1
View File
@@ -38,6 +38,7 @@ spring-boot-oauth2-resource-server = { module = "org.springframework.boot:spring
spring-boot-config = { module = "org.springframework.boot:spring-boot-configuration-processor", version.ref = "spring-boot" }
spring-cloud = { module = "org.springframework.cloud:spring-cloud-dependencies", version.ref = "spring-cloud" }
spring-cloud-starter = { module = "org.springframework.cloud:spring-cloud-starter" }
spring-cloud-starter-bus-kafka = { module = "org.springframework.cloud:spring-cloud-starter-bus-kafka" }
spring-cloud-starter-config = { module = "org.springframework.cloud:spring-cloud-starter-config" }
spring-cloud-config-server = { module = "org.springframework.cloud:spring-cloud-config-server" }
spring-boot-starter = { module = "org.springframework.boot:spring-boot-starter" }
+1 -1
View File
@@ -1,4 +1,4 @@
POST http://localhost:12000/wahlrecht/v1/calculate
POST {{backend}}/wahlrecht/v1/calculate
Content-Type: application/json
{
+2
View File
@@ -0,0 +1,2 @@
GET {{backend}}/wahlrecht/v1/elections
Content-Type: application/json
+8
View File
@@ -0,0 +1,8 @@
{
"dev": {
"backend": "http://localhost:12000"
},
"prod" : {
"backend": "https://api.2martens.de"
}
}
@@ -1,2 +0,0 @@
server:
port: 12000
+1
View File
@@ -10,4 +10,5 @@ dependencies {
annotationProcessor(libs.mapstruct.processor)
kapt(libs.mapstruct.processor)
implementation(libs.spring.cloud.starter.config)
implementation(libs.spring.cloud.starter.bus.kafka)
}
@@ -36,7 +36,7 @@ open class OpenApiConfiguration {
.version(apiVersion)
.description(apiDescription)
)
.addServersItem(Server().url("http://localhost:12000"))
.addServersItem(Server().url("https://api.2martens.de"))
.addServersItem(Server().url("http://localhost:12000"))
.addServersItem(Server().url("https://api.2martens.de"))
}
}
@@ -16,10 +16,13 @@ open class WebConfiguration(private val headerInterceptorRest: HeaderInterceptor
override fun addCorsMappings(registry: CorsRegistry) {
val registration = registry.addMapping("/**")
registration.allowedMethods(
HttpMethod.GET.name(), HttpMethod.POST.name(),
HttpMethod.PUT.name(), HttpMethod.OPTIONS.name()
HttpMethod.GET.name(), HttpMethod.POST.name(),
HttpMethod.PUT.name(), HttpMethod.HEAD.name()
)
registration.allowCredentials(true)
registration.allowedOrigins("http://localhost:4200")
registration.allowedOrigins(
"http://localhost:4200",
"https://wahlrecht.2martens.de"
)
}
}
@@ -32,14 +32,16 @@ class VersionHtmlController {
}
private fun getTitle(): String {
val title = VersionHtmlController::class.java.getPackage().implementationTitle
val title = VersionHtmlController::class.java.`package`.implementationTitle
?: return "application"
return title.ifBlank {
"application"
}
}
private fun getVersion(): String {
val version = VersionHtmlController::class.java.getPackage().implementationVersion
val version = VersionHtmlController::class.java.`package`.implementationVersion
?: return "DEVELOPER"
return version.ifBlank {
"DEVELOPER"
}
@@ -1,5 +1,6 @@
package de.twomartens.wahlrecht.controller.v1
import de.twomartens.wahlrecht.property.ServiceProperties
import io.swagger.v3.oas.annotations.Hidden
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
@@ -7,11 +8,12 @@ import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping(value = ["/wahlrecht/v1"])
class HealthCheckController {
class HealthCheckController(private val properties: ServiceProperties) {
@Hidden
@GetMapping("/healthCheck")
fun healthCheck(message: String): String {
return message
return properties.greeting.format(message)
}
}
@@ -1,6 +1,7 @@
package de.twomartens.wahlrecht.monitoring.actuator
import de.twomartens.wahlrecht.interceptor.HeaderInterceptorRest
import de.twomartens.wahlrecht.property.ServiceProperties
import org.springframework.boot.actuate.health.Health
import org.springframework.boot.actuate.health.HealthIndicator
import org.springframework.boot.actuate.health.Status
@@ -28,8 +29,10 @@ import java.time.Clock
*/
@Component
class RestHealthIndicator(
clock: Clock, interceptor: HeaderInterceptorRest,
serverProperties: ServerProperties, private val restTemplateRestHealthIndicator: RestTemplate
clock: Clock, interceptor: HeaderInterceptorRest,
serverProperties: ServerProperties,
private val restTemplateRestHealthIndicator: RestTemplate,
private val serviceProperties: ServiceProperties
) : AbstractHealthIndicator(clock, Preparable { interceptor.markAsHealthCheck() }), HealthIndicator {
private val randomizer = SecureRandom()
private val urlPrefix: String = (HTTP_PREFIX + HOST + HOST_PORT_SEPARATOR
@@ -43,10 +46,10 @@ class RestHealthIndicator(
val random = randomizer.nextInt(100000, 999999).toString()
val url = "$urlPrefix{random}"
val response = restTemplateRestHealthIndicator.getForEntity(url, String::class.java, random)
val status = if (response.body == random) Status.UP else Status.DOWN
val status = if (response.body == serviceProperties.greeting.format(random)) Status.UP else Status.DOWN
return Health.status(status)
.withDetail(DETAIL_ENDPOINT_KEY, url)
.build()
.withDetail(DETAIL_ENDPOINT_KEY, url)
.build()
}
companion object {
@@ -9,4 +9,4 @@ import java.time.ZoneId
@RefreshScope
@ConfigurationProperties(prefix = "de.twomartens.wahlrecht")
@Schema(description = "Properties, to configure this Application")
data class ServiceProperties @ConstructorBinding constructor(val defaultTimeZone: ZoneId, val greeting: String)
data class ServiceProperties @ConstructorBinding constructor(var defaultTimeZone: ZoneId, var greeting: String)
@@ -1,41 +0,0 @@
package de.twomartens.wahlrecht.service
import mu.KotlinLogging
import org.apache.logging.log4j.message.StringMapMessage
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.cloud.context.refresh.ContextRefresher
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Service
import java.util.concurrent.TimeUnit
/**
* automatically reloads application*.yaml. reload can also be triggered manually by doing a post
* request on http://localhost:12001/actuator/refresh
*/
@Service
class PropertyReloadService(@Qualifier("configDataContextRefresher") private val contextRefresher: ContextRefresher) {
@Scheduled(
fixedDelay = REFRESH_SECONDS.toLong(),
initialDelay = REFRESH_SECONDS.toLong(),
timeUnit = TimeUnit.SECONDS
)
fun refresh() {
val properties = contextRefresher.refresh()
if (properties.isNotEmpty()) {
log.info(
StringMapMessage()
.with(PARAM_MESSAGE, "properties changed")
.with(PARAM_PROPERTIES, properties.joinToString("\n"))
.asString()
)
}
}
companion object {
const val REFRESH_SECONDS = 60
const val PARAM_MESSAGE = "message"
const val PARAM_PROPERTIES = "labels.properties"
private val log = KotlinLogging.logger {}
}
}
@@ -1,2 +1,9 @@
server.port: 12000
management.server.port: 12001
spring:
config:
import:
- "classpath:config/wahlrecht.yaml"
- "optional:configserver:http://localhost:8888/config"
@@ -0,0 +1,7 @@
spring:
config:
import:
- "configserver:http://configserver:8888/config"
kafka:
bootstrap-servers:
- kafka:9092
@@ -23,8 +23,9 @@ management:
http.server.requests: true
spring:
config:
import: "optional:configserver:http://127.0.0.1:8888/config"
cloud:
config:
name: wahlrecht
main:
banner-mode: off
profiles:
@@ -40,17 +41,6 @@ spring:
application:
name: wahlrecht
# properties for application
de.twomartens.wahlrecht:
defaultTimeZone: Europe/Berlin
greeting: "Hello %s"
statusprobe:
scheduleDuration: 60
maxKafkaFailureDuration: 5
maxBlobFailureCount: 5
maxFailurePercent: 50
springdoc:
swagger-ui:
display-request-duration: true
@@ -0,0 +1,2 @@
de.twomartens.wahlrecht:
greeting: "Moin %s, you are stage"
@@ -0,0 +1,8 @@
de.twomartens.wahlrecht:
defaultTimeZone: Europe/Berlin
greeting: "Hello %s, on millenium"
statusprobe:
scheduleDuration: 60
maxKafkaFailureDuration: 5
maxBlobFailureCount: 5
maxFailurePercent: 50