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

Commit597bc72

Browse files
authored
feature: Add setting to remove/set custom workspace filter for connections view. (#490)
Add setting to remove/set custom workspace filter for connections view.
1 parent39faf50 commit597bc72

File tree

35 files changed

+331
-162
lines changed

35 files changed

+331
-162
lines changed

‎CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44

55
##Unreleased
66

7+
###Added
8+
9+
- Add ability to customize filter for workspace connections view.
10+
- Add owner column to connections view table.
11+
- Add ability to connect to workspaces you don't own but have permissions for.
12+
713
##2.14.2 - 2024-09-23
814

915
###Changed

‎src/main/kotlin/com/coder/gateway/CoderSettingsConfigurable.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,11 @@ class CoderSettingsConfigurable : BoundConfigurable("Coder") {
144144
.bindText(state::sshLogDirectory)
145145
.comment(CoderGatewayBundle.message("gateway.connector.settings.ssh-log-directory.comment"))
146146
}.layout(RowLayout.PARENT_GRID)
147+
row(CoderGatewayBundle.message("gateway.connector.settings.workspace-filter.title")) {
148+
textField().resizableColumn().align(AlignX.FILL)
149+
.bindText(state::workspaceFilter)
150+
.comment(CoderGatewayBundle.message("gateway.connector.settings.workspace-filter.comment"))
151+
}.layout(RowLayout.PARENT_GRID)
147152
}
148153
}
149154

‎src/main/kotlin/com/coder/gateway/cli/CoderCLIManager.kt

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ package com.coder.gateway.cli
33
importcom.coder.gateway.cli.ex.MissingVersionException
44
importcom.coder.gateway.cli.ex.ResponseException
55
importcom.coder.gateway.cli.ex.SSHConfigFormatException
6+
importcom.coder.gateway.sdk.v2.models.User
7+
importcom.coder.gateway.sdk.v2.models.Workspace
8+
importcom.coder.gateway.sdk.v2.models.WorkspaceAgent
69
importcom.coder.gateway.settings.CoderSettings
710
importcom.coder.gateway.settings.CoderSettingsState
811
importcom.coder.gateway.util.CoderHostnameVerifier
@@ -219,11 +222,12 @@ class CoderCLIManager(
219222
* This can take supported features for testing purposes only.
220223
*/
221224
funconfigSsh(
222-
workspaceNames:Set<String>,
225+
workspacesAndAgents:Set<Pair<Workspace,WorkspaceAgent>>,
226+
currentUser:User,
223227
feats:Features = features,
224228
) {
225229
logger.info("Configuring SSH config at${settings.sshConfigPath}")
226-
writeSSHConfig(modifySSHConfig(readSSHConfig(),workspaceNames, feats))
230+
writeSSHConfig(modifySSHConfig(readSSHConfig(),workspacesAndAgents, feats, currentUser))
227231
}
228232

229233
/**
@@ -245,8 +249,9 @@ class CoderCLIManager(
245249
*/
246250
privatefunmodifySSHConfig(
247251
contents:String?,
248-
workspaceNames:Set<String>,
252+
workspaceNames:Set<Pair<Workspace,WorkspaceAgent>>,
249253
feats:Features,
254+
currentUser:User,
250255
):String? {
251256
val host= deploymentURL.safeHost()
252257
val startBlock="# --- START CODER JETBRAINS$host"
@@ -287,8 +292,8 @@ class CoderCLIManager(
287292
System.lineSeparator()+ endBlock,
288293
transform= {
289294
"""
290-
Host${getHostName(deploymentURL, it)}
291-
ProxyCommand${proxyArgs.joinToString("")}$it
295+
Host${getHostName(deploymentURL, it.first, currentUser, it.second)}
296+
ProxyCommand${proxyArgs.joinToString("")}${getWorkspaceParts(it.first, it.second)}
292297
ConnectTimeout 0
293298
StrictHostKeyChecking no
294299
UserKnownHostsFile /dev/null
@@ -299,8 +304,8 @@ class CoderCLIManager(
299304
.plus("\n")
300305
.plus(
301306
"""
302-
Host${getBackgroundHostName(deploymentURL, it)}
303-
ProxyCommand${backgroundProxyArgs.joinToString("")}$it
307+
Host${getBackgroundHostName(deploymentURL, it.first, currentUser, it.second)}
308+
ProxyCommand${backgroundProxyArgs.joinToString("")}${getWorkspaceParts(it.first, it.second)}
304309
ConnectTimeout 0
305310
StrictHostKeyChecking no
306311
UserKnownHostsFile /dev/null
@@ -478,17 +483,43 @@ class CoderCLIManager(
478483

479484
privateval tokenRegex="--token [^ ]+".toRegex()
480485

486+
/**
487+
* This function returns the ssh host name generated for connecting to the workspace.
488+
*/
481489
@JvmStatic
482490
fungetHostName(
483491
url:URL,
484-
workspaceName:String,
485-
):String="coder-jetbrains--$workspaceName--${url.safeHost()}"
492+
workspace:Workspace,
493+
currentUser:User,
494+
agent:WorkspaceAgent,
495+
):String=
496+
// For a user's own workspace, we use the old syntax without a username for backwards compatibility,
497+
// since the user might have recent connections that still use the old syntax.
498+
if (currentUser.username== workspace.ownerName) {
499+
"coder-jetbrains--${workspace.name}.${agent.name}--${url.safeHost()}"
500+
}else {
501+
"coder-jetbrains--${workspace.ownerName}--${workspace.name}.${agent.name}--${url.safeHost()}"
502+
}
486503

487-
@JvmStatic
488504
fungetBackgroundHostName(
489505
url:URL,
490-
workspaceName:String,
491-
):String= getHostName(url, workspaceName)+"--bg"
506+
workspace:Workspace,
507+
currentUser:User,
508+
agent:WorkspaceAgent,
509+
):String {
510+
return getHostName(url, workspace, currentUser, agent)+"--bg"
511+
}
512+
513+
514+
/**
515+
* This function returns the identifier for the workspace to pass to the
516+
* coder ssh proxy command.
517+
*/
518+
@JvmStatic
519+
fungetWorkspaceParts(
520+
workspace:Workspace,
521+
agent:WorkspaceAgent,
522+
):String="${workspace.ownerName}/${workspace.name}.${agent.name}"
492523

493524
@JvmStatic
494525
fungetBackgroundHostName(

‎src/main/kotlin/com/coder/gateway/sdk/CoderRestClient.kt

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,7 @@ import com.coder.gateway.sdk.convertors.OSConverter
88
importcom.coder.gateway.sdk.convertors.UUIDConverter
99
importcom.coder.gateway.sdk.ex.APIResponseException
1010
importcom.coder.gateway.sdk.v2.CoderV2RestFacade
11-
importcom.coder.gateway.sdk.v2.models.BuildInfo
12-
importcom.coder.gateway.sdk.v2.models.CreateWorkspaceBuildRequest
13-
importcom.coder.gateway.sdk.v2.models.Template
14-
importcom.coder.gateway.sdk.v2.models.User
15-
importcom.coder.gateway.sdk.v2.models.Workspace
16-
importcom.coder.gateway.sdk.v2.models.WorkspaceBuild
17-
importcom.coder.gateway.sdk.v2.models.WorkspaceResource
18-
importcom.coder.gateway.sdk.v2.models.WorkspaceTransition
11+
importcom.coder.gateway.sdk.v2.models.*
1912
importcom.coder.gateway.settings.CoderSettings
2013
importcom.coder.gateway.settings.CoderSettingsState
2114
importcom.coder.gateway.util.CoderHostnameVerifier
@@ -166,7 +159,7 @@ open class CoderRestClient(
166159
* @throws [APIResponseException].
167160
*/
168161
funworkspaces():List<Workspace> {
169-
val workspacesResponse= retroRestClient.workspaces("owner:me").execute()
162+
val workspacesResponse= retroRestClient.workspaces(settings.workspaceFilter).execute()
170163
if (!workspacesResponse.isSuccessful) {
171164
throwAPIResponseException("retrieve workspaces", url, workspacesResponse)
172165
}
@@ -178,12 +171,12 @@ open class CoderRestClient(
178171
* Retrieves all the agent names for all workspaces, including those that
179172
* are off. Meant to be used when configuring SSH.
180173
*/
181-
funagentNames(workspaces:List<Workspace>):Set<String> {
174+
funwithAgents(workspaces:List<Workspace>):Set<Pair<Workspace,WorkspaceAgent>> {
182175
// It is possible for there to be resources with duplicate names so we
183176
// need to use a set.
184177
return workspaces.flatMap { ws->
185178
ws.latestBuild.resources.ifEmpty { resources(ws) }.filter { it.agents!=null }.flatMap { it.agents!! }.map {
186-
"${ws.name}.${it.name}"
179+
ws to it
187180
}
188181
}.toSet()
189182
}

‎src/main/kotlin/com/coder/gateway/sdk/v2/models/Workspace.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ data class Workspace(
1919
@Json(name="latest_build")vallatestBuild:WorkspaceBuild,
2020
@Json(name="outdated")valoutdated:Boolean,
2121
@Json(name="name")valname:String,
22+
@Json(name="owner_name")valownerName:String,
2223
)
2324

2425
/**

‎src/main/kotlin/com/coder/gateway/settings/CoderSettings.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ open class CoderSettingsState(
9898
openvardefaultURL:String ="",
9999
// Value for --log-dir.
100100
openvarsshLogDirectory:String ="",
101+
// Default filter for fetching workspaces
102+
openvarworkspaceFilter:String ="owner:me"
101103
)
102104

103105
/**
@@ -135,6 +137,12 @@ open class CoderSettings(
135137
val enableDownloads:Boolean
136138
get()= state.enableDownloads
137139

140+
/**
141+
* The filter to apply when fetching workspaces (default is owner:me)
142+
*/
143+
val workspaceFilter:String
144+
get()= state.workspaceFilter
145+
138146
/**
139147
* Whether falling back to the data directory is allowed if the binary
140148
* directory is not writable.

‎src/main/kotlin/com/coder/gateway/util/Dialogs.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,13 @@ import javax.swing.border.Border
3232
* A dialog wrapper around CoderWorkspaceStepView.
3333
*/
3434
privateclassCoderWorkspaceStepDialog(
35-
name:String,
3635
privatevalstate:CoderWorkspacesStepSelection,
3736
) : DialogWrapper(true) {
3837
privateval view=CoderWorkspaceProjectIDEStepView(showTitle=false)
3938

4039
init {
4140
init()
42-
title=CoderGatewayBundle.message("gateway.connector.view.coder.remoteproject.choose.text",name)
41+
title=CoderGatewayBundle.message("gateway.connector.view.coder.remoteproject.choose.text",CoderCLIManager.getWorkspaceParts(state.workspace, state.agent))
4342
}
4443

4544
overridefunshow() {
@@ -71,7 +70,6 @@ private class CoderWorkspaceStepDialog(
7170
}
7271

7372
funaskIDE(
74-
name:String,
7573
agent:WorkspaceAgent,
7674
workspace:Workspace,
7775
cli:CoderCLIManager,
@@ -82,7 +80,6 @@ fun askIDE(
8280
ApplicationManager.getApplication().invokeAndWait {
8381
val dialog=
8482
CoderWorkspaceStepDialog(
85-
name,
8683
CoderWorkspacesStepSelection(agent, workspace, cli, client, workspaces),
8784
)
8885
data= dialog.showAndGetData()

‎src/main/kotlin/com/coder/gateway/util/LinkHandler.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ open class LinkHandler(
106106
}
107107

108108
indicator?.invoke("Configuring Coder CLI...")
109-
cli.configSsh(client.agentNames(workspaces))
109+
cli.configSsh(workspacesAndAgents=client.withAgents(workspaces), currentUser= client.me)
110110

111111
val name="${workspace.name}.${agent.name}"
112112
val openDialog=
@@ -116,14 +116,14 @@ open class LinkHandler(
116116
parameters.folder().isNullOrBlank()
117117

118118
returnif (openDialog) {
119-
askIDE(name,agent, workspace, cli, client, workspaces)?:throwMissingArgumentException("IDE selection aborted; unable to connect")
119+
askIDE(agent, workspace, cli, client, workspaces)?:throwMissingArgumentException("IDE selection aborted; unable to connect")
120120
}else {
121121
// Check that both the domain and the redirected domain are
122122
// allowlisted. If not, check with the user whether to proceed.
123123
verifyDownloadLink(parameters)
124124
WorkspaceProjectIDE.fromInputs(
125125
name= name,
126-
hostname=CoderCLIManager.getHostName(deploymentURL.toURL(),name),
126+
hostname=CoderCLIManager.getHostName(deploymentURL.toURL(),workspace, client.me, agent),
127127
projectPath= parameters.folder(),
128128
ideProductCode= parameters.ideProductCode(),
129129
ideBuildNumber= parameters.ideBuildNumber(),

‎src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspaceProjectIDEStepView.kt

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -184,23 +184,22 @@ class CoderWorkspaceProjectIDEStepView(
184184

185185
// We use this when returning the connection params from data().
186186
state= data
187-
188-
val name="${data.workspace.name}.${data.agent.name}"
187+
val name=CoderCLIManager.getWorkspaceParts(data.workspace, data.agent)
189188
logger.info("Initializing workspace step for$name")
190189

191190
val homeDirectory= data.agent.expandedDirectory?: data.agent.directory
192191
tfProject.text=if (homeDirectory.isNullOrBlank())"/home"else homeDirectory
193192
titleLabel.text=CoderGatewayBundle.message("gateway.connector.view.coder.remoteproject.choose.text", name)
194193
titleLabel.isVisible= showTitle
195-
terminalLink.url= data.client.url.withPath("/me/$name/terminal").toString()
194+
terminalLink.url= data.client.url.withPath("/$name/terminal").toString()
196195

197196
ideResolvingJob=
198197
cs.launch(ModalityState.current().asContextElement()) {
199198
try {
200199
logger.info("Configuring Coder CLI...")
201200
cbIDE.renderer=IDECellRenderer("Configuring Coder CLI...")
202201
withContext(Dispatchers.IO) {
203-
data.cliManager.configSsh(data.client.agentNames(data.workspaces))
202+
data.cliManager.configSsh(data.client.withAgents(data.workspaces), data.client.me)
204203
}
205204

206205
val ides=
@@ -215,7 +214,7 @@ class CoderWorkspaceProjectIDEStepView(
215214
}else {
216215
IDECellRenderer(CoderGatewayBundle.message("gateway.connector.view.coder.connect-ssh"))
217216
}
218-
val executor= createRemoteExecutor(CoderCLIManager.getBackgroundHostName(data.client.url,name))
217+
val executor= createRemoteExecutor(CoderCLIManager.getBackgroundHostName(data.client.url,data.workspace, data.client.me, data.agent))
219218

220219
if (ComponentValidator.getInstance(tfProject).isEmpty) {
221220
logger.info("Installing remote path validator...")
@@ -338,7 +337,7 @@ class CoderWorkspaceProjectIDEStepView(
338337
workspace:Workspace,
339338
agent:WorkspaceAgent,
340339
):List<IdeWithStatus> {
341-
val name="${workspace.name}.${agent.name}"
340+
val name=CoderCLIManager.getWorkspaceParts(workspace,agent)
342341
logger.info("Retrieving available IDEs for$name...")
343342
val workspaceOS=
344343
if (agent.operatingSystem!=null&& agent.architecture!=null) {
@@ -406,7 +405,7 @@ class CoderWorkspaceProjectIDEStepView(
406405
val name="${state.workspace.name}.${state.agent.name}"
407406
selectedIDE.withWorkspaceProject(
408407
name= name,
409-
hostname=CoderCLIManager.getHostName(state.client.url,name),
408+
hostname=CoderCLIManager.getHostName(state.client.url,state.workspace, state.client.me, state.agent),
410409
projectPath= tfProject.text,
411410
deploymentURL= state.client.url,
412411
)

‎src/main/kotlin/com/coder/gateway/views/steps/CoderWorkspacesStepView.kt

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import com.intellij.openapi.application.ModalityState
3333
importcom.intellij.openapi.application.asContextElement
3434
importcom.intellij.openapi.components.service
3535
importcom.intellij.openapi.diagnostic.Logger
36+
importcom.intellij.openapi.observable.properties.ObservableMutableProperty
3637
importcom.intellij.openapi.rd.util.launchUnderBackgroundProgress
3738
importcom.intellij.openapi.ui.panel.ComponentPanelBuilder
3839
importcom.intellij.openapi.ui.setEmptyState
@@ -89,7 +90,7 @@ private const val SESSION_TOKEN_KEY = "session-token"
8990
privatedata classCoderWorkspacesFormFields(
9091
varcoderURL:String ="",
9192
vartoken:Pair<String,Source>? =null,
92-
varuseExistingToken:Boolean =false,
93+
varuseExistingToken:Boolean =false
9394
)
9495

9596
/**
@@ -751,7 +752,7 @@ class CoderWorkspacesStepView :
751752
overridefundata():CoderWorkspacesStepSelection {
752753
val selected= tableOfWorkspaces.selectedObject
753754
return withoutNull(client, cliManager, selected?.agent, selected?.workspace) { client, cli, agent, workspace->
754-
val name="${workspace.name}.${agent.name}"
755+
val name=CoderCLIManager.getWorkspaceParts(workspace,agent)
755756
logger.info("Returning data for$name")
756757
CoderWorkspacesStepSelection(
757758
agent= agent,
@@ -783,6 +784,7 @@ class WorkspacesTableModel :
783784
ListTableModel<WorkspaceAgentListModel>(
784785
WorkspaceIconColumnInfo(""),
785786
WorkspaceNameColumnInfo("Name"),
787+
WorkspaceOwnerColumnInfo("Owner"),
786788
WorkspaceTemplateNameColumnInfo("Template"),
787789
WorkspaceVersionColumnInfo("Version"),
788790
WorkspaceStatusColumnInfo("Status"),
@@ -849,6 +851,36 @@ class WorkspacesTableModel :
849851
}
850852
}
851853

854+
privateclassWorkspaceOwnerColumnInfo(columnName:String) : ColumnInfo<WorkspaceAgentListModel, String>(columnName) {
855+
overridefunvalueOf(item:WorkspaceAgentListModel?):String?= item?.workspace?.ownerName
856+
857+
overridefungetComparator():Comparator<WorkspaceAgentListModel>=Comparator { a, b->
858+
a.workspace.ownerName.compareTo(b.workspace.ownerName, ignoreCase=true)
859+
}
860+
861+
overridefungetRenderer(item:WorkspaceAgentListModel?):TableCellRenderer {
862+
returnobject:DefaultTableCellRenderer() {
863+
overridefungetTableCellRendererComponent(
864+
table:JTable,
865+
value:Any,
866+
isSelected:Boolean,
867+
hasFocus:Boolean,
868+
row:Int,
869+
column:Int,
870+
):Component {
871+
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column)
872+
if (valueisString) {
873+
text= value
874+
}
875+
876+
font=RelativeFont.BOLD.derive(table.tableHeader.font)
877+
border=JBUI.Borders.empty(0,8)
878+
returnthis
879+
}
880+
}
881+
}
882+
}
883+
852884
privateclassWorkspaceTemplateNameColumnInfo(columnName:String) : ColumnInfo<WorkspaceAgentListModel, String>(columnName) {
853885
overridefunvalueOf(item:WorkspaceAgentListModel?):String?= item?.workspace?.templateName
854886

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp