-
Notifications
You must be signed in to change notification settings - Fork 16
Check the agent's status #232
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
Changes from 7 commits
ed37ab0
3b06d9f
9b787c7
9ab8769
5f31f55
176d868
d5abf2b
596934c
a70a32b
55e4a61
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,96 @@ | ||||||||||||
package com.coder.gateway.models | ||||||||||||
|
||||||||||||
import com.coder.gateway.sdk.v2.models.Workspace | ||||||||||||
import com.coder.gateway.sdk.v2.models.WorkspaceAgent | ||||||||||||
import com.coder.gateway.sdk.v2.models.WorkspaceAgentLifecycleState | ||||||||||||
import com.coder.gateway.sdk.v2.models.WorkspaceAgentStatus | ||||||||||||
import com.coder.gateway.sdk.v2.models.WorkspaceStatus | ||||||||||||
import com.intellij.ui.JBColor | ||||||||||||
|
||||||||||||
/** | ||||||||||||
* WorkspaceAndAgentStatus represents the combined status of a single agent and | ||||||||||||
* its workspace (or just the workspace if there are no agents). | ||||||||||||
*/ | ||||||||||||
enum class WorkspaceAndAgentStatus(val label: String, val description: String) { | ||||||||||||
// Workspace states. | ||||||||||||
QUEUED("◍ Queued", "The workspace is queueing to start."), | ||||||||||||
STARTING("⦿ Starting", "The workspace is starting."), | ||||||||||||
FAILED("ⓧ Failed", "The workspace has failed to start."), | ||||||||||||
DELETING("⦸ Deleting", "The workspace is being deleted."), | ||||||||||||
DELETED("⦸ Deleted", "The workspace has been deleted."), | ||||||||||||
STOPPING("◍ Stopping", "The workspace is stopping."), | ||||||||||||
STOPPED("◍ Stopped", "The workspace has stopped."), | ||||||||||||
CANCELING("◍ Canceling action", "The workspace is being canceled."), | ||||||||||||
CANCELED("◍ Canceled action", "The workspace has been canceled."), | ||||||||||||
RUNNING("⦿ Running", "The workspace is running, waiting for agents."), | ||||||||||||
|
||||||||||||
// Agent states. | ||||||||||||
CONNECTING("⦿ Connecting", "The agent is connecting."), | ||||||||||||
DISCONNECTED("⦸ Disconnected", "The agent has disconnected."), | ||||||||||||
TIMEOUT("ⓧ Timeout", "The agent has timed out."), | ||||||||||||
AGENT_STARTING("⦿ Starting", "The agent is running the startup script."), | ||||||||||||
AGENT_STARTING_READY("⦿ Starting", "The agent is running the startup script but is ready to accept connections."), | ||||||||||||
CREATED("⦿ Created", "The agent has been created."), | ||||||||||||
START_ERROR("◍ Started with error", "The agent is ready but the startup script errored."), | ||||||||||||
START_TIMEOUT("◍ Started with timeout", "The agent is ready but the startup script timed out"), | ||||||||||||
code-asher marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
SHUTTING_DOWN("◍ Shutting down", "The agent is shutting down."), | ||||||||||||
SHUTDOWN_ERROR("⦸ Shutdown with error", "The agent shut down but the shutdown script errored."), | ||||||||||||
SHUTDOWN_TIMEOUT("⦸ Shutdown with timeout", "The agent shut down but the shutdown script timed out."), | ||||||||||||
code-asher marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
OFF("⦸ Off", "The agent has shut down."), | ||||||||||||
READY("⦿ Ready", "The agent is ready to accept connections."); | ||||||||||||
|
||||||||||||
fun statusColor(): JBColor = when (this) { | ||||||||||||
READY, AGENT_STARTING_READY -> JBColor.GREEN | ||||||||||||
START_ERROR, START_TIMEOUT -> JBColor.YELLOW | ||||||||||||
FAILED, DISCONNECTED, TIMEOUT, SHUTTING_DOWN, SHUTDOWN_ERROR, SHUTDOWN_TIMEOUT -> JBColor.RED | ||||||||||||
else -> if (JBColor.isBright()) JBColor.LIGHT_GRAY else JBColor.DARK_GRAY | ||||||||||||
} | ||||||||||||
|
||||||||||||
// 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. | ||||||||||||
// | ||||||||||||
// We can also choose to allow `start_timeout` and `start_error` for the | ||||||||||||
// agent state; this means the startup script did not successfully complete | ||||||||||||
// but the agent will accept SSH connections. | ||||||||||||
// | ||||||||||||
// Lastly we can also allow connections when the agent lifecycle state is | ||||||||||||
// `starting` if `login_before_ready` is true on the workspace response. | ||||||||||||
// | ||||||||||||
// Note that latest_build.status is derived from latest_build.job.status and | ||||||||||||
// latest_build.job.transition so there is no need to check those. | ||||||||||||
companion object { | ||||||||||||
fun from(workspace: Workspace, agent: WorkspaceAgent? = null) = when (workspace.latestBuild.status) { | ||||||||||||
WorkspaceStatus.PENDING -> QUEUED | ||||||||||||
WorkspaceStatus.STARTING -> STARTING | ||||||||||||
WorkspaceStatus.RUNNING -> when (agent?.status) { | ||||||||||||
WorkspaceAgentStatus.CONNECTED -> when (agent.lifecycleState) { | ||||||||||||
WorkspaceAgentLifecycleState.CREATED -> CREATED | ||||||||||||
WorkspaceAgentLifecycleState.STARTING -> if (agent.loginBeforeReady == true) AGENT_STARTING_READY else AGENT_STARTING | ||||||||||||
WorkspaceAgentLifecycleState.START_TIMEOUT -> START_TIMEOUT | ||||||||||||
code-asher marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||
WorkspaceAgentLifecycleState.START_ERROR -> START_ERROR | ||||||||||||
WorkspaceAgentLifecycleState.READY -> READY | ||||||||||||
WorkspaceAgentLifecycleState.SHUTTING_DOWN -> SHUTTING_DOWN | ||||||||||||
WorkspaceAgentLifecycleState.SHUTDOWN_TIMEOUT -> SHUTDOWN_TIMEOUT | ||||||||||||
WorkspaceAgentLifecycleState.SHUTDOWN_ERROR -> SHUTDOWN_ERROR | ||||||||||||
WorkspaceAgentLifecycleState.OFF -> OFF | ||||||||||||
} | ||||||||||||
|
||||||||||||
WorkspaceAgentStatus.DISCONNECTED -> DISCONNECTED | ||||||||||||
WorkspaceAgentStatus.TIMEOUT -> TIMEOUT | ||||||||||||
WorkspaceAgentStatus.CONNECTING -> CONNECTING | ||||||||||||
else -> RUNNING | ||||||||||||
} | ||||||||||||
|
||||||||||||
WorkspaceStatus.STOPPING -> STOPPING | ||||||||||||
WorkspaceStatus.STOPPED -> STOPPED | ||||||||||||
WorkspaceStatus.FAILED -> FAILED | ||||||||||||
WorkspaceStatus.CANCELING -> CANCELING | ||||||||||||
WorkspaceStatus.CANCELED -> CANCELED | ||||||||||||
WorkspaceStatus.DELETING -> DELETING | ||||||||||||
WorkspaceStatus.DELETED -> DELETED | ||||||||||||
} | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mafredri does this look right to you? I use this computed state to determine whether to enable the connect button: jetbrains-coder/src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt Lines 135 to 139 in 664c383
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, it looks mostly correct 👍. The start timeout behaves a bit different so needs some extra consideration but didn't spot any other issues. |
||||||||||||
|
||||||||||||
fun from(str: String) = WorkspaceAndAgentStatus.values().first { it.label.contains(str, true) } | ||||||||||||
} | ||||||||||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something feels a bit off to me about this, like maybe we should just have the workspace status and agent status and check both whenever we need to rather than have this computed state but my thoughts about it are a bit fuzzy and we already had it architectured like this so I left it for now.