@@ -15,6 +15,7 @@ import com.intellij.openapi.application.invokeLater
1515import com.intellij.openapi.components.service
1616import com.intellij.openapi.progress.ProgressManager
1717import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeScreenUIManager
18+ import com.intellij.ui.components.JBCheckBox
1819import com.intellij.ui.components.JBTextField
1920import com.intellij.ui.dsl.builder.Align
2021import com.intellij.ui.dsl.builder.panel
@@ -23,18 +24,16 @@ import com.intellij.util.ui.JBUI
2324import com.redhat.devtools.gateway.DevSpacesBundle
2425import com.redhat.devtools.gateway.DevSpacesContext
2526import com.redhat.devtools.gateway.kubeconfig.FileWatcher
26- import com.redhat.devtools.gateway.kubeconfig.KubeConfigUtils
2727import com.redhat.devtools.gateway.kubeconfig.KubeConfigMonitor
28+ import com.redhat.devtools.gateway.kubeconfig.KubeConfigUtils
29+ import com.redhat.devtools.gateway.kubeconfig.KubeConfigWriter
2830import com.redhat.devtools.gateway.openshift.Cluster
2931import com.redhat.devtools.gateway.openshift.OpenShiftClientFactory
3032import com.redhat.devtools.gateway.openshift.Projects
3133import com.redhat.devtools.gateway.settings.DevSpacesSettings
3234import com.redhat.devtools.gateway.util.message
33- import com.redhat.devtools.gateway.view.ui.Dialogs
34- import com.redhat.devtools.gateway.view.ui.FilteringComboBox
35- import com.redhat.devtools.gateway.view.ui.PasteClipboardMenu
36- import com.redhat.devtools.gateway.view.ui.getAllElements
37- import com.redhat.devtools.gateway.view.ui.requestInitialFocus
35+ import com.redhat.devtools.gateway.view.ui.*
36+ import io.kubernetes.client.util.KubeConfig
3837import kotlinx.coroutines.*
3938import java.awt.event.ItemEvent
4039import javax.swing.JTextField
@@ -51,12 +50,18 @@ class DevSpacesServerStepView(
5150
5251 private lateinit var kubeconfigMonitor: KubeConfigMonitor
5352
53+ private var kubeconfigServerUrl: String? = null
54+ private var kubeconfigToken: String? = null
55+ private var hasUnsavedChanges: Boolean = false
56+
57+ private val updateKubeconfigCheckbox = JBCheckBox (" Update kubeconfig" )
58+ private lateinit var saveKubeconfigCheckbox: com.intellij.ui.dsl.builder.Row
59+
5460 private var tfToken = JBTextField ()
5561 .apply {
5662 document.addDocumentListener(onTokenChanged())
5763 PasteClipboardMenu .addTo(this )
5864 }
59-
6065 private var tfServer =
6166 FilteringComboBox .create(
6267 { it?.toString() ? : " " },
@@ -78,6 +83,13 @@ class DevSpacesServerStepView(
7883 row(DevSpacesBundle .message(" connector.wizard_step.openshift_connection.label.token" )) {
7984 cell(tfToken).align(Align .FILL )
8085 }
86+ saveKubeconfigCheckbox = row(" " ) {
87+ cell(updateKubeconfigCheckbox).applyToComponent {
88+ isOpaque = false
89+ background = WelcomeScreenUIManager .getMainAssociatedComponentBackground()
90+ }
91+ visible(false )
92+ }
8193 }.apply {
8294 background = WelcomeScreenUIManager .getMainAssociatedComponentBackground()
8395 border = JBUI .Borders .empty(8 )
@@ -101,30 +113,60 @@ class DevSpacesServerStepView(
101113 }
102114 }
103115 }
116+ updateSaveKubeconfigCheckbox((tfServer.selectedItem as Cluster ? ), tfToken.text)
104117 }
105118
106119 private fun onTokenChanged (): DocumentListener = object : DocumentListener {
107120 override fun insertUpdate (event : DocumentEvent ) {
108121 enableNextButton?.invoke()
122+ updateSaveKubeconfigCheckbox((tfServer.selectedItem as Cluster ? ), tfToken.text)
109123 }
110124
111125 override fun removeUpdate (e : DocumentEvent ) {
112126 enableNextButton?.invoke()
127+ updateSaveKubeconfigCheckbox((tfServer.selectedItem as Cluster ? ), tfToken.text)
113128 }
114129
115130 override fun changedUpdate (e : DocumentEvent ? ) {
116131 enableNextButton?.invoke()
132+ updateSaveKubeconfigCheckbox((tfServer.selectedItem as Cluster ? ), tfToken.text)
117133 }
118134 }
119135
136+ private fun updateSaveKubeconfigCheckbox (cluster : Cluster ? , token : String? ) {
137+ if (cluster == null
138+ || token.isNullOrBlank()) {
139+ return
140+ }
141+ this .hasUnsavedChanges =
142+ (kubeconfigServerUrl != null && kubeconfigServerUrl != cluster.url)
143+ || (! kubeconfigToken.isNullOrBlank() && kubeconfigToken != token)
144+
145+ saveKubeconfigCheckbox.visible(hasUnsavedChanges)
146+ }
147+
120148 private fun onClustersChanged (): suspend (List <Cluster >) -> Unit = { updatedClusters ->
121- invokeLater {
122- val selectedName = (tfServer.selectedItem as ? Cluster )?.name
123- setClusters(updatedClusters)
124- setSelectedCluster(selectedName, updatedClusters)
149+ if (updatedClusters.isNotEmpty()) {
150+ invokeLater {
151+ val kubeConfigCurrentCluster = KubeConfigUtils .getCurrentContextClusterName()
152+ val previouslySelected = tfServer.selectedItem as ? Cluster ?
153+ setClusters(updatedClusters)
154+ setSelectedCluster(
155+ (previouslySelected)?.name ? : kubeConfigCurrentCluster,
156+ updatedClusters
157+ )
158+ val newSelected = tfServer.selectedItem as ? Cluster
159+ setKubeconfigValues(newSelected?.url, tfToken.text)
160+ updateSaveKubeconfigCheckbox(newSelected, tfToken.text)
161+ }
125162 }
126163 }
127164
165+ private fun setKubeconfigValues (url : String? , token : String? ) {
166+ this .kubeconfigServerUrl = url
167+ this .kubeconfigToken = token
168+ }
169+
128170 override fun onPrevious (): Boolean {
129171 stopKubeconfigMonitor()
130172 return true
@@ -138,6 +180,27 @@ class DevSpacesServerStepView(
138180 var success = false
139181 stopKubeconfigMonitor()
140182
183+ if (updateKubeconfigCheckbox.isVisible && updateKubeconfigCheckbox.isSelected) {
184+ val mergedKubeConfigContent = KubeConfigUtils .getAllConfigsMerged()
185+ val currentKubeConfig = mergedKubeConfigContent?.reader()?.let { KubeConfig .loadKubeConfig(it) }
186+ val currentUser = if (currentKubeConfig != null ) KubeConfigUtils .getCurrentUser(currentKubeConfig) else " "
187+ val kubeConfigFilePath = KubeConfigWriter .findKubeConfigFileForUser(currentUser, System .getenv(" KUBECONFIG" )) ? : " "
188+
189+ if (kubeConfigFilePath.isNotBlank()) {
190+ kubeconfigScope.launch {
191+ try {
192+ KubeConfigWriter .applyChangesAndSave(kubeConfigFilePath, server, token)
193+ Dialogs .info(" Kubeconfig updated successfully." , " Kubeconfig Update" )
194+ } catch (e: Exception ) {
195+ Dialogs .error(" Failed to update kubeconfig: ${e.message} " , " Kubeconfig Update Failed" )
196+ e.printStackTrace()
197+ }
198+ }
199+ } else {
200+ Dialogs .error(" Could not determine kubeconfig file path to update." , " Kubeconfig Update Failed" )
201+ }
202+ }
203+
141204 ProgressManager .getInstance().runProcessWithProgressSynchronously(
142205 {
143206 try {
0 commit comments