Skip to content

Commit 183fded

Browse files
authored
Credentials added as environment variables in Run Command Tool (#2693)
* Credentials added as environment variables in Run Command Tool * duplication removed * Custom Run Profile added * Tests changed, tool deleted * Extension function for connection settings, mock region and credential identifier added * test changed, deleted unwanted code from run profile * windows test changed * unit test changed for windows * test changed
1 parent 92bde87 commit 183fded

File tree

6 files changed

+221
-41
lines changed

6 files changed

+221
-41
lines changed

jetbrains-core/src/software/aws/toolkits/jetbrains/core/credentials/ConnectionSettings.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,19 @@
33

44
package software.aws.toolkits.jetbrains.core.credentials
55

6+
import com.intellij.openapi.project.Project
67
import software.aws.toolkits.core.credentials.ToolkitCredentialsProvider
78
import software.aws.toolkits.core.region.AwsRegion
89

910
data class ConnectionSettings(val credentials: ToolkitCredentialsProvider, val region: AwsRegion)
1011

1112
val ConnectionSettings.shortName get() = "${credentials.shortName}@${region.id}"
13+
14+
fun ConnectionSettings.toEnvironmentVariables(): Map<String, String> = region.toEnvironmentVariables() +
15+
credentials.resolveCredentials().toEnvironmentVariables()
16+
17+
fun <T> Project.withAwsConnection(block: (ConnectionSettings) -> T): T {
18+
val connectionSettings = AwsConnectionManager.getInstance(this).connectionSettings()
19+
?: throw IllegalStateException("Connection settings are not configured")
20+
return block(connectionSettings)
21+
}

jetbrains-core/src/software/aws/toolkits/jetbrains/services/ecs/ContainerActions.kt

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ import software.amazon.awssdk.services.ecs.model.LogDriver
1818
import software.amazon.awssdk.services.ecs.model.Service
1919
import software.aws.toolkits.jetbrains.AwsToolkit
2020
import software.aws.toolkits.jetbrains.core.awsClient
21-
import software.aws.toolkits.jetbrains.core.credentials.AwsConnectionManager
22-
import software.aws.toolkits.jetbrains.core.credentials.toEnvironmentVariables
21+
import software.aws.toolkits.jetbrains.core.credentials.withAwsConnection
2322
import software.aws.toolkits.jetbrains.core.explorer.actions.SingleExplorerNodeActionGroup
2423
import software.aws.toolkits.jetbrains.core.getResource
2524
import software.aws.toolkits.jetbrains.core.getResourceNow
@@ -143,7 +142,9 @@ class ExecuteCommandAction(
143142
if (EcsExecUtils.ensureServiceIsInStableState(project, container.service)) {
144143
SessionManagerPluginInstallationVerification.requiresSessionManager(project) {
145144
runInEdt {
146-
RunCommandDialog(project, container).show()
145+
project.withAwsConnection {
146+
RunCommandDialog(project, container, it).show()
147+
}
147148
}
148149
}
149150
} else {
@@ -166,12 +167,9 @@ class ExecuteCommandInShellAction(
166167
coroutineScope.launch {
167168
if (EcsExecUtils.ensureServiceIsInStableState(project, container.service)) {
168169
SessionManagerPluginInstallationVerification.requiresSessionManager(project) {
169-
val connectionSettings = AwsConnectionManager.getInstance(project).connectionSettings()
170-
if (connectionSettings != null) {
171-
val environmentVariables = connectionSettings.region.toEnvironmentVariables() +
172-
connectionSettings.credentials.resolveCredentials().toEnvironmentVariables()
173-
runInEdt {
174-
OpenShellInContainerDialog(project, container, environmentVariables).show()
170+
runInEdt {
171+
project.withAwsConnection {
172+
OpenShellInContainerDialog(project, container, it).show()
175173
}
176174
}
177175
}

jetbrains-core/src/software/aws/toolkits/jetbrains/services/ecs/exec/OpenShellInContainerDialog.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import org.jetbrains.plugins.terminal.TerminalTabState
1717
import org.jetbrains.plugins.terminal.TerminalView
1818
import org.jetbrains.plugins.terminal.cloud.CloudTerminalProcess
1919
import org.jetbrains.plugins.terminal.cloud.CloudTerminalRunner
20+
import software.aws.toolkits.jetbrains.core.credentials.ConnectionSettings
21+
import software.aws.toolkits.jetbrains.core.credentials.toEnvironmentVariables
2022
import software.aws.toolkits.jetbrains.core.executables.ExecutableInstance
2123
import software.aws.toolkits.jetbrains.core.executables.ExecutableManager
2224
import software.aws.toolkits.jetbrains.core.executables.getExecutable
@@ -35,7 +37,7 @@ import javax.swing.JComponent
3537
class OpenShellInContainerDialog(
3638
private val project: Project,
3739
private val container: ContainerDetails,
38-
private val environmentVariables: Map<String, String>
40+
private val connectionSettings: ConnectionSettings
3941
) : DialogWrapper(project) {
4042
private val coroutineScope = ApplicationThreadPoolScope("OpenShellInContainerDialog")
4143
private val tasks = ResourceSelector
@@ -126,7 +128,7 @@ class OpenShellInContainerDialog(
126128
private fun constructExecCommand(executable: ExecutableInstance.Executable): PtyProcess {
127129
val task = tasks.selected() ?: throw IllegalStateException("No tasks selected")
128130
val commandLine = executable.getCommandLine().execCommand(
129-
environmentVariables,
131+
connectionSettings.toEnvironmentVariables(),
130132
container.service.clusterArn(),
131133
task,
132134
('"' + shell + '"'),

jetbrains-core/src/software/aws/toolkits/jetbrains/services/ecs/exec/RunCommandDialog.kt

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,18 @@ package software.aws.toolkits.jetbrains.services.ecs.exec
55

66
import com.intellij.execution.executors.DefaultRunExecutor
77
import com.intellij.execution.runners.ExecutionEnvironmentBuilder
8-
import com.intellij.openapi.actionSystem.impl.SimpleDataContext
98
import com.intellij.openapi.application.ModalityState
109
import com.intellij.openapi.project.Project
1110
import com.intellij.openapi.ui.DialogWrapper
12-
import com.intellij.tools.Tool
13-
import com.intellij.tools.ToolRunProfile
1411
import com.intellij.ui.CollectionComboBoxModel
1512
import com.intellij.ui.components.JBTextField
1613
import com.intellij.ui.layout.GrowPolicy
1714
import com.intellij.ui.layout.applyToComponent
1815
import com.intellij.ui.layout.panel
1916
import kotlinx.coroutines.launch
2017
import kotlinx.coroutines.withContext
18+
import software.aws.toolkits.jetbrains.core.credentials.ConnectionSettings
19+
import software.aws.toolkits.jetbrains.core.credentials.toEnvironmentVariables
2120
import software.aws.toolkits.jetbrains.services.ecs.ContainerDetails
2221
import software.aws.toolkits.jetbrains.services.ecs.resources.EcsResources
2322
import software.aws.toolkits.jetbrains.ui.ResourceSelector
@@ -27,12 +26,11 @@ import software.aws.toolkits.resources.message
2726
import software.aws.toolkits.telemetry.EcsExecuteCommandType
2827
import software.aws.toolkits.telemetry.EcsTelemetry
2928
import software.aws.toolkits.telemetry.Result
30-
import java.nio.file.Path
3129
import javax.swing.JComponent
3230
import javax.swing.JTextField
3331
import javax.swing.plaf.basic.BasicComboBoxEditor
3432

35-
class RunCommandDialog(private val project: Project, private val container: ContainerDetails) :
33+
class RunCommandDialog(private val project: Project, private val container: ContainerDetails, private val connectionSettings: ConnectionSettings) :
3634
DialogWrapper(project) {
3735
private val coroutineScope = ApplicationThreadPoolScope("RunCommandDialog")
3836
private val tasks = ResourceSelector
@@ -122,14 +120,15 @@ class RunCommandDialog(private val project: Project, private val container: Cont
122120
private suspend fun runCommand() {
123121
try {
124122
val awsCliPath = AwsCliExecutable().resolve() ?: throw IllegalStateException(message("executableCommon.missing_executable", "AWS CLI"))
125-
val execCommand = buildExecCommandConfiguration(('"' + command + '"'), awsCliPath)
126123
val environment = ExecutionEnvironmentBuilder
127124
.create(
128125
project,
129126
DefaultRunExecutor.getRunExecutorInstance(),
130-
ToolRunProfile(
131-
execCommand,
132-
SimpleDataContext.getProjectContext(project)
127+
RunCommandRunProfile(
128+
connectionSettings.toEnvironmentVariables(),
129+
constructExecCommandParameters(('"' + command + '"')),
130+
container.containerDefinition.name(),
131+
awsCliPath.toAbsolutePath().toString()
133132
)
134133
)
135134
.build()
@@ -144,16 +143,6 @@ class RunCommandDialog(private val project: Project, private val container: Cont
144143
}
145144
}
146145

147-
fun buildExecCommandConfiguration(commandToExecute: String, path: Path): Tool {
148-
val execCommand = Tool()
149-
execCommand.isShowConsoleOnStdOut = true
150-
execCommand.isUseConsole = true
151-
execCommand.parameters = constructExecCommandParameters(commandToExecute)
152-
execCommand.name = container.containerDefinition.name()
153-
execCommand.program = path.toAbsolutePath().toString()
154-
return execCommand
155-
}
156-
157146
companion object {
158147
val commandsEnteredPreviously = mutableSetOf<String>()
159148
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package software.aws.toolkits.jetbrains.services.ecs.exec
5+
6+
import com.intellij.execution.ExecutionResult
7+
import com.intellij.execution.Executor
8+
import com.intellij.execution.configurations.CommandLineState
9+
import com.intellij.execution.configurations.GeneralCommandLine
10+
import com.intellij.execution.configurations.RunProfile
11+
import com.intellij.execution.configurations.RunProfileState
12+
import com.intellij.execution.filters.TextConsoleBuilderFactory
13+
import com.intellij.execution.process.ColoredProcessHandler
14+
import com.intellij.execution.process.ProcessAdapter
15+
import com.intellij.execution.process.ProcessEvent
16+
import com.intellij.execution.process.ProcessHandler
17+
import com.intellij.execution.process.ProcessOutputTypes
18+
import com.intellij.execution.process.ProcessTerminatedListener
19+
import com.intellij.execution.runners.ExecutionEnvironment
20+
import com.intellij.execution.runners.ProgramRunner
21+
import com.intellij.execution.ui.RunContentManager
22+
import com.intellij.openapi.project.Project
23+
import com.intellij.openapi.util.Key
24+
import javax.swing.Icon
25+
26+
class RunCommandRunProfile(
27+
private val credentials: Map<String, String>,
28+
private val parameters: String?,
29+
private val containerName: String,
30+
private val path: String
31+
) : RunProfile {
32+
override fun getState(executor: Executor, environment: ExecutionEnvironment): RunProfileState? {
33+
val cmdLine = getCommandLine()
34+
val project = environment.project
35+
if (cmdLine == null) {
36+
return null
37+
}
38+
val commandLineState = CmdLineState(environment, cmdLine, project)
39+
val builder = TextConsoleBuilderFactory.getInstance().createBuilder(project)
40+
commandLineState.consoleBuilder = builder
41+
return commandLineState
42+
}
43+
44+
override fun getName(): String = containerName
45+
46+
override fun getIcon(): Icon? = null
47+
48+
fun getCommandLine(): GeneralCommandLine? {
49+
val commandLine = GeneralCommandLine()
50+
commandLine.parametersList.addParametersString(parameters)
51+
commandLine.exePath = path
52+
commandLine.withEnvironment(credentials)
53+
return commandLine
54+
}
55+
}
56+
57+
class CmdLineState(
58+
environment: ExecutionEnvironment,
59+
private val cmdLine: GeneralCommandLine,
60+
private val project: Project,
61+
) : CommandLineState(environment) {
62+
override fun startProcess(): ProcessHandler {
63+
val processHandler = ColoredProcessHandler(cmdLine)
64+
ProcessTerminatedListener.attach(processHandler)
65+
return processHandler
66+
}
67+
68+
override fun execute(executor: Executor, runner: ProgramRunner<*>): ExecutionResult {
69+
val result = super.execute(executor, runner)
70+
val processHandler = result.processHandler
71+
processHandler?.addProcessListener(object : ProcessAdapter() {
72+
override fun onTextAvailable(event: ProcessEvent, outputType: Key<*>) {
73+
if (outputType === ProcessOutputTypes.STDOUT ||
74+
outputType === ProcessOutputTypes.STDERR
75+
) {
76+
RunContentManager.getInstance(project).toFrontRunContent(executor, processHandler)
77+
}
78+
}
79+
})
80+
return result
81+
}
82+
}

0 commit comments

Comments
 (0)