Skip to content

Commit b0ffc7d

Browse files
committed
feat: allow to save cluster + token to kubeconf (#23649)
Signed-off-by: Andre Dietisheim <[email protected]> Assisted by: gemini-cli Assisted by: cursor Assisted by: qwen-code
1 parent 8d10739 commit b0ffc7d

25 files changed

+3164
-1001
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright (c) 2025 Red Hat, Inc.
3+
* This program and the accompanying materials are made
4+
* available under the terms of the Eclipse Public License 2.0
5+
* which is available at https://www.eclipse.org/legal/epl-2.0/
6+
*
7+
* SPDX-License-Identifier: EPL-2.0
8+
*
9+
* Contributors:
10+
* Red Hat, Inc. - initial API and implementation
11+
*/
12+
package com.redhat.devtools.gateway.kubeconfig
13+
14+
import io.kubernetes.client.persister.ConfigPersister
15+
import org.yaml.snakeyaml.DumperOptions
16+
import org.yaml.snakeyaml.Yaml
17+
import java.io.File
18+
19+
class BlockStyleFilePersister(private val file: File) : ConfigPersister {
20+
21+
@Throws(java.io.IOException::class)
22+
override fun save(
23+
contexts: ArrayList<Any?>,
24+
clusters: ArrayList<Any?>,
25+
users: ArrayList<Any?>,
26+
preferences: Any?,
27+
currentContext: String?
28+
) {
29+
val config = mapOf(
30+
"apiVersion" to "v1",
31+
"kind" to "Config",
32+
"current-context" to currentContext,
33+
"preferences" to preferences,
34+
35+
"clusters" to clusters,
36+
"contexts" to contexts,
37+
"users" to users,
38+
)
39+
40+
synchronized(file) {
41+
java.io.FileWriter(file).use { writer ->
42+
val options = DumperOptions().apply {
43+
defaultFlowStyle = DumperOptions.FlowStyle.BLOCK
44+
isPrettyFlow = true
45+
}
46+
val yaml = Yaml(options)
47+
yaml.dump(config, writer)
48+
writer.flush()
49+
}
50+
}
51+
}
52+
}

src/main/kotlin/com/redhat/devtools/gateway/kubeconfig/FileWatcher.kt

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import kotlin.io.path.exists
1818
import kotlin.io.path.isRegularFile
1919

2020
class FileWatcher(
21-
private val scope: CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Default),
21+
private val scope: CoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.IO),
2222
private val dispatcher: CoroutineDispatcher = Dispatchers.IO,
2323
private val watchService: WatchService = FileSystems.getDefault().newWatchService()
2424
) {
@@ -29,23 +29,31 @@ class FileWatcher(
2929

3030
fun start() {
3131
this.watchJob = scope.launch(dispatcher) {
32-
while (isActive) {
33-
val key = watchService.poll(100, java.util.concurrent.TimeUnit.MILLISECONDS)
34-
if (key == null) {
35-
delay(100)
36-
continue
32+
try {
33+
while (isActive) {
34+
val key = watchService.poll(100, java.util.concurrent.TimeUnit.MILLISECONDS)
35+
if (key == null) {
36+
delay(100)
37+
continue
38+
}
39+
val dir = registeredKeys[key] ?: continue
40+
pollEvents(key, dir)
41+
key.reset()
3742
}
38-
val dir = registeredKeys[key] ?: continue
39-
pollEvents(key, dir)
40-
key.reset()
43+
} catch (e: ClosedWatchServiceException) {
44+
// Watch service was closed, exit gracefully
4145
}
4246
}
4347
}
4448

4549
fun stop() {
4650
watchJob?.cancel()
4751
watchJob = null
48-
watchService.close()
52+
try {
53+
watchService.close()
54+
} catch (e: Exception) {
55+
// Ignore exceptions when closing
56+
}
4957
}
5058

5159
fun addFile(path: Path): FileWatcher {

0 commit comments

Comments
 (0)