Skip to content

Commit ed2aed0

Browse files
committed
Add IntOrStringDeserializer
1 parent ea8cf22 commit ed2aed0

8 files changed

Lines changed: 105 additions & 156 deletions

File tree

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* ShinyProxy-Operator
3+
*
4+
* Copyright (C) 2021-2024 Open Analytics
5+
*
6+
* ===========================================================================
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the Apache License as published by
10+
* The Apache Software Foundation, either version 2 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* Apache License for more details.
17+
*
18+
* You should have received a copy of the Apache License
19+
* along with this program. If not, see <http://www.apache.org/licenses/>
20+
*/
21+
package eu.openanalytics.shinyproxyoperator
22+
23+
import com.fasterxml.jackson.core.JsonParser
24+
import com.fasterxml.jackson.databind.DeserializationContext
25+
import com.fasterxml.jackson.databind.JsonNode
26+
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
27+
import io.fabric8.kubernetes.api.model.IntOrString
28+
29+
class IntOrStringDeserializer : StdDeserializer<IntOrString>(IntOrString::class.java) {
30+
31+
override fun deserialize(jsonParser: JsonParser, deserializationContext: DeserializationContext): IntOrString {
32+
val node = jsonParser.codec.readTree<JsonNode>(jsonParser)
33+
val value = node.asText()
34+
35+
val asInt = value?.toIntOrNull()
36+
if (asInt != null) {
37+
return IntOrString(asInt)
38+
}
39+
40+
return IntOrString(value)
41+
}
42+
43+
}

src/main/kotlin/eu/openanalytics/shinyproxyoperator/components/IngressFactory.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class IngressFactory(private val kubeClient: KubernetesClient) {
3333

3434
private val logger = KotlinLogging.logger {}
3535

36-
private val ingressPatcher = IngressPatcher()
36+
private val ingressPatcher = Patcher()
3737

3838
fun create(shinyProxy: ShinyProxy, latestShinyProxyInstance: ShinyProxyInstance) {
3939
val labels = LabelFactory.labelsForShinyProxy(shinyProxy).toMutableMap()

src/main/kotlin/eu/openanalytics/shinyproxyoperator/components/IngressPatcher.kt

Lines changed: 0 additions & 63 deletions
This file was deleted.

src/main/kotlin/eu/openanalytics/shinyproxyoperator/components/PodTemplateSpecPatcher.kt renamed to src/main/kotlin/eu/openanalytics/shinyproxyoperator/components/Patcher.kt

Lines changed: 57 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,76 @@
2121
package eu.openanalytics.shinyproxyoperator.components
2222

2323
import com.fasterxml.jackson.databind.ObjectMapper
24+
import com.fasterxml.jackson.databind.module.SimpleModule
2425
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
2526
import com.fasterxml.jackson.datatype.jsr353.JSR353Module
26-
import io.fabric8.kubernetes.api.model.HTTPGetAction
27+
import eu.openanalytics.shinyproxyoperator.IntOrStringDeserializer
2728
import io.fabric8.kubernetes.api.model.IntOrString
2829
import io.fabric8.kubernetes.api.model.PodTemplateSpec
30+
import io.fabric8.kubernetes.api.model.Service
31+
import io.fabric8.kubernetes.api.model.networking.v1.Ingress
2932
import mu.KotlinLogging
3033
import javax.json.JsonPatch
3134
import javax.json.JsonStructure
3235

33-
class PodTemplateSpecPatcher {
36+
37+
class Patcher {
3438
private val mapper = ObjectMapper(YAMLFactory())
3539
private val logger = KotlinLogging.logger { }
3640

3741
init {
3842
mapper.registerModule(JSR353Module())
43+
val module = SimpleModule()
44+
module.addDeserializer(IntOrString::class.java, IntOrStringDeserializer())
45+
mapper.registerModule(module)
46+
}
47+
48+
/**
49+
* Applies a JsonPatch to the given Service.
50+
*/
51+
fun patch(service: Service, patch: JsonPatch?): Service {
52+
if (patch == null) {
53+
return service
54+
}
55+
56+
logger.debug { "Original Service (before applying patches): ${mapper.writeValueAsString(service)}" }
57+
58+
// 1. convert Service to javax.json.JsonValue object.
59+
// This conversion does not actually convert to a string, but some internal
60+
// representation of Jackson.
61+
val podAsJsonValue: JsonStructure = mapper.convertValue(service, JsonStructure::class.java)
62+
// 2. apply patch
63+
val patchedAsJsonValue: JsonStructure = patch.apply(podAsJsonValue)
64+
// 3. convert back to a Service
65+
val patchedService = mapper.convertValue(patchedAsJsonValue, Service::class.java)
66+
67+
logger.debug { "Patched Service (after applying patches): ${mapper.writeValueAsString(patchedService)}" }
68+
69+
return patchedService
70+
}
71+
72+
/**
73+
* Applies a JsonPatch to the given Ingress.
74+
*/
75+
fun patch(ingress: Ingress, patch: JsonPatch?): Ingress {
76+
if (patch == null) {
77+
return ingress
78+
}
79+
80+
logger.debug { "Original Ingress (before applying patches): ${mapper.writeValueAsString(ingress)}" }
81+
82+
// 1. convert PodTemplate to javax.json.JsonValue object.
83+
// This conversion does not actually convert to a string, but some internal
84+
// representation of Jackson.
85+
val podAsJsonValue: JsonStructure = mapper.convertValue(ingress, JsonStructure::class.java)
86+
// 2. apply patch
87+
val patchedAsJsonValue: JsonStructure = patch.apply(podAsJsonValue)
88+
// 3. convert back to a PodTemplate
89+
val patchedIngress = mapper.convertValue(patchedAsJsonValue, Ingress::class.java)
90+
91+
logger.debug { "Patched Ingress (after applying patches): ${mapper.writeValueAsString(patchedIngress)}" }
92+
93+
return patchedIngress
3994
}
4095

4196
/**
@@ -57,24 +112,9 @@ class PodTemplateSpecPatcher {
57112
// 3. convert back to a PodTemplate
58113
val patchedPodTemplateSpec = mapper.convertValue(patchedPodAsJsonValue, PodTemplateSpec::class.java)
59114

60-
for (container in patchedPodTemplateSpec.spec.containers) {
61-
container.livenessProbe?.httpGet?.let { patchHttpGet(it) }
62-
container.readinessProbe?.httpGet?.let { patchHttpGet(it) }
63-
container.startupProbe?.httpGet?.let { patchHttpGet(it) }
64-
}
65-
66115
logger.debug { "Patched PodTemplateSpec (after applying patches): ${mapper.writeValueAsString(patchedPodTemplateSpec)}" }
67116

68117
return patchedPodTemplateSpec
69118
}
70119

71-
private fun patchHttpGet(httpGet: HTTPGetAction) {
72-
if (httpGet.port.intVal == null) {
73-
val asInt = httpGet.port.strVal.toIntOrNull()
74-
if (asInt != null) {
75-
httpGet.port = IntOrString(asInt)
76-
}
77-
}
78-
}
79-
80120
}

src/main/kotlin/eu/openanalytics/shinyproxyoperator/components/PodTemplateSpecFactory.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import io.fabric8.kubernetes.api.model.*
2727

2828
class PodTemplateSpecFactory {
2929

30-
private val podTemplatePatcher = PodTemplateSpecPatcher()
30+
private val podTemplatePatcher = Patcher()
3131

3232
fun create(shinyProxy: ShinyProxy, shinyProxyInstance: ShinyProxyInstance): PodTemplateSpec {
3333

src/main/kotlin/eu/openanalytics/shinyproxyoperator/components/ServiceFactory.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class ServiceFactory(private val serviceClient: MixedOperation<Service, ServiceL
3434

3535
private val logger = KotlinLogging.logger {}
3636

37-
private val servicePatcher = ServicePatcher()
37+
private val servicePatcher = Patcher()
3838

3939
fun create(shinyProxy: ShinyProxy, latestShinyProxyInstance: ShinyProxyInstance) {
4040
val labels = LabelFactory.labelsForShinyProxy(shinyProxy).toMutableMap()

src/main/kotlin/eu/openanalytics/shinyproxyoperator/components/ServicePatcher.kt

Lines changed: 0 additions & 71 deletions
This file was deleted.

src/test/resources/configs/simple_config_with_patches.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ spec:
4444
failureThreshold: 1
4545
httpGet:
4646
path: /actuator/health/liveness
47-
port: "9090"
47+
port: 9090
4848
scheme: HTTP
4949
periodSeconds: 1
5050
initialDelaySeconds: 30
@@ -56,7 +56,7 @@ spec:
5656
failureThreshold: 1
5757
httpGet:
5858
path: /actuator/health/readiness
59-
port: "9090"
59+
port: 9090
6060
scheme: HTTP
6161
periodSeconds: 1
6262
initialDelaySeconds: 30

0 commit comments

Comments
 (0)