-
Notifications
You must be signed in to change notification settings - Fork 16
add popup diaglog for missing IDE data on url handler #372
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 all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,6 @@ import com.coder.gateway.cli.CoderCLIManager | |
import com.coder.gateway.cli.ensureCLI | ||
import com.coder.gateway.models.TokenSource | ||
import com.coder.gateway.models.WorkspaceAndAgentStatus | ||
import com.coder.gateway.sdk.BaseCoderRestClient | ||
import com.coder.gateway.sdk.CoderRestClient | ||
import com.coder.gateway.sdk.ex.AuthenticationResponseException | ||
import com.coder.gateway.sdk.v2.models.Workspace | ||
|
@@ -15,12 +14,17 @@ import com.coder.gateway.sdk.v2.models.WorkspaceStatus | |
import com.coder.gateway.services.CoderSettingsService | ||
import com.coder.gateway.util.toURL | ||
import com.coder.gateway.util.withPath | ||
import com.coder.gateway.views.steps.CoderWorkspaceStepView | ||
import com.coder.gateway.views.steps.CoderWorkspacesStepSelection | ||
import com.intellij.openapi.application.ApplicationManager | ||
import com.intellij.openapi.components.service | ||
import com.intellij.openapi.diagnostic.Logger | ||
import com.intellij.openapi.ui.DialogWrapper | ||
import com.jetbrains.gateway.api.ConnectionRequestor | ||
import com.jetbrains.gateway.api.GatewayConnectionHandle | ||
import com.jetbrains.gateway.api.GatewayConnectionProvider | ||
import java.net.URL | ||
import javax.swing.JComponent | ||
|
||
// In addition to `type`, these are the keys that we support in our Gateway | ||
// links. | ||
|
@@ -34,6 +38,18 @@ private const val IDE_DOWNLOAD_LINK = "ide_download_link" | |
private const val IDE_PRODUCT_CODE = "ide_product_code" | ||
private const val IDE_BUILD_NUMBER = "ide_build_number" | ||
private const val IDE_PATH_ON_HOST = "ide_path_on_host" | ||
private const val PROJECT_PATH = "project_path" | ||
|
||
class SelectWorkspaceIDEDialog(private val comp: JComponent) : DialogWrapper(true) { | ||
init { | ||
init() | ||
title = "Select workspace IDE" | ||
} | ||
|
||
override fun createCenterPanel(): JComponent? { | ||
return comp | ||
} | ||
} | ||
|
||
// CoderGatewayConnectionProvider handles connecting via a Gateway link such as | ||
// jetbrains-gateway://connect#type=coder. | ||
|
@@ -93,31 +109,38 @@ class CoderGatewayConnectionProvider : GatewayConnectionProvider { | |
cli.login(client.token) | ||
|
||
indicator.text = "Configuring Coder CLI..." | ||
cli.configSsh(client.agentNames(workspaces)) | ||
cli.configSsh(client.agentNames(workspaces).toSet()) | ||
|
||
// TODO: Ask for these if missing. Maybe we can reuse the second | ||
// step of the wizard? Could also be nice if we automatically used | ||
// the last IDE. | ||
if (parameters[IDE_PRODUCT_CODE].isNullOrBlank()) { | ||
throw IllegalArgumentException("Query parameter \"$IDE_PRODUCT_CODE\" is missing") | ||
} | ||
if (parameters[IDE_BUILD_NUMBER].isNullOrBlank()) { | ||
throw IllegalArgumentException("Query parameter \"$IDE_BUILD_NUMBER\" is missing") | ||
} | ||
if (parameters[IDE_PATH_ON_HOST].isNullOrBlank() && parameters[IDE_DOWNLOAD_LINK].isNullOrBlank()) { | ||
throw IllegalArgumentException("One of \"$IDE_PATH_ON_HOST\" or \"$IDE_DOWNLOAD_LINK\" is required") | ||
} | ||
|
||
val openDialog = parameters[IDE_PRODUCT_CODE].isNullOrBlank() || | ||
parameters[IDE_BUILD_NUMBER].isNullOrBlank() || | ||
(parameters[IDE_PATH_ON_HOST].isNullOrBlank() && parameters[IDE_DOWNLOAD_LINK].isNullOrBlank()) || | ||
parameters[FOLDER].isNullOrBlank() | ||
|
||
val params = if (openDialog) { | ||
val view = CoderWorkspaceStepView{} | ||
ApplicationManager.getApplication().invokeAndWait { | ||
view.init( | ||
CoderWorkspacesStepSelection(agent, workspace, cli, client, workspaces) | ||
) | ||
val dialog = SelectWorkspaceIDEDialog(view.component) | ||
dialog.show() | ||
code-asher marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
val p = parameters.toMutableMap() | ||
|
||
|
||
listOf(IDE_PRODUCT_CODE, IDE_BUILD_NUMBER, PROJECT_PATH, IDE_PATH_ON_HOST, IDE_DOWNLOAD_LINK).forEach { prop -> | ||
view.data()[prop]?.let { value -> p[prop] = value } | ||
} | ||
p | ||
} else | ||
parameters.withProjectPath(parameters[FOLDER]!!) | ||
|
||
// Check that both the domain and the redirected domain are | ||
// allowlisted. If not, check with the user whether to proceed. | ||
verifyDownloadLink(parameters) | ||
code-asher marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
// TODO: Ask for the project path if missing and validate the path. | ||
val folder = parameters[FOLDER] ?: throw IllegalArgumentException("Query parameter \"$FOLDER\" is missing") | ||
|
||
parameters | ||
.withWorkspaceHostname(CoderCLIManager.getHostName(deploymentURL.toURL(), agent.name)) | ||
.withProjectPath(folder) | ||
params.withWorkspaceHostname(CoderCLIManager.getHostName(deploymentURL.toURL(), "${workspace.name}.${agent.name}")) | ||
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. I am not sure how this ever worked ... this was just using the 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. Good catch, I think I recently broke this because |
||
.withWebTerminalLink(client.url.withPath("/@$username/$workspace.name/terminal").toString()) | ||
.withConfigDirectory(cli.coderConfigPath.toString()) | ||
.withName(workspaceName) | ||
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. Note to self: I think this is also meant to be in the |
||
|
@@ -129,7 +152,7 @@ class CoderGatewayConnectionProvider : GatewayConnectionProvider { | |
* Return an authenticated Coder CLI and the user's name, asking for the | ||
* token as long as it continues to result in an authentication failure. | ||
*/ | ||
private fun authenticate(deploymentURL: URL, queryToken: String?, lastToken: Pair<String, TokenSource>? = null): Pair<BaseCoderRestClient, String> { | ||
private fun authenticate(deploymentURL: URL, queryToken: String?, lastToken: Pair<String, TokenSource>? = null): Pair<CoderRestClient, String> { | ||
code-asher marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Use the token from the query, unless we already tried that. | ||
val isRetry = lastToken != null | ||
val token = if (!queryToken.isNullOrBlank() && !isRetry) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -89,7 +89,7 @@ class CoderWorkspaceStepView( | |
// Called with a boolean indicating whether IDE selection is complete. | ||
private val nextButtonEnabled: (Boolean) -> Unit, | ||
) : CoderWizardStep { | ||
private val cs = CoroutineScope(Dispatchers.Main) | ||
private val cs = CoroutineScope(Dispatchers.IO) | ||
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. I moved it to 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. @coryb is this code performing an I/O heavy operation, like waiting on network calls or disk read / writes? If not, 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. The operation I think uses ssh to connect to the workspace to look for installed ides, so it is certainly using network I/O, but probably does not qualify as "I/O heavy" 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. If that’s the case, the IO Dispatcher is likely safe to keep as-is 👍🏼 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. There probably is some magic to get |
||
private var ideComboBoxModel = DefaultComboBoxModel<IdeWithStatus>() | ||
private var state: CoderWorkspacesStepSelection? = null | ||
|
||
|
@@ -189,7 +189,7 @@ class CoderWorkspaceStepView( | |
logger.info("Configuring Coder CLI...") | ||
cbIDE.renderer = IDECellRenderer("Configuring Coder CLI...") | ||
withContext(Dispatchers.IO) { | ||
data.cliManager.configSsh(data.client.agentNames(data.workspaces)) | ||
data.cliManager.configSsh(data.client.agentNames(data.workspaces).toSet()) | ||
} | ||
|
||
val ides = suspendingRetryWithExponentialBackOff( | ||
|
@@ -228,7 +228,7 @@ class CoderWorkspaceStepView( | |
cbIDE.renderer = IDECellRenderer(CoderGatewayBundle.message("gateway.connector.view.coder.retrieve-ides.failed.retry", humanizeDuration(remainingMs))) | ||
}, | ||
) | ||
withContext(Dispatchers.Main) { | ||
withContext(Dispatchers.IO) { | ||
ideComboBoxModel.addAll(ides) | ||
cbIDE.selectedIndex = 0 | ||
} | ||
|
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.
The previous version was expired, so could not run it locally.