Skip to content

Retrieve workspace directly in link handler when using wildcardSSH feature #542

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 3 commits into from
Mar 7, 2025
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

## Unreleased

### Changed

Retrieve workspace directly in link handler when using wildcardSSH feature

## 2.19.0 - 2025-02-21

### Added
Expand Down
13 changes: 13 additions & 0 deletions src/main/kotlin/com/coder/gateway/sdk/CoderRestClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,19 @@ open class CoderRestClient(
return workspacesResponse.body()!!.workspaces
}

/**
* Retrieves a specific workspace by owner and name.
* @throws [APIResponseException].
*/
fun workspaceByOwnerAndName(owner: String, workspaceName: String): Workspace {
val workspaceResponse = retroRestClient.workspaceByOwnerAndName(owner, workspaceName).execute()
if (!workspaceResponse.isSuccessful) {
throw APIResponseException("retrieve workspace", url, workspaceResponse)
}

return workspaceResponse.body()!!
}

/**
* Retrieves all the agent names for all workspaces, including those that
* are off. Meant to be used when configuring SSH.
Expand Down
10 changes: 10 additions & 0 deletions src/main/kotlin/com/coder/gateway/sdk/v2/CoderV2RestFacade.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.coder.gateway.sdk.v2.models.BuildInfo
import com.coder.gateway.sdk.v2.models.CreateWorkspaceBuildRequest
import com.coder.gateway.sdk.v2.models.Template
import com.coder.gateway.sdk.v2.models.User
import com.coder.gateway.sdk.v2.models.Workspace
import com.coder.gateway.sdk.v2.models.WorkspaceBuild
import com.coder.gateway.sdk.v2.models.WorkspaceResource
import com.coder.gateway.sdk.v2.models.WorkspacesResponse
Expand All @@ -22,6 +23,15 @@ interface CoderV2RestFacade {
@GET("api/v2/users/me")
fun me(): Call<User>

/**
* Retrieves a specific workspace by owner and name.
*/
@GET("api/v2/users/{user}/workspace/{workspace}")
fun workspaceByOwnerAndName(
@Path("user") user: String,
@Path("workspace") workspace: String,
): Call<Workspace>

/**
* Retrieves all workspaces the authenticated user has access to.
*/
Expand Down
40 changes: 22 additions & 18 deletions src/main/kotlin/com/coder/gateway/util/LinkHandler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,27 @@
// owner is included, assume the current user.
val owner = (parameters.owner() ?: client.me.username).ifBlank { client.me.username }

val workspaces = client.workspaces()
val workspace =
workspaces.firstOrNull {
it.ownerName == owner && it.name == workspaceName
} ?: throw IllegalArgumentException("The workspace $workspaceName does not exist")
val cli =
ensureCLI(
deploymentURL.toURL(),
client.buildInfo().version,
settings,
indicator,
)

var workspace : Workspace

Check warning on line 68 in src/main/kotlin/com/coder/gateway/util/LinkHandler.kt

View workflow job for this annotation

GitHub Actions / Build

Local 'var' is never modified and can be declared as 'val'

Variable is never modified, so it can be declared using 'val'
var workspaces : List<Workspace> = emptyList()
var workspacesAndAgents : Set<Pair<Workspace, WorkspaceAgent>> = emptySet()
if (cli.features.wildcardSSH) {
workspace = client.workspaceByOwnerAndName(owner, workspaceName)
} else {
workspaces = client.workspaces()
workspace =
workspaces.firstOrNull {
it.ownerName == owner && it.name == workspaceName
} ?: throw IllegalArgumentException("The workspace $workspaceName does not exist")
workspacesAndAgents = client.withAgents(workspaces)
}

when (workspace.latestBuild.status) {
WorkspaceStatus.PENDING, WorkspaceStatus.STARTING ->
Expand Down Expand Up @@ -96,26 +112,14 @@
throw IllegalArgumentException("The agent \"${agent.name}\" has a status of \"${status.toString().lowercase()}\"; unable to connect")
}

val cli =
ensureCLI(
deploymentURL.toURL(),
client.buildInfo().version,
settings,
indicator,
)

// We only need to log in if we are using token-based auth.
if (client.token != null) {
indicator?.invoke("Authenticating Coder CLI...")
cli.login(client.token)
}

indicator?.invoke("Configuring Coder CLI...")
if (cli.features.wildcardSSH) {
cli.configSsh(workspacesAndAgents = emptySet(), currentUser = client.me)
} else {
cli.configSsh(workspacesAndAgents = client.withAgents(workspaces), currentUser = client.me)
}
cli.configSsh(workspacesAndAgents, currentUser = client.me)

val openDialog =
parameters.ideProductCode().isNullOrBlank() ||
Expand Down
Loading