Skip to content

Show all workspaces - working and non working #61

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Aug 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
# coder-gateway Changelog

## [Unreleased]
### Added
- support for displaying working and non-working workspaces
- better support for Light and Dark themes in the "Status" column

### Fixed

- left panel is no longer visible when a new connection is triggered from Coder's "Recent Workspaces" panel.
Expand Down Expand Up @@ -31,8 +35,6 @@
### Added
- support for Gateway 2022.2



### Changed
- Java 17 is now required to run the plugin
- adapted the code to the new SSH API provided by Gateway
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
pluginGroup=com.coder.gateway
pluginName=coder-gateway
# SemVer format -> https://semver.org
pluginVersion=2.0.1
pluginVersion=2.0.2
# See https://plugins.jetbrains.com/docs/intellij/build-number-ranges.html
# for insight into build numbers and IntelliJ Platform versions.
pluginSinceBuild=222.3739.24
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ import java.time.format.DateTimeFormatter

class CoderGatewayConnectionProvider : GatewayConnectionProvider {
private val recentConnectionsService = service<CoderRecentWorkspaceConnectionsService>()
private val sshConfigService = service<SshConfigManager>()

private val connections = mutableSetOf<CoderConnectionMetadata>()
private val localTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MMM-dd HH:mm")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ import com.coder.gateway.sdk.v2.models.WorkspaceBuildTransition
data class WorkspaceAgentModel(
val name: String,
val templateName: String,

val jobStatus: ProvisionerJobStatus,
val buildTransition: WorkspaceBuildTransition,

val agentStatus: WorkspaceAgentStatus,
val agentOS: OS?,
val agentArch: Arch?,
val homeDirectory: String?
Expand Down
32 changes: 32 additions & 0 deletions src/main/kotlin/com/coder/gateway/models/WorkspaceAgentStatus.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.coder.gateway.models

import com.coder.gateway.sdk.v2.models.ProvisionerJobStatus
import com.coder.gateway.sdk.v2.models.Workspace
import com.coder.gateway.sdk.v2.models.WorkspaceBuildTransition

enum class WorkspaceAgentStatus(val label: String) {
QUEUED("◍ Queued"), STARTING("⦿ Starting"), STOPPING("◍ Stopping"), DELETING("⦸ Deleting"),
RUNNING("⦿ Running"), STOPPED("◍ Stopped"), DELETED("⦸ Deleted"),
CANCELING("◍ Canceling action"), CANCELED("◍ Canceled action"), FAILED("ⓧ Failed");

companion object {
fun from(workspace: Workspace) = when (workspace.latestBuild.job.status) {
ProvisionerJobStatus.PENDING -> QUEUED
ProvisionerJobStatus.RUNNING -> when (workspace.latestBuild.workspaceTransition) {
WorkspaceBuildTransition.START -> STARTING
WorkspaceBuildTransition.STOP -> STOPPING
WorkspaceBuildTransition.DELETE -> DELETING
}

ProvisionerJobStatus.SUCCEEDED -> when (workspace.latestBuild.workspaceTransition) {
WorkspaceBuildTransition.START -> RUNNING
WorkspaceBuildTransition.STOP -> STOPPED
WorkspaceBuildTransition.DELETE -> DELETED
}

ProvisionerJobStatus.CANCELING -> CANCELING
ProvisionerJobStatus.CANCELED -> CANCELED
ProvisionerJobStatus.FAILED -> FAILED
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import com.coder.gateway.CoderGatewayBundle
import com.coder.gateway.icons.CoderIcons
import com.coder.gateway.models.CoderWorkspacesWizardModel
import com.coder.gateway.models.WorkspaceAgentModel
import com.coder.gateway.models.WorkspaceAgentStatus
import com.coder.gateway.models.WorkspaceAgentStatus.DELETING
import com.coder.gateway.models.WorkspaceAgentStatus.RUNNING
import com.coder.gateway.models.WorkspaceAgentStatus.STARTING
import com.coder.gateway.models.WorkspaceAgentStatus.STOPPING
import com.coder.gateway.sdk.Arch
import com.coder.gateway.sdk.CoderCLIManager
import com.coder.gateway.sdk.CoderRestClientService
Expand All @@ -28,6 +33,7 @@ import com.intellij.openapi.progress.Task
import com.intellij.openapi.ui.panel.ComponentPanelBuilder
import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeScreenUIManager
import com.intellij.ui.AppIcon
import com.intellij.ui.JBColor
import com.intellij.ui.components.JBTextField
import com.intellij.ui.components.dialog
import com.intellij.ui.dsl.builder.BottomGap
Expand Down Expand Up @@ -78,7 +84,7 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) :

setSelectionMode(ListSelectionModel.SINGLE_SELECTION)
selectionModel.addListSelectionListener {
enableNextButtonCallback(selectedObject != null)
enableNextButtonCallback(selectedObject != null && selectedObject?.agentStatus == RUNNING)
}
}

Expand Down Expand Up @@ -221,26 +227,55 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) :
}

private fun List<Workspace>.collectAgents(): List<WorkspaceAgentModel> {
return this.flatMap { workspace ->
try {
val agents = coderClient.workspaceAgents(workspace)
val shouldContainAgentName = agents.size > 1
return@flatMap agents.map { agent ->
val workspaceName = if (shouldContainAgentName) "${workspace.name}.${agent.name}" else workspace.name
return this.flatMap { it.agentModels() }.toList()
}

private fun Workspace.agentModels(): List<WorkspaceAgentModel> {
return try {
val agents = coderClient.workspaceAgents(this)
when (agents.size) {
0 -> {
listOf(
WorkspaceAgentModel(
this.name,
this.templateName,
WorkspaceAgentStatus.from(this),
null,
null,
null
)
)
}

1 -> {
listOf(
WorkspaceAgentModel(
this.name,
this.templateName,
WorkspaceAgentStatus.from(this),
OS.from(agents[0].operatingSystem),
Arch.from(agents[0].architecture),
agents[0].directory
)
)
}

else -> agents.map { agent ->
val workspaceName = "${this.name}.${agent.name}"
WorkspaceAgentModel(
workspaceName,
workspace.templateName,
workspace.latestBuild.job.status,
workspace.latestBuild.workspaceTransition,
this.templateName,
WorkspaceAgentStatus.from(this),
OS.from(agent.operatingSystem),
Arch.from(agent.architecture),
agent.directory
)
}
} catch (e: Exception) {
logger.error("Skipping workspace ${workspace.name} because we could not retrieve the agent(s). Reason: $e")
emptyList()
.toList()
}
} catch (e: Exception) {
logger.error("Skipping workspace ${this.name} because we could not retrieve the agent(s). Reason: $e")
emptyList()
}
}

Expand Down Expand Up @@ -322,7 +357,7 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) :

private class WorkspaceStatusColumnInfo(columnName: String) : ColumnInfo<WorkspaceAgentModel, String>(columnName) {
override fun valueOf(workspace: WorkspaceAgentModel?): String? {
return workspace?.statusLabel()
return workspace?.agentStatus?.label
}

override fun getRenderer(item: WorkspaceAgentModel?): TableCellRenderer {
Expand All @@ -339,32 +374,10 @@ class CoderWorkspacesStepView(val enableNextButtonCallback: (Boolean) -> Unit) :
}
}

private fun WorkspaceAgentModel.statusLabel() = when (this.jobStatus) {
ProvisionerJobStatus.PENDING -> "◍ Queued"
ProvisionerJobStatus.RUNNING -> when (this.buildTransition) {
WorkspaceBuildTransition.START -> "⦿ Starting"
WorkspaceBuildTransition.STOP -> "◍ Stopping"
WorkspaceBuildTransition.DELETE -> "⦸ Deleting"
}

ProvisionerJobStatus.SUCCEEDED -> when (this.buildTransition) {
WorkspaceBuildTransition.START -> "⦿ Running"
WorkspaceBuildTransition.STOP -> "◍ Stopped"
WorkspaceBuildTransition.DELETE -> "⦸ Deleted"
}

ProvisionerJobStatus.CANCELING -> "◍ Canceling action"
ProvisionerJobStatus.CANCELED -> "◍ Canceled action"
ProvisionerJobStatus.FAILED -> "ⓧ Failed"
}

private fun WorkspaceAgentModel.statusColor() = when (this.jobStatus) {
ProvisionerJobStatus.SUCCEEDED -> if (this.buildTransition == WorkspaceBuildTransition.START) Color.GREEN else Color.RED
ProvisionerJobStatus.RUNNING -> when (this.buildTransition) {
WorkspaceBuildTransition.START, WorkspaceBuildTransition.STOP, WorkspaceBuildTransition.DELETE -> Color.GRAY
}

else -> Color.RED
private fun WorkspaceAgentModel.statusColor() = when (this.agentStatus) {
RUNNING -> JBColor.GREEN
STARTING, STOPPING, DELETING -> if (JBColor.isBright()) JBColor.LIGHT_GRAY else JBColor.DARK_GRAY
else -> JBColor.RED
}
}

Expand Down