Skip to content

Commit ea8cf22

Browse files
bsauvajonLEDfan
authored andcommitted
Add kubernetesServicePatches to shinyproxy definition
1 parent 9538318 commit ea8cf22

3 files changed

Lines changed: 92 additions & 1 deletion

File tree

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

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

3535
private val logger = KotlinLogging.logger {}
3636

37+
private val servicePatcher = ServicePatcher()
38+
3739
fun create(shinyProxy: ShinyProxy, latestShinyProxyInstance: ShinyProxyInstance) {
3840
val labels = LabelFactory.labelsForShinyProxy(shinyProxy).toMutableMap()
3941
labels[LabelFactory.LATEST_INSTANCE_LABEL] = latestShinyProxyInstance.hashOfSpec
@@ -63,7 +65,8 @@ class ServiceFactory(private val serviceClient: MixedOperation<Service, ServiceL
6365
.build()
6466
//@formatter:on
6567

66-
val createdService = serviceClient.inNamespace(shinyProxy.metadata.namespace).resource(serviceDefinition).serverSideApply()
68+
val patchedService = servicePatcher.patch(serviceDefinition, shinyProxy.parsedServicePatches)
69+
val createdService = serviceClient.inNamespace(shinyProxy.metadata.namespace).resource(patchedService).serverSideApply()
6770
logger.debug { "${shinyProxy.logPrefix(latestShinyProxyInstance)} [Component/Service] Created ${createdService.metadata.name}" }
6871
}
6972

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/**
2+
* ShinyProxy-Operator
3+
*
4+
* Copyright (C) 2021-2023 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.components
22+
23+
import com.fasterxml.jackson.databind.ObjectMapper
24+
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory
25+
import com.fasterxml.jackson.datatype.jsr353.JSR353Module
26+
import io.fabric8.kubernetes.api.model.HTTPGetAction
27+
import io.fabric8.kubernetes.api.model.IntOrString
28+
import io.fabric8.kubernetes.api.model.PodTemplateSpec
29+
import io.fabric8.kubernetes.api.model.Service
30+
import io.fabric8.kubernetes.api.model.ServicePort
31+
import mu.KotlinLogging
32+
import javax.json.JsonPatch
33+
import javax.json.JsonStructure
34+
35+
class ServicePatcher {
36+
private val mapper = ObjectMapper(YAMLFactory())
37+
private val logger = KotlinLogging.logger { }
38+
39+
init {
40+
mapper.registerModule(JSR353Module())
41+
}
42+
43+
/**
44+
* Applies a JsonPatch to the given Ingress.
45+
*/
46+
fun patch(service: Service, patch: JsonPatch?): Service {
47+
if (patch == null) {
48+
return service
49+
}
50+
51+
logger.debug { "Original Service (before applying patches): ${mapper.writeValueAsString(service)}" }
52+
53+
// 1. convert Service to javax.json.JsonValue object.
54+
// This conversion does not actually convert to a string, but some internal
55+
// representation of Jackson.
56+
val podAsJsonValue: JsonStructure = mapper.convertValue(service, JsonStructure::class.java)
57+
// 2. apply patch
58+
val patchedPodAsJsonValue: JsonStructure = patch.apply(podAsJsonValue)
59+
// 3. convert back to a Service
60+
val patchedService = mapper.convertValue(patchedPodAsJsonValue, Service::class.java)
61+
62+
for (port in patchedService.spec.ports) {
63+
port.setTargetPort(IntOrString(port.targetPort.strVal.toIntOrNull()))
64+
}
65+
66+
logger.debug { "Patched Service (after applying patches): ${mapper.writeValueAsString(patchedService)}" }
67+
68+
return patchedService
69+
}
70+
71+
}

src/main/kotlin/eu/openanalytics/shinyproxyoperator/crd/ShinyProxy.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,23 @@ class ShinyProxy : CustomResource<JsonNode, ShinyProxyStatus>(), Namespaced {
145145
return@lazy null
146146
}
147147

148+
@get:JsonIgnore
149+
val parsedServicePatches: JsonPatch? by lazy {
150+
if (spec.get("kubernetesServicePatches")?.isTextual == true) {
151+
try {
152+
// convert the raw YAML string into a JsonPatch
153+
val yamlReader = ObjectMapper(YAMLFactory())
154+
yamlReader.registerModule(JSR353Module())
155+
return@lazy yamlReader.readValue(spec.get("kubernetesServicePatches").textValue(), JsonPatch::class.java)
156+
} catch (exception: Exception) {
157+
exception.printStackTrace() // log the exception for easier debugging
158+
throw exception
159+
}
160+
161+
}
162+
return@lazy null
163+
}
164+
148165
@get:JsonIgnore
149166
val subPath: String by lazy {
150167
if (spec.get("server")?.get("servlet")?.get("context-path")?.isTextual == true) {

0 commit comments

Comments
 (0)