Skip to content

Commit 9d1f1a6

Browse files
committed
Fix #33622: check duplicate fqdn and sub-paths
1 parent 3c3752c commit 9d1f1a6

2 files changed

Lines changed: 60 additions & 4 deletions

File tree

src/main/kotlin/eu/openanalytics/shinyproxyoperator/impl/kubernetes/KubernetesSource.kt

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,20 +44,28 @@ class KubernetesSource(private val shinyProxyClient: ShinyProxyClient,
4444
private val logger = KotlinLogging.logger {}
4545

4646
override suspend fun init() {
47-
informer = shinyProxyClient.inform(object : ResourceEventHandler<ShinyProxyCustomResource> {
47+
informer = shinyProxyClient.inform(null, 10 * 60 * 1000.toLong())
48+
lister = Lister(informer.indexer)
49+
informer.addEventHandler(object : ResourceEventHandler<ShinyProxyCustomResource> {
4850
override fun onAdd(shinyProxy: ShinyProxyCustomResource) {
4951
if (!isInManagedNamespace(shinyProxy)) return
5052
if (shinyProxy.status?.instances?.isNotEmpty() == true) {
5153
// ShinyProxy already has an instance -> not a new resource
5254
return
5355
}
5456
logger.debug { "${logPrefix(shinyProxy.realmId)} [Event/Add]" }
57+
if (!checkDuplicateUrl(shinyProxy)) {
58+
return
59+
}
5560
runBlocking { channel.send(ShinyProxyEvent(ShinyProxyEventType.ADD, shinyProxy.realmId, shinyProxy.metadata.name, shinyProxy.metadata.namespace, null)) }
5661
}
5762

5863
override fun onUpdate(shinyProxy: ShinyProxyCustomResource, newShinyProxy: ShinyProxyCustomResource) {
5964
if (!isInManagedNamespace(shinyProxy)) return
6065

66+
if (!checkDuplicateUrl(newShinyProxy)) {
67+
return
68+
}
6169
if (shinyProxy.hashOfCurrentSpec == newShinyProxy.hashOfCurrentSpec) {
6270
logger.debug { "${logPrefix(shinyProxy.realmId)} [Event/Update]" }
6371
runBlocking {
@@ -90,8 +98,7 @@ class KubernetesSource(private val shinyProxyClient: ShinyProxyClient,
9098

9199
override fun onDelete(shinyProxy: ShinyProxyCustomResource, b: Boolean) {
92100
}
93-
}, 10 * 60 * 1000.toLong())
94-
lister = Lister(informer.indexer)
101+
})
95102
}
96103

97104
override suspend fun run() {
@@ -112,6 +119,31 @@ class KubernetesSource(private val shinyProxyClient: ShinyProxyClient,
112119
}
113120
}
114121

122+
private fun checkDuplicateUrl(shinyProxyCustomResource: ShinyProxyCustomResource): Boolean {
123+
val shinyProxy = ShinyProxy(shinyProxyCustomResource.spec, shinyProxyCustomResource.metadata.name, shinyProxyCustomResource.metadata.namespace)
124+
for (resource in lister.list()) {
125+
val otherShinyproxy = ShinyProxy(resource.spec, resource.metadata.name, resource.metadata.namespace)
126+
if (shinyProxy.realmId == otherShinyproxy.realmId || shinyProxy.subPath != otherShinyproxy.subPath) {
127+
continue
128+
}
129+
if (shinyProxy.fqdn == otherShinyproxy.fqdn) {
130+
logger.warn { "Found multiple ShinyProxy resources with the same URL, fqdn: '${shinyProxy.fqdn}', path: '${shinyProxy.subPath}', realm: '${shinyProxy.realmId}' already defined in realm '${otherShinyproxy.realmId}'" }
131+
return false
132+
}
133+
for (additionalFqdn in shinyProxy.additionalFqdns) {
134+
for (otherAdditionalFqdn in otherShinyproxy.additionalFqdns) {
135+
if (additionalFqdn == otherAdditionalFqdn) {
136+
logger.warn { "Found multiple ShinyProxy resources with the same (additional) URL, additional fqdn: '${additionalFqdn}', path: '${shinyProxy.subPath}', realm: '${shinyProxy.realmId}' already defined in realm '${otherShinyproxy.realmId}'" }
137+
return false
138+
}
139+
}
140+
}
141+
}
142+
// TODO additionalfqdns
143+
144+
return true
145+
}
146+
115147
private fun isInManagedNamespace(shinyProxy: ShinyProxyCustomResource): Boolean {
116148
when (mode) {
117149
Mode.CLUSTERED -> return true

src/main/kotlin/eu/openanalytics/shinyproxyoperator/impl/source/FileSource.kt

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ class FileSource(
8787

8888
var hasInputError = false
8989
val nameToFile = hashMapOf<String, String>()
90+
val urlToFile = hashMapOf<Pair<String, String>, String>()
9091
for (file in files) {
9192
try {
9293
val spec = objectMapper.readValue<JsonNode>(file)
@@ -99,12 +100,17 @@ class FileSource(
99100

100101
// check for duplicate realms in files
101102
if (nameToFile.containsKey(realmId)) {
102-
logger.warn { "Found duplicate realmId: '${shinyProxy.realmId}' in file: '${nameToFile[realmId]}', already defined in '${file.name}'" }
103+
logger.warn { "Found duplicate realmId: '${shinyProxy.realmId}' in file: '${file.name}', already defined in '${nameToFile[realmId]}'" }
103104
hasInputError = true
104105
continue
105106
}
106107
nameToFile[realmId] = file.name
107108

109+
if (!checkDuplicateUrl(urlToFile, shinyProxy, file.name)) {
110+
hasInputError = true
111+
continue
112+
}
113+
108114
val existingShinyProxy = shinyProxies[shinyProxy.realmId]
109115
if (existingShinyProxy == null) {
110116
logger.info { "${logPrefix(shinyProxy.realmId)} [Add]" }
@@ -135,6 +141,24 @@ class FileSource(
135141
}
136142
}
137143

144+
private fun checkDuplicateUrl(urlToFile: HashMap<Pair<String, String>, String>, shinyProxy: ShinyProxy, fileName: String): Boolean {
145+
val baseUrl = Pair(shinyProxy.fqdn, shinyProxy.subPath)
146+
if (urlToFile.containsKey(baseUrl)) {
147+
logger.warn { "Found multiple ShinyProxy resources with the same URL, fqdn: '${shinyProxy.fqdn}', path: '${shinyProxy.subPath}', realm: '${shinyProxy.realmId}' in file: '${fileName}', already defined in '${urlToFile[baseUrl]}'" }
148+
return false
149+
}
150+
urlToFile[baseUrl] = fileName
151+
for (additionalFqdn in shinyProxy.additionalFqdns) {
152+
val url = Pair(additionalFqdn, shinyProxy.subPath)
153+
if (urlToFile.containsKey(url)) {
154+
logger.warn { "Found multiple ShinyProxy resources with the same (additional) URL, additional fqdn: '${additionalFqdn}', path: '${shinyProxy.subPath}', realm: '${shinyProxy.realmId}' in file: '${fileName}', already defined in '${urlToFile[url]}'" }
155+
return false
156+
}
157+
urlToFile[url] =fileName
158+
}
159+
return true
160+
}
161+
138162
private suspend fun checkForDeleted(discoveredShinyProxies: Collection<String>) {
139163
// list of all ShinyProxies currently being managed
140164
val allShinyProxies = (orchestrator.getShinyProxyStatuses().map { it.realmId } + shinyProxies.keys).toSet()

0 commit comments

Comments
 (0)