Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Support for removing workspaces#10

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
fioan89 merged 7 commits intomainfromsupport-for-removing-workspaces
Feb 28, 2025
Merged
Show file tree
Hide file tree
Changes fromall 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
50 changes: 48 additions & 2 deletionssrc/main/kotlin/com/coder/toolbox/CoderRemoteEnvironment.kt
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,6 +3,7 @@ package com.coder.toolbox
import com.coder.toolbox.browser.BrowserUtil
import com.coder.toolbox.models.WorkspaceAndAgentStatus
import com.coder.toolbox.sdk.CoderRestClient
import com.coder.toolbox.sdk.ex.APIResponseException
import com.coder.toolbox.sdk.v2.models.Workspace
import com.coder.toolbox.sdk.v2.models.WorkspaceAgent
import com.coder.toolbox.util.withPath
Expand All@@ -13,9 +14,15 @@ import com.jetbrains.toolbox.api.remoteDev.AbstractRemoteProviderEnvironment
import com.jetbrains.toolbox.api.remoteDev.EnvironmentVisibilityState
import com.jetbrains.toolbox.api.remoteDev.environments.EnvironmentContentsView
import com.jetbrains.toolbox.api.remoteDev.states.EnvironmentStateConsumer
import com.jetbrains.toolbox.api.remoteDev.ui.EnvironmentUiPageManager
import com.jetbrains.toolbox.api.ui.ToolboxUi
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withTimeout
import kotlin.time.Duration.Companion.minutes
import kotlin.time.Duration.Companion.seconds

/**
* Represents an agent and workspace combination.
Expand DownExpand Up@@ -71,7 +78,7 @@ class CoderRemoteEnvironment(
},
)
actionsList.add(
Action("Stop", enabled = { status.ready() || status.pending() }) {
Action("Stop", enabled = { status.canStop() }) {
val build = client.stopWorkspace(workspace)
workspace = workspace.copy(latestBuild = build)
update(workspace, agent)
Expand DownExpand Up@@ -128,7 +135,46 @@ class CoderRemoteEnvironment(
}

override fun onDelete() {
throw NotImplementedError()
cs.launch {
// TODO info and cancel pop-ups only appear on the main page where all environments are listed.
// However, #showSnackbar works on other pages. Until JetBrains fixes this issue we are going to use the snackbar
val shouldDelete = if (status.canStop()) {
ui.showOkCancelPopup(
"Delete running workspace?",
"Workspace will be closed and all the information in this workspace will be lost, including all files, unsaved changes and historical.",
"Delete",
"Cancel"
)
} else {
ui.showOkCancelPopup(
"Delete workspace?",
"All the information in this workspace will be lost, including all files, unsaved changes and historical.",
"Delete",
"Cancel"
)
}
if (shouldDelete) {
try {
client.removeWorkspace(workspace)
cs.launch {
withTimeout(5.minutes) {
var workspaceStillExists = true
while (cs.isActive && workspaceStillExists) {
if (status == WorkspaceAndAgentStatus.DELETING || status == WorkspaceAndAgentStatus.DELETED) {
workspaceStillExists = false
serviceLocator.getService(EnvironmentUiPageManager::class.java)
.showPluginEnvironmentsPage()
} else {
delay(1.seconds)
}
}
}
}
} catch (e: APIResponseException) {
ui.showErrorInfoPopup(e)
}
}
}
}

/**
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,6 +9,7 @@ import com.jetbrains.toolbox.api.core.ServiceLocator
import com.jetbrains.toolbox.api.core.ui.color.StateColor
import com.jetbrains.toolbox.api.remoteDev.states.CustomRemoteEnvironmentState
import com.jetbrains.toolbox.api.remoteDev.states.EnvironmentStateColorPalette
import com.jetbrains.toolbox.api.remoteDev.states.EnvironmentStateIcons
import com.jetbrains.toolbox.api.remoteDev.states.StandardRemoteEnvironmentState

/**
Expand DownExpand Up@@ -59,26 +60,34 @@ enum class WorkspaceAndAgentStatus(val label: String, val description: String) {
* "disconnected" regardless of the label we give that status.
*/
fun toRemoteEnvironmentState(serviceLocator: ServiceLocator): CustomRemoteEnvironmentState {
val stateColor = getStateColor(serviceLocator)
return CustomRemoteEnvironmentState(
label,
stateColor,
getStateColor(serviceLocator),
ready(), // reachable
// TODO@JB: How does this work? Would like a spinner for pending states.
null, // iconId
getStateIcon()
)
}

private fun getStateColor(serviceLocator: ServiceLocator): StateColor {
val colorPalette = serviceLocator.getService(EnvironmentStateColorPalette::class.java)


return if (ready()) colorPalette.getColor(StandardRemoteEnvironmentState.Active)
else if (canStart()) colorPalette.getColor(StandardRemoteEnvironmentState.Failed)
else if (pending()) colorPalette.getColor(StandardRemoteEnvironmentState.Activating)
else if (this == DELETING) colorPalette.getColor(StandardRemoteEnvironmentState.Deleting)
else if (this == DELETED) colorPalette.getColor(StandardRemoteEnvironmentState.Deleted)
else colorPalette.getColor(StandardRemoteEnvironmentState.Unreachable)
}

private fun getStateIcon(): EnvironmentStateIcons {
return if (ready()) EnvironmentStateIcons.Active
else if (canStart()) EnvironmentStateIcons.Hibernated
else if (pending()) EnvironmentStateIcons.Connecting
else if (this == DELETING || this == DELETED) EnvironmentStateIcons.Offline
else EnvironmentStateIcons.NoIcon
}

/**
* Return true if the agent is in a connectable state.
*/
Expand DownExpand Up@@ -107,6 +116,11 @@ enum class WorkspaceAndAgentStatus(val label: String, val description: String) {
fun canStart(): Boolean = listOf(STOPPED, FAILED, CANCELED)
.contains(this)

/**
* Return true if the workspace can be stopped.
*/
fun canStop(): Boolean = ready() || pending()

// We want to check that the workspace is `running`, the agent is
// `connected`, and the agent lifecycle state is `ready` to ensure the best
// possible scenario for attempting a connection.
Expand Down
14 changes: 12 additions & 2 deletionssrc/main/kotlin/com/coder/toolbox/sdk/CoderRestClient.kt
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,7 @@ import retrofit2.converter.moshi.MoshiConverterFactory
import java.net.HttpURLConnection
import java.net.ProxySelector
import java.net.URL
import java.util.*
import java.util.UUID
import javax.net.ssl.X509TrustManager

/**
Expand DownExpand Up@@ -229,7 +229,6 @@ open class CoderRestClient(
}

/**
* @throws [APIResponseException].
*/
fun stopWorkspace(workspace: Workspace): WorkspaceBuild {
val buildRequest = CreateWorkspaceBuildRequest(null, WorkspaceTransition.STOP)
Expand All@@ -240,6 +239,17 @@ open class CoderRestClient(
return buildResponse.body()!!
}

/**
* @throws [APIResponseException] if issues are encountered during deletion
*/
fun removeWorkspace(workspace: Workspace) {
val buildRequest = CreateWorkspaceBuildRequest(null, WorkspaceTransition.DELETE, false)
val buildResponse = retroRestClient.createWorkspaceBuild(workspace.id, buildRequest).execute()
if (buildResponse.code() != HttpURLConnection.HTTP_CREATED) {
throw APIResponseException("delete workspace ${workspace.name}", url, buildResponse)
}
}

/**
* Start the workspace with the latest template version. Best practice is
* to STOP a workspace before doing an update if it is started.
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -8,8 +8,9 @@ import java.util.UUID
data class CreateWorkspaceBuildRequest(
// Use to update the workspace to a new template version.
@Json(name = "template_version_id") val templateVersionID: UUID?,
// Use to startandstop the workspace.
// Use to start, stopanddelete the workspace.
@Json(name = "transition") val transition: WorkspaceTransition,
@Json(name = "orphan") var orphan: Boolean? = null
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
Expand All@@ -19,12 +20,13 @@ data class CreateWorkspaceBuildRequest(

if (templateVersionID != other.templateVersionID) return false
if (transition != other.transition) return false

if (orphan != other.orphan) return false
return true
}

override fun hashCode(): Int {
var result = templateVersionID?.hashCode() ?: 0
var result = orphan?.hashCode() ?: 0
result = 31 * result + (templateVersionID?.hashCode() ?: 0)
result = 31 * result + transition.hashCode()
return result
}
Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp