@@ -36,6 +36,7 @@ import com.intellij.openapi.diagnostic.Logger
3636import com.intellij.openapi.progress.ProgressIndicator
3737import com.intellij.openapi.progress.ProgressManager
3838import com.intellij.openapi.progress.Task
39+ import com.intellij.openapi.rd.util.launchUnderBackgroundProgress
3940import com.intellij.openapi.ui.panel.ComponentPanelBuilder
4041import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeScreenUIManager
4142import com.intellij.ui.AnActionButton
@@ -57,14 +58,14 @@ import com.intellij.util.ui.JBFont
5758import com.intellij.util.ui.JBUI
5859import com.intellij.util.ui.ListTableModel
5960import com.intellij.util.ui.table.IconTableCellRenderer
61+ import com.jetbrains.rd.util.lifetime.LifetimeDefinition
6062import kotlinx.coroutines.CoroutineScope
6163import kotlinx.coroutines.Dispatchers
6264import kotlinx.coroutines.Job
6365import kotlinx.coroutines.cancel
6466import kotlinx.coroutines.delay
6567import kotlinx.coroutines.isActive
6668import kotlinx.coroutines.launch
67- import kotlinx.coroutines.runBlocking
6869import kotlinx.coroutines.withContext
6970import org.zeroturnaround.exec.ProcessExecutor
7071import java.awt.Component
@@ -123,7 +124,7 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) :
123124 enableNextButtonCallback(selectedObject != null && selectedObject?.agentStatus == RUNNING && selectedObject?.agentOS == OS .LINUX )
124125 if (selectedObject?.agentOS != OS .LINUX ) {
125126 notificationBanner.apply {
126- isVisible = true
127+ component. isVisible = true
127128 showInfo(CoderGatewayBundle .message(" gateway.connector.view.coder.workspaces.unsupported.os.info" ))
128129 }
129130 } else {
@@ -391,62 +392,56 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) :
391392 appPropertiesService.setValue(SESSION_TOKEN , token)
392393 val cliManager = CoderCLIManager (localWizardModel.coderURL.toURL(), coderClient.buildVersion)
393394
394-
395395 localWizardModel.apply {
396396 this .token = token
397397 buildVersion = coderClient.buildVersion
398398 localCliPath = cliManager.localCli.toAbsolutePath().toString()
399399 }
400400
401- val authTask = object : Task .Modal (null , CoderGatewayBundle .message(" gateway.connector.view.coder.workspaces.cli.downloader.dialog.title" ), false ) {
402- override fun run (pi : ProgressIndicator ) {
403- pi.apply {
404- isIndeterminate = false
405- text = " Retrieving Workspaces..."
406- fraction = 0.1
407- }
408- runBlocking {
409- loadWorkspaces()
410- }
401+ LifetimeDefinition ().launchUnderBackgroundProgress(CoderGatewayBundle .message(" gateway.connector.view.coder.workspaces.cli.downloader.dialog.title" ), canBeCancelled = false , isIndeterminate = true ) {
402+ this .indicator.apply {
403+ isIndeterminate = false
404+ text = " Retrieving Workspaces..."
405+ fraction = 0.1
406+ }
411407
412- pi.apply {
413- isIndeterminate = false
414- text = " Downloading Coder CLI..."
415- fraction = 0.3
416- }
408+ withContext(Dispatchers .IO ) {
409+ loadWorkspaces()
410+ }
417411
418- cliManager.downloadCLI()
419- if (getOS() != OS .WINDOWS ) {
420- pi.fraction = 0.4
421- val chmodOutput = ProcessExecutor ().command(" chmod" , " +x" , localWizardModel.localCliPath).readOutput(true ).execute().outputUTF8()
422- logger.info(" chmod +x ${cliManager.localCli.toAbsolutePath()} $chmodOutput " )
423- }
424- pi.apply {
425- text = " Configuring Coder CLI..."
426- fraction = 0.5
427- }
412+ this .indicator.apply {
413+ isIndeterminate = false
414+ text = " Downloading Coder CLI..."
415+ fraction = 0.3
416+ }
428417
429- val loginOutput = ProcessExecutor ().command(localWizardModel.localCliPath, " login" , localWizardModel.coderURL, " --token" , localWizardModel.token).readOutput(true ).execute().outputUTF8()
430- logger.info(" coder-cli login output: $loginOutput " )
431- pi.fraction = 0.8
432- val sshConfigOutput = ProcessExecutor ().command(localWizardModel.localCliPath, " config-ssh" , " --yes" , " --use-previous-options" ).readOutput(true ).execute().outputUTF8()
433- logger.info(" Result of `${localWizardModel.localCliPath} config-ssh --yes --use-previous-options`: $sshConfigOutput " )
418+ cliManager.downloadCLI()
419+ if (getOS() != OS .WINDOWS ) {
420+ this .indicator.fraction = 0.4
421+ val chmodOutput = ProcessExecutor ().command(" chmod" , " +x" , localWizardModel.localCliPath).readOutput(true ).execute().outputUTF8()
422+ logger.info(" chmod +x ${cliManager.localCli.toAbsolutePath()} $chmodOutput " )
423+ }
424+ this .indicator.apply {
425+ text = " Configuring Coder CLI..."
426+ fraction = 0.5
427+ }
434428
435- pi. apply {
436- text = " Remove old Coder CLI versions... "
437- fraction = 0.9
438- }
439- cliManager.removeOldCli( )
429+ val loginOutput = ProcessExecutor ().command(localWizardModel.localCliPath, " login " , localWizardModel.coderURL, " --token " , localWizardModel.token).readOutput( true ).execute().outputUTF8()
430+ logger.info( " coder-cli login output: $loginOutput " )
431+ this .indicator. fraction = 0.8
432+ val sshConfigOutput = ProcessExecutor ().command(localWizardModel.localCliPath, " config-ssh " , " --yes " , " --use-previous-options " ).readOutput( true ).execute().outputUTF8()
433+ logger.info( " Result of ` ${localWizardModel.localCliPath} config-ssh --yes --use-previous-options`: $sshConfigOutput " )
440434
441- pi.fraction = 1.0
435+ this .indicator.apply {
436+ text = " Remove old Coder CLI versions..."
437+ fraction = 0.9
442438 }
443- }
439+ cliManager.removeOldCli()
444440
445- cs.launch {
446- ProgressManager .getInstance().run (authTask)
441+ this .indicator.fraction = 1.0
442+ updateWorkspaceActions()
443+ triggerWorkspacePolling()
447444 }
448- updateWorkspaceActions()
449- triggerWorkspacePolling()
450445 }
451446
452447 private fun askToken (): String? {
@@ -483,102 +478,108 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) :
483478 }
484479
485480 private suspend fun loadWorkspaces () {
486- withContext(Dispatchers .IO ) {
481+ val ws = withContext(Dispatchers .IO ) {
487482 val timeBeforeRequestingWorkspaces = System .currentTimeMillis()
488483 try {
489484 val ws = coderClient.workspaces()
485+ val ams = ws.flatMap { it.toAgentModels() }.toSet()
490486 val timeAfterRequestingWorkspaces = System .currentTimeMillis()
491487 logger.info(" Retrieving the workspaces took: ${timeAfterRequestingWorkspaces - timeBeforeRequestingWorkspaces} millis" )
492- ws.resolveAndDisplayAgents()
488+ return @withContext ams
493489 } catch (e: Exception ) {
494490 logger.error(" Could not retrieve workspaces for ${coderClient.me.username} on ${coderClient.coderURL} . Reason: $e " )
491+ emptySet()
492+ }
493+ }
494+ withContext(Dispatchers .Main ) {
495+ val selectedWorkspace = tableOfWorkspaces.selectedObject?.name
496+ listTableModelOfWorkspaces.items = ws.toList()
497+ if (selectedWorkspace != null ) {
498+ tableOfWorkspaces.selectItem(selectedWorkspace)
495499 }
496500 }
497501 }
498502
499- private fun List<Workspace>.resolveAndDisplayAgents () {
500- this .forEach { workspace ->
501- cs.launch(Dispatchers .IO ) {
502- val timeBeforeRequestingAgents = System .currentTimeMillis()
503- workspace.agentModels().forEach { am ->
503+ private fun Workspace.toAgentModels (): Set <WorkspaceAgentModel > {
504+ return when (this .latestBuild.resources.size) {
505+ 0 -> {
506+ val wm = WorkspaceAgentModel (
507+ this .id,
508+ this .name,
509+ this .name,
510+ this .templateID,
511+ this .templateName,
512+ this .templateIcon,
513+ null ,
514+ WorkspaceVersionStatus .from(this ),
515+ WorkspaceAgentStatus .from(this ),
516+ this .latestBuild.transition,
517+ null ,
518+ null ,
519+ null
520+ )
521+ cs.launch(Dispatchers .IO ) {
522+ wm.templateIcon = iconDownloader.load(wm.templateIconPath, wm.templateName)
504523 withContext(Dispatchers .Main ) {
505- val selectedWorkspace = tableOfWorkspaces.selectedObject?.name
506- if (listTableModelOfWorkspaces.indexOf(am) >= 0 ) {
507- val index = listTableModelOfWorkspaces.indexOf(am)
508- listTableModelOfWorkspaces.setItem(index, am)
509- } else {
510- listTableModelOfWorkspaces.addRow(am)
511- }
512- if (selectedWorkspace != null ) {
513- tableOfWorkspaces.selectItem(selectedWorkspace)
514- }
524+ tableOfWorkspaces.updateUI()
515525 }
516526 }
517- val timeAfterRequestingAgents = System .currentTimeMillis()
518- logger.info(" Retrieving the agents for ${workspace.name} took: ${timeAfterRequestingAgents - timeBeforeRequestingAgents} millis" )
527+ setOf (wm)
519528 }
520- }
521- }
522-
523- private fun Workspace.agentModels (): List <WorkspaceAgentModel > {
524- return try {
525- val agents = coderClient.workspaceAgentsByTemplate(this )
526- when (agents.size) {
527- 0 -> {
528- listOf (
529- WorkspaceAgentModel (
530- this .id,
531- this .name,
532- this .name,
533- this .templateID,
534- this .templateName,
535- iconDownloader.load(this @agentModels.templateIcon, this .name),
536- WorkspaceVersionStatus .from(this ),
537- WorkspaceAgentStatus .from(this ),
538- this .latestBuild.transition,
539- null ,
540- null ,
541- null
542- )
543- )
544- }
545529
546- else -> agents.map { agent ->
530+ else -> {
531+ val wam = this .latestBuild.resources.filter { it.agents != null }.flatMap { it.agents!! }.map { agent ->
547532 val workspaceWithAgentName = " ${this .name} .${agent.name} "
548- WorkspaceAgentModel (
533+ val wm = WorkspaceAgentModel (
549534 this .id,
550535 this .name,
551536 workspaceWithAgentName,
552537 this .templateID,
553538 this .templateName,
554- iconDownloader.load(this @agentModels.templateIcon, workspaceWithAgentName),
539+ this .templateIcon,
540+ null ,
555541 WorkspaceVersionStatus .from(this ),
556542 WorkspaceAgentStatus .from(this ),
557543 this .latestBuild.transition,
558544 OS .from(agent.operatingSystem),
559545 Arch .from(agent.architecture),
560546 agent.directory
561547 )
562- }.toList()
548+ cs.launch(Dispatchers .IO ) {
549+ wm.templateIcon = iconDownloader.load(wm.templateIconPath, wm.templateName)
550+ withContext(Dispatchers .Main ) {
551+ tableOfWorkspaces.updateUI()
552+ }
553+ }
554+ wm
555+ }.toSet()
556+
557+ if (wam.isNullOrEmpty()) {
558+ val wm = WorkspaceAgentModel (
559+ this .id,
560+ this .name,
561+ this .name,
562+ this .templateID,
563+ this .templateName,
564+ this .templateIcon,
565+ null ,
566+ WorkspaceVersionStatus .from(this ),
567+ WorkspaceAgentStatus .from(this ),
568+ this .latestBuild.transition,
569+ null ,
570+ null ,
571+ null
572+ )
573+ cs.launch(Dispatchers .IO ) {
574+ wm.templateIcon = iconDownloader.load(wm.templateIconPath, wm.templateName)
575+ withContext(Dispatchers .Main ) {
576+ tableOfWorkspaces.updateUI()
577+ }
578+ }
579+ return setOf (wm)
580+ }
581+ return wam
563582 }
564- } catch (e: Exception ) {
565- logger.warn(" Agent(s) for ${this .name} could not be retrieved. Reason: $e " )
566- listOf (
567- WorkspaceAgentModel (
568- this .id,
569- this .name,
570- this .name,
571- this .templateID,
572- this .templateName,
573- iconDownloader.load(this @agentModels.templateIcon, this .name),
574- WorkspaceVersionStatus .from(this ),
575- WorkspaceAgentStatus .from(this ),
576- this .latestBuild.transition,
577- null ,
578- null ,
579- null
580- )
581- )
582583 }
583584 }
584585
@@ -627,7 +628,7 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) :
627628
628629 private class WorkspaceIconColumnInfo (columnName : String ) : ColumnInfo<WorkspaceAgentModel, String>(columnName) {
629630 override fun valueOf (workspace : WorkspaceAgentModel ? ): String? {
630- return workspace?.agentOS?.name
631+ return workspace?.templateName
631632 }
632633
633634 override fun getRenderer (item : WorkspaceAgentModel ? ): TableCellRenderer {
0 commit comments