From 48cbd8bff8960fc848218b8b25572e0e170e2387 Mon Sep 17 00:00:00 2001 From: Victor Nogueira Date: Tue, 11 Oct 2022 08:54:23 +0000 Subject: [PATCH] Adjust JetBrains Backend Plugin to work with the new Port Forwarding API --- .../backend-plugin/gradle-latest.properties | 2 +- .../backend-plugin/launch-dev-server.sh | 36 ++++-- .../latest/GitpodPortForwardingService.kt | 116 ++++++++++++------ .../resources-latest/META-INF/extensions.xml | 2 +- 4 files changed, 108 insertions(+), 48 deletions(-) diff --git a/components/ide/jetbrains/backend-plugin/gradle-latest.properties b/components/ide/jetbrains/backend-plugin/gradle-latest.properties index c5b70c4deb7d44..f1e494134b3a3b 100644 --- a/components/ide/jetbrains/backend-plugin/gradle-latest.properties +++ b/components/ide/jetbrains/backend-plugin/gradle-latest.properties @@ -6,4 +6,4 @@ pluginUntilBuild=223.* # See https://jb.gg/intellij-platform-builds-list for available build versions. pluginVerifierIdeVersions=2022.3 # Version from "com.jetbrains.intellij.idea" which can be found at https://www.jetbrains.com/intellij-repository/snapshots -platformVersion=223.5756-EAP-CANDIDATE-SNAPSHOT +platformVersion=223.6160-EAP-CANDIDATE-SNAPSHOT diff --git a/components/ide/jetbrains/backend-plugin/launch-dev-server.sh b/components/ide/jetbrains/backend-plugin/launch-dev-server.sh index 2742dc0de3da41..503b7ebe980301 100755 --- a/components/ide/jetbrains/backend-plugin/launch-dev-server.sh +++ b/components/ide/jetbrains/backend-plugin/launch-dev-server.sh @@ -7,17 +7,19 @@ set -e set -o pipefail # Default Options -DEBUG_PORT=0 +DEBUG_PORT=44444 JB_QUALIFIER="latest" TEST_REPO=https://github.com/gitpod-io/spring-petclinic +RUN_FROM="release" # Parsing Custom Options -while getopts "p:r:s" OPTION +while getopts "p:r:su" OPTION do case $OPTION in s) JB_QUALIFIER="stable" ;; r) TEST_REPO=$OPTARG ;; p) DEBUG_PORT=$OPTARG ;; + u) RUN_FROM="snapshot" ;; *) ;; esac done @@ -25,16 +27,30 @@ done TEST_BACKEND_DIR="/workspace/ide-backend-$JB_QUALIFIER" if [ ! -d "$TEST_BACKEND_DIR" ]; then mkdir -p $TEST_BACKEND_DIR - if [[ $JB_QUALIFIER == "stable" ]]; then - PRODUCT_TYPE="release" + if [[ $RUN_FROM == "snapshot" ]]; then + (cd $TEST_BACKEND_DIR && + SNAPSHOT_VERSION=$(grep "platformVersion=" "gradle-$JB_QUALIFIER.properties" | sed 's/platformVersion=//') && + echo "Downloading the $JB_QUALIFIER version of IntelliJ IDEA ($SNAPSHOT_VERSION)..." && + curl -sSLo backend.zip "https://www.jetbrains.com/intellij-repository/snapshots/com/jetbrains/intellij/idea/ideaIU/$SNAPSHOT_VERSION/ideaIU-$SNAPSHOT_VERSION.zip" && + unzip backend.zip && + rm backend.zip && + ln -s "ideaIU-$SNAPSHOT_VERSION" . && + rm -r "ideaIU-$SNAPSHOT_VERSION" && + cp -r /ide-desktop/backend/jbr . && + cp /ide-desktop/backend/bin/idea.properties ./bin && + cp /ide-desktop/backend/bin/idea64.vmoptions ./bin) else - PRODUCT_TYPE="release,rc,eap" + if [[ $JB_QUALIFIER == "stable" ]]; then + PRODUCT_TYPE="release" + else + PRODUCT_TYPE="release,rc,eap" + fi + (cd $TEST_BACKEND_DIR && + echo "Downloading the $JB_QUALIFIER version of IntelliJ IDEA..." && + curl -sSLo backend.tar.gz "https://download.jetbrains.com/product?type=$PRODUCT_TYPE&distribution=linux&code=IIU" && + tar -xf backend.tar.gz --strip-components=1 && + rm backend.tar.gz) fi - (cd $TEST_BACKEND_DIR && - echo "Downloading the $JB_QUALIFIER version of IntelliJ IDEA..." && - curl -sSLo backend.tar.gz "https://download.jetbrains.com/product?type=$PRODUCT_TYPE&distribution=linux&code=IIU" && - tar -xf backend.tar.gz --strip-components=1 && - rm backend.tar.gz) fi TEST_PLUGINS_DIR="$TEST_BACKEND_DIR/plugins" diff --git a/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/latest/GitpodPortForwardingService.kt b/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/latest/GitpodPortForwardingService.kt index 3e13e22a95ab57..81bb510d2bdde2 100644 --- a/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/latest/GitpodPortForwardingService.kt +++ b/components/ide/jetbrains/backend-plugin/src/main/kotlin/io/gitpod/jetbrains/remote/latest/GitpodPortForwardingService.kt @@ -4,17 +4,17 @@ package io.gitpod.jetbrains.remote.latest +import com.intellij.openapi.Disposable +import com.intellij.openapi.client.ClientProjectSession import com.intellij.openapi.components.service import com.intellij.openapi.diagnostic.thisLogger -import com.intellij.openapi.project.Project +import com.intellij.openapi.util.Disposer import com.intellij.remoteDev.util.onTerminationOrNow import com.intellij.util.application -import com.jetbrains.codeWithMe.model.RdPortType +import com.jetbrains.rd.platform.codeWithMe.portForwarding.* import com.jetbrains.rd.platform.util.lifetime import com.jetbrains.rd.util.lifetime.LifetimeStatus -import com.jetbrains.rdserver.portForwarding.ForwardedPortInfo -import com.jetbrains.rdserver.portForwarding.PortForwardingManager -import com.jetbrains.rdserver.portForwarding.remoteDev.PortEventsProcessor +import io.gitpod.jetbrains.remote.GitpodIgnoredPortsForNotificationService import io.gitpod.jetbrains.remote.GitpodManager import io.gitpod.jetbrains.remote.GitpodPortsService import io.gitpod.supervisor.api.Status @@ -24,14 +24,18 @@ import io.grpc.stub.ClientResponseObserver import io.ktor.utils.io.* import java.util.concurrent.CompletableFuture import java.util.concurrent.TimeUnit +import javax.swing.Icon @Suppress("UnstableApiUsage") -class GitpodPortForwardingService(private val project: Project) { +class GitpodPortForwardingService(private val session: ClientProjectSession) { companion object { const val FORWARDED_PORT_LABEL = "gitpod" } private val portsService = service() + private val perClientPortForwardingManager = service() + private val ignoredPortsForNotificationService = service() + private val portToDisposableMap = mutableMapOf() init { start() } @@ -42,7 +46,7 @@ class GitpodPortForwardingService(private val project: Project) { } private fun observePortsListWhileProjectIsOpen() = application.executeOnPooledThread { - while (project.lifetime.status == LifetimeStatus.Alive) { + while (session.project.lifetime.status == LifetimeStatus.Alive) { try { observePortsList().get() } catch (throwable: Throwable) { @@ -70,7 +74,7 @@ class GitpodPortForwardingService(private val project: Project) { val portsStatusResponseObserver = object : ClientResponseObserver { override fun beforeStart(request: ClientCallStreamObserver) { - project.lifetime.onTerminationOrNow { request.cancel("gitpod: Project terminated.", null) } + session.project.lifetime.onTerminationOrNow { request.cancel("gitpod: Project terminated.", null) } } override fun onNext(response: Status.PortsStatusResponse) { application.invokeLater { updateForwardedPortsList(response) } @@ -85,46 +89,86 @@ class GitpodPortForwardingService(private val project: Project) { } private fun updateForwardedPortsList(response: Status.PortsStatusResponse) { - val portForwardingManager = PortForwardingManager.getInstance(project) - val forwardedPortsList = portForwardingManager.getForwardedPortsWithLabel(FORWARDED_PORT_LABEL) + val ignoredPorts = ignoredPortsForNotificationService.getIgnoredPorts() for (port in response.portsList) { + if (ignoredPorts.contains(port.localPort)) continue + val hostPort = port.localPort val isServed = port.served - val isForwarded = forwardedPortsList.find { it.hostPort == hostPort } != null + val isForwarded = perClientPortForwardingManager.getPorts(hostPort).isNotEmpty() if (isServed && !isForwarded) { - val portEventsProcessor = object : PortEventsProcessor { - override fun onPortForwarded(hostPort: Int, clientPort: Int) { - portsService.setForwardedPort(hostPort, clientPort) - thisLogger().info("gitpod: Forwarded port $hostPort to client's port $clientPort.") - } - - override fun onPortForwardingEnded(hostPort: Int) { - thisLogger().info("gitpod: Finished forwarding port $hostPort.") - } - - override fun onPortForwardingFailed(hostPort: Int, reason: String) { - thisLogger().error("gitpod: Failed to forward port $hostPort: $reason") - } - } - - val portInfo = ForwardedPortInfo( + try { + val forwardedPort = perClientPortForwardingManager.forwardPort( hostPort, - RdPortType.HTTP, - port.exposed.url, - port.name, - port.description, + PortType.TCP, setOf(FORWARDED_PORT_LABEL), - emptyList(), - portEventsProcessor - ) + hostPort, + ClientPortPickingStrategy.REASSIGN_WHEN_BUSY + ) { + this.name = port.name + this.description = port.description + this.icon = null + this.tooltip = "Forwarded Port" + } - portForwardingManager.forwardPort(portInfo) + val portListenerDisposable = portToDisposableMap.getOrPut(hostPort, fun() = Disposer.newDisposable()) + + forwardedPort.addPortListener(portListenerDisposable, object: ForwardedPortListener { + override fun becameReadOnly(port: ForwardedPort, reason: String?) { + thisLogger().warn("gitpod: becameReadOnly($port, $reason)") + } + + override fun descriptionChanged(port: ForwardedPort, oldDescription: String?, newDescription: String?) { + thisLogger().warn("gitpod: descriptionChanged($port, $oldDescription, $newDescription)") + } + + override fun exposedUrlChanged(port: ForwardedPort, newUrl: String) { + thisLogger().warn("gitpod: exposedUrlChanged($port, $newUrl)") + } + + override fun iconChanged(port: ForwardedPort, oldIcon: Icon?, newIcon: Icon?) { + thisLogger().warn("gitpod: iconChanged($port, $oldIcon, $newIcon)") + } + + override fun nameChanged(port: ForwardedPort, oldName: String?, newName: String?) { + thisLogger().warn("gitpod: nameChanged($port, $oldName, $newName)") + } + + override fun stateChanged(port: ForwardedPort, newState: ClientPortState) { + when (newState) { + is ClientPortState.Assigned -> { + thisLogger().warn("gitpod: Started forwarding host port $hostPort to client port ${newState.clientPort}.") + portsService.setForwardedPort(hostPort, newState.clientPort) + } + is ClientPortState.FailedToAssign -> { + thisLogger().warn("gitpod: Detected that host port $hostPort failed to be assigned to a client port.") + } + else -> { + thisLogger().warn("gitpod: Detected that host port $hostPort is not assigned to any client port.") + } + } + } + + override fun tooltipChanged(port: ForwardedPort, oldTooltip: String?, newTooltip: String?) { + thisLogger().warn("gitpod: tooltipChanged($port, $oldTooltip, $newTooltip)") + } + }) + } catch (error: Error) { + thisLogger().warn("gitpod: ${error.message}") + } } if (!isServed && isForwarded) { - portForwardingManager.removePort(hostPort) + val portListenerDisposable = portToDisposableMap[hostPort] + if (portListenerDisposable != null) { + portListenerDisposable.dispose() + portToDisposableMap.remove(hostPort) + } + perClientPortForwardingManager.getPorts(hostPort).forEach { portToRemove -> + perClientPortForwardingManager.removePort(portToRemove) + } portsService.removeForwardedPort(hostPort) thisLogger().info("gitpod: Stopped forwarding port $hostPort.") } diff --git a/components/ide/jetbrains/backend-plugin/src/main/resources-latest/META-INF/extensions.xml b/components/ide/jetbrains/backend-plugin/src/main/resources-latest/META-INF/extensions.xml index b2ae56126e5d60..3e2f69929e3abf 100644 --- a/components/ide/jetbrains/backend-plugin/src/main/resources-latest/META-INF/extensions.xml +++ b/components/ide/jetbrains/backend-plugin/src/main/resources-latest/META-INF/extensions.xml @@ -7,6 +7,6 @@ - +