Skip to content

Commit a87aad4

Browse files
committed
Support SP add and delete
1 parent fcb9d08 commit a87aad4

6 files changed

Lines changed: 92 additions & 43 deletions

File tree

src/main/kotlin/eu/openanalytics/shinyproxyoperator/controller/ResourceListener.kt

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@ import io.fabric8.kubernetes.api.model.HasMetadata
55
import io.fabric8.kubernetes.api.model.OwnerReference
66
import io.fabric8.kubernetes.client.informers.ResourceEventHandler
77
import io.fabric8.kubernetes.client.informers.SharedIndexInformer
8-
import io.fabric8.kubernetes.client.informers.cache.Cache
98
import io.fabric8.kubernetes.client.informers.cache.Lister
109
import kotlinx.coroutines.channels.SendChannel
1110
import kotlinx.coroutines.runBlocking
1211
import mu.KotlinLogging
1312

14-
class ResourceListener<T : HasMetadata>(private val channel: SendChannel<String>,
13+
class ResourceListener<T : HasMetadata>(private val channel: SendChannel<ShinyProxyEvent>,
1514
informer: SharedIndexInformer<T>,
1615
private val shinyProxyLister: Lister<ShinyProxy>) {
1716

@@ -37,19 +36,12 @@ class ResourceListener<T : HasMetadata>(private val channel: SendChannel<String>
3736
}
3837

3938
private suspend fun enqueuResource(resource: T) {
40-
val shinyProxy = if (resource is ShinyProxy) {
41-
resource
42-
} else {
43-
val ownerReference = getControllerOf(resource) ?: return
44-
if (ownerReference.kind.toLowerCase() != "shinyproxy") {
45-
return
46-
}
47-
shinyProxyLister[ownerReference.name] ?: return
48-
}
49-
val key = Cache.metaNamespaceKeyFunc(shinyProxy)
50-
if (key != null && key.isNotEmpty()) {
51-
channel.send(key)
39+
val ownerReference = getControllerOf(resource) ?: return
40+
if (ownerReference.kind.toLowerCase() != "shinyproxy") {
41+
return
5242
}
43+
val shinyProxy = shinyProxyLister[ownerReference.name] ?: return
44+
channel.send(ShinyProxyEvent(ShinyProxyEventType.UPDATE_DEPENDENCY, shinyProxy))
5345
}
5446

5547

src/main/kotlin/eu/openanalytics/shinyproxyoperator/controller/ShinyProxyController.kt

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ class ShinyProxyController(private val kubernetesClient: KubernetesClient,
2121
private val shinyProxyInformer: SharedIndexInformer<ShinyProxy>,
2222
namespace: String) {
2323

24-
private val workqueue = Channel<String>()
24+
private val workqueue = Channel<ShinyProxyEvent>()
2525
private val shinyProxyLister = Lister(shinyProxyInformer.indexer, namespace)
2626
private val replicaSetLister = Lister(replicaSetInformer.indexer, namespace)
2727
private val configMapLister = Lister(configMapInformer.indexer, namespace)
2828
private val serviceLister = Lister(serviceInformer.indexer, namespace)
29-
private val shinyProxyListener = ResourceListener(workqueue, shinyProxyInformer, shinyProxyLister)
29+
private val shinyProxyListener = ShinyProxyListener(workqueue, shinyProxyInformer, shinyProxyLister)
3030
private val replicaSetListener = ResourceListener(workqueue, replicaSetInformer, shinyProxyLister)
3131
private val serviceListener = ResourceListener(workqueue, serviceInformer, shinyProxyLister)
3232
private val configMapListener = ResourceListener(workqueue, configMapInformer, shinyProxyLister)
@@ -44,27 +44,43 @@ class ShinyProxyController(private val kubernetesClient: KubernetesClient,
4444
}
4545
while (true) {
4646
try {
47-
val key = workqueue.receive()
48-
if (key.isEmpty() || !key.contains("/")) {
49-
logger.warn { "invalid resource key: $key" }
50-
}
51-
52-
val name = key.split("/").toTypedArray()[1]
53-
val shinyProxy: ShinyProxy? = shinyProxyLister[key.split("/").toTypedArray()[1]]
47+
val event = workqueue.receive()
5448

55-
if (shinyProxy == null) {
56-
logger.warn { "ShinyProxy $name in workqueue no longer exists" }
57-
return
49+
when (event.eventType) {
50+
ShinyProxyEventType.ADD -> {
51+
reconcileSingleShinyProxy(event.shinyProxy)
52+
}
53+
ShinyProxyEventType.UPDATE -> {
54+
// TODO calculate hash -> reconcile
55+
}
56+
ShinyProxyEventType.DELETE -> {
57+
deleteSingleShinyProxy(event.shinyProxy)
58+
}
59+
ShinyProxyEventType.UPDATE_DEPENDENCY -> {
60+
reconcileSingleShinyProxy(event.shinyProxy)
61+
}
5862
}
5963

60-
reconcileSingleShinyProxy(shinyProxy)
6164
} catch (interruptedException: InterruptedException) {
6265
Thread.currentThread().interrupt()
6366
logger.warn { "controller interrupted.." }
6467
}
6568
}
6669
}
6770

71+
private fun deleteSingleShinyProxy(shinyProxy: ShinyProxy) {
72+
logger.info { "DeleteSingleShinyProxy: ${shinyProxy.metadata.name}" }
73+
for (service in resourceRetriever.getServiceByLabel(APP_LABEL, shinyProxy.metadata.name)) {
74+
kubernetesClient.resource(service).delete()
75+
}
76+
for (replicaSet in resourceRetriever.getReplicaSetByLabel(APP_LABEL, shinyProxy.metadata.name)) {
77+
kubernetesClient.resource(replicaSet).delete()
78+
}
79+
for (configMap in resourceRetriever.getConfigMapByLabel(APP_LABEL, shinyProxy.metadata.name)) {
80+
kubernetesClient.resource(configMap).delete()
81+
}
82+
}
83+
6884
private suspend fun reconcileSingleShinyProxy(shinyProxy: ShinyProxy) {
6985
logger.info { "ReconcileSingleShinyProxy: ${shinyProxy.metadata.name}" }
7086
val configMaps = resourceRetriever.getConfigMapByLabel(APP_LABEL, shinyProxy.metadata.name)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package eu.openanalytics.shinyproxyoperator.controller
2+
3+
import eu.openanalytics.shinyproxyoperator.crd.ShinyProxy
4+
5+
data class ShinyProxyEvent(val eventType: ShinyProxyEventType, val shinyProxy: ShinyProxy)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package eu.openanalytics.shinyproxyoperator.controller
2+
3+
enum class ShinyProxyEventType {
4+
ADD,
5+
UPDATE,
6+
DELETE,
7+
UPDATE_DEPENDENCY
8+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package eu.openanalytics.shinyproxyoperator.controller
2+
3+
import eu.openanalytics.shinyproxyoperator.crd.ShinyProxy
4+
import io.fabric8.kubernetes.api.model.HasMetadata
5+
import io.fabric8.kubernetes.api.model.OwnerReference
6+
import io.fabric8.kubernetes.client.informers.ResourceEventHandler
7+
import io.fabric8.kubernetes.client.informers.SharedIndexInformer
8+
import io.fabric8.kubernetes.client.informers.cache.Cache
9+
import io.fabric8.kubernetes.client.informers.cache.Lister
10+
import kotlinx.coroutines.channels.SendChannel
11+
import kotlinx.coroutines.runBlocking
12+
import mu.KotlinLogging
13+
14+
class ShinyProxyListener(private val channel: SendChannel<ShinyProxyEvent>,
15+
informer: SharedIndexInformer<ShinyProxy>,
16+
private val shinyProxyLister: Lister<ShinyProxy>) {
17+
18+
private val logger = KotlinLogging.logger {}
19+
20+
init {
21+
informer.addEventHandler(object : ResourceEventHandler<ShinyProxy> {
22+
override fun onAdd(shinyProxy: ShinyProxy) {
23+
logger.debug { "ShinyProxy::OnAdd ${shinyProxy.metadata.name}" }
24+
runBlocking { channel.send(ShinyProxyEvent(ShinyProxyEventType.ADD, shinyProxy)) }
25+
}
26+
27+
override fun onUpdate(shinyProxy: ShinyProxy, newShinyProxy: ShinyProxy) {
28+
logger.debug { "ShinyProxy::OnUpdate ${shinyProxy.metadata.name}" }
29+
// TODO new shinyProxy
30+
runBlocking { channel.send(ShinyProxyEvent(ShinyProxyEventType.UPDATE, shinyProxy)) }
31+
}
32+
33+
override fun onDelete(shinyProxy: ShinyProxy, b: Boolean) {
34+
logger.debug { "ShinyProxy::OnDelete ${shinyProxy.metadata.name}" }
35+
runBlocking { channel.send(ShinyProxyEvent(ShinyProxyEventType.DELETE, shinyProxy)) }
36+
}
37+
})
38+
}
39+
40+
}

src/main/resources/cr.yaml

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,36 +11,24 @@ spec:
1111
heartbeatTimeout: 60000
1212
port: 8080
1313
authentication: simple
14-
#admin-groups: scientists
1514
containerBackend: kubernetes
16-
#kubernetes:
17-
#url: https://172.17.0.2:8443
18-
# Example: 'simple' authentication configuration
1915
users:
2016
- name: jack
2117
password: password
2218
groups: scientists
2319
- name: jeff
2420
password: password
2521
groups: mathematicians
26-
# Example: 'ldap' authentication configuration
2722
specs:
2823
- id: 01_hello
2924
displayName: Hello Application
3025
description: Application which demonstrates the basics of a Shiny app
3126
containerCmd: ["R", "-e", "shinyproxy::run_01_hello()"]
3227
containerImage: openanalytics/shinyproxy-demo
33-
#kubernetes-pod-patches: |
34-
#- op: replace
35-
#path: /metadata/namespace
36-
#value: my-namespace
37-
#- op: add
38-
#path: /spec/containers/0/resources
39-
#value:
40-
#requests:
41-
#cpu: "1"
42-
#limits:
43-
#cpu: "1"
28+
kubernetes-pod-patches: |
29+
- op: replace
30+
path: /metadata/namespace
31+
value: my-namespace
4432
- id: 06_tabsets
4533
container-cmd: ["R", "-e", "shinyproxy::run_06_tabsets()"]
4634
container-image: openanalytics/shinyproxy-demo

0 commit comments

Comments
 (0)