Skip to content

Commit

Permalink
support unset env feature (#253)
Browse files Browse the repository at this point in the history
* support unset env feature

* finished

* build error

* Apply suggestions from code review

Co-authored-by: Michał Smolarek <[email protected]>

* Fixed removing env

---------

Co-authored-by: Michał Smolarek <[email protected]>
Co-authored-by: Razz4780 <[email protected]>
  • Loading branch information
3 people authored Apr 2, 2024
1 parent b31751b commit 395ad4a
Show file tree
Hide file tree
Showing 12 changed files with 94 additions and 38 deletions.
1 change: 1 addition & 0 deletions changelog.d/+support-unset-feature.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
support unset env feature
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,11 @@ data class IdeMessage(val id: String, val level: NotificationLevel, val text: St

data class Error(val message: String, val severity: String, val causes: List<String>, val help: String, val labels: List<String>, val related: List<String>)

data class MirrordExecution(val environment: MutableMap<String, String>, @SerializedName("patched_path") val patchedPath: String?)
data class MirrordExecution(
val environment: MutableMap<String, String>,
@SerializedName("patched_path") val patchedPath: String?,
@SerializedName("env_to_unset") val envToUnset: List<String>?
)

/**
* Wrapper around Gson for parsing messages from the mirrord binary.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class MirrordExecManager(private val service: MirrordProjectService) {
executable: String?,
product: String,
projectEnvVars: Map<String, String>?
): Pair<Map<String, String>, String?>? {
): MirrordExecution? {
MirrordLogger.logger.debug("MirrordExecManager.start")
val explicitlyEnabled = projectEnvVars?.any { (key, value) -> key == "MIRRORD_ACTIVE" && value == "1" } ?: false
if (!service.enabled && !explicitlyEnabled) {
Expand Down Expand Up @@ -195,7 +195,7 @@ class MirrordExecManager(private val service: MirrordProjectService) {
MirrordLogger.logger.debug("MirrordExecManager.start: executionInfo: $executionInfo")

executionInfo.environment["MIRRORD_IGNORE_DEBUGGER_PORTS"] = "35000-65535"
return Pair(executionInfo.environment, executionInfo.patchedPath)
return executionInfo
}

/**
Expand All @@ -207,7 +207,7 @@ class MirrordExecManager(private val service: MirrordProjectService) {
var wsl: WSLDistribution? = null
var executable: String? = null

fun start(): Pair<Map<String, String>, String?>? {
fun start(): MirrordExecution? {
return try {
manager.start(wsl, executable, product, extraEnvVars)
} catch (e: MirrordError) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,15 @@ class MirrordNpmExecutionListener : ExecutionListener {
service.execManager.wrapper("JS", executionGuard.originEnv).apply {
wsl = wslDistribution
executable = executablePath
}.start()?.let { (newEnv, patchedPath) ->
runSettings.envs = executionGuard.originEnv + newEnv
}.start()?.let { executionInfo ->
var envs = (executionGuard.originEnv + executionInfo.environment)

patchedPath?.let {
executionInfo.envToUnset?.let { envToUnset ->
envs = envs.filterKeys { !envToUnset.contains(it) }
}
runSettings.envs = envs

executionInfo.patchedPath?.let {
executionGuard.originPackageManagerPackageRef = runSettings.packageManagerPackageRef
runSettings.packageManagerPackagePath = it
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,18 @@ class GolandRunConfigurationExtension : GoRunConfigurationExtension() {

service.execManager.wrapper("goland", configuration.getCustomEnvironment()).apply {
this.wsl = wsl
}.start()?.first?.let { env ->
for (entry in env.entries.iterator()) {
}.start()?.let { executionInfo ->

for (entry in executionInfo.environment.entries.iterator()) {
cmdLine.addEnvironmentVariable(entry.key, entry.value)
}
cmdLine.addEnvironmentVariable("MIRRORD_SKIP_PROCESSES", "dlv;debugserver;go")

executionInfo.envToUnset?.let { keys ->
for (key in keys.iterator()) {
cmdLine.removeEnvironmentVariable(key)
}
}
}
}
super.patchCommandLine(configuration, runnerSettings, cmdLine, runnerId, state, commandLineType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,19 +72,27 @@ class IdeaRunConfigurationExtension : RunConfigurationExtension() {
params.env
}

val mirrordEnv = service.execManager.wrapper("idea", extraEnv).apply {
service.execManager.wrapper("idea", extraEnv).apply {
this.wsl = wsl
}.start()?.first?.let { it + mapOf(Pair("MIRRORD_DETECT_DEBUGGER_PORT", "javaagent")) }.orEmpty()

params.env = params.env + mirrordEnv
runningProcessEnvs[configuration.project] = params.env.toMap()

// Gradle support (and external system configuration)
if (configuration is ExternalSystemRunConfiguration) {
runningProcessEnvs[configuration.project] = configuration.settings.env.toMap()
configuration.settings.env = configuration.settings.env + mirrordEnv
}.start()?.let { executionInfo ->
val mirrordEnv = executionInfo.environment + mapOf(Pair("MIRRORD_DETECT_DEBUGGER_PORT", "javaagent"))
params.env = params.env + mirrordEnv
executionInfo.envToUnset?.let { keys ->
params.env = params.env.filterKeys { !keys.contains(it) }
}
runningProcessEnvs[configuration.project] = params.env.toMap()

// Gradle support (and external system configuration)
if (configuration is ExternalSystemRunConfiguration) {
runningProcessEnvs[configuration.project] = configuration.settings.env.toMap()
var env = configuration.settings.env + mirrordEnv
executionInfo.envToUnset?.let { keys ->
env = env.filterKeys { !keys.contains(it) }
}
configuration.settings.env = configuration.settings.env + mirrordEnv
}
MirrordLogger.logger.debug("setting env and finishing")
}
MirrordLogger.logger.debug("setting env and finishing")
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,15 @@ class NodeRunConfigurationExtension : AbstractNodeRunConfigurationExtension() {

service.execManager.wrapper("nodejs", extraEnvVars).apply {
this.wsl = wsl
}.start()?.first?.forEach { (key, value) ->
targetRun.commandLineBuilder.addEnvironmentVariable(key, value)
}.start()?.let { executionInfo ->
executionInfo.environment.forEach { (key, value) ->
targetRun.commandLineBuilder.addEnvironmentVariable(key, value)
}
executionInfo.envToUnset?.let { keys ->
for (key in keys.iterator()) {
targetRun.commandLineBuilder.removeEnvironmentVariable(key)
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,15 @@ class PythonCommandLineProvider : PythonCommandLineTargetEnvironmentProvider {

service.execManager.wrapper("pycharm", runParams.getEnvs()).apply {
this.wsl = wsl
}.start()?.first?.let { env ->
for (entry in env.entries.iterator()) {
}.start()?.let { executionInfo ->
for (entry in executionInfo.environment.entries.iterator()) {
pythonExecution.addEnvironmentVariable(entry.key, entry.value)
}

for (key in executionInfo.envToUnset.orEmpty()) {
pythonExecution.envs.remove(key)
}

pythonExecution.addEnvironmentVariable("MIRRORD_DETECT_DEBUGGER_PORT", "pydevd")
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,15 @@ class PythonRunConfigurationExtension : PythonRunConfigurationExtension() {

service.execManager.wrapper("pycharm", currentEnv).apply {
this.wsl = wsl
}.start()?.first?.let { env ->
for (entry in env.entries.iterator()) {
}.start()?.let { executionInfo ->
for (entry in executionInfo.environment.entries.iterator()) {
currentEnv[entry.key] = entry.value
}
executionInfo.envToUnset?.let { envToUnset ->
for (key in envToUnset.iterator()) {
currentEnv.remove(key)
}
}
}

currentEnv["MIRRORD_DETECT_DEBUGGER_PORT"] = "pydevd"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,14 @@ class RiderPatchCommandLineExtension : PatchCommandLineExtension {

service.execManager.wrapper("rider", commandLine.environment).apply {
this.wsl = wsl
}.start()?.first?.let { env ->
for (entry in env.entries.iterator()) {
}.start()?.let { executionInfo ->
for (entry in executionInfo.environment.entries.iterator()) {
commandLine.withEnvironment(entry.key, entry.value)
}

for (key in executionInfo.envToUnset.orEmpty()) {
commandLine.environment.remove(key)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import com.metalbear.mirrord.MirrordError
import com.metalbear.mirrord.MirrordProjectService
import org.jetbrains.plugins.ruby.ruby.run.configuration.AbstractRubyRunConfiguration
import org.jetbrains.plugins.ruby.ruby.run.configuration.RubyRunConfigurationExtension
import kotlin.io.path.*
import kotlin.io.path.createTempFile
import kotlin.io.path.pathString
import kotlin.io.path.writeText

class RubyMineRunConfigurationExtension : RubyRunConfigurationExtension() {

Expand Down Expand Up @@ -48,15 +50,18 @@ class RubyMineRunConfigurationExtension : RubyRunConfigurationExtension() {
if (isMac) {
this.executable = cmdLine.exePath
}
}.start()?.let { (mirrordEnv, patched) ->
}.start()?.let { executionInfo ->
// this is the env the Ruby app and the layer see, at least with RVM.
cmdLine.withEnvironment(mirrordEnv)
cmdLine.withEnvironment(executionInfo.environment)

if (isMac && patched !== null) {
cmdLine.exePath = patched
for (key in executionInfo.envToUnset.orEmpty()) {
cmdLine.environment.remove(key)
}

if (isMac) {
executionInfo.patchedPath?.let {
cmdLine.exePath = it
}
// TODO: would be nice to have a more robust RVM detection mechanism.
val isRvm = cmdLine.exePath.contains("/.rvm/rubies/")
if (isRvm) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ class TomcatExecutionListener : ExecutionListener {
MirrordLogger.logger.debug("processStartScheduled tomcat")
getConfig(env)?.let { config ->
MirrordLogger.logger.debug("processStartScheduled: got tomcat config")
val envVars = config.envVariables
var envVars = config.envVariables
val envVarsMap = envVars.map { it.NAME to it.VALUE }.toMap()

val service = env.project.service<MirrordProjectService>()
Expand Down Expand Up @@ -168,19 +168,24 @@ class TomcatExecutionListener : ExecutionListener {
service.execManager.wrapper("idea", envVarsMap).apply {
this.wsl = wsl
this.executable = scriptAndArgs?.command
}.start()?.let { (env, patchedPath) ->
MirrordLogger.logger.debug("got execution info for tomcat - env: $env, patchedPath: $patchedPath")
}.start()?.let { executionInfo ->
// `MIRRORD_IGNORE_DEBUGGER_PORTS` should allow clean shutdown of the app
// even if `outgoing` feature is enabled.
val mirrordEnv = env + mapOf(Pair("MIRRORD_DETECT_DEBUGGER_PORT", "javaagent"), Pair("MIRRORD_IGNORE_DEBUGGER_PORTS", getTomcatServerPort()))
val mirrordEnv = executionInfo.environment + mapOf(Pair("MIRRORD_DETECT_DEBUGGER_PORT", "javaagent"), Pair("MIRRORD_IGNORE_DEBUGGER_PORTS", getTomcatServerPort()))

val savedData = SavedConfigData(envVars.toList(), null)
envVars.addAll(mirrordEnv.map { (k, v) -> EnvironmentVariable(k, v, false) })

executionInfo.envToUnset?.let { envToUnset ->
envVars = envVars.filter {
!envToUnset.contains(it.name)
}
}
config.setEnvironmentVariables(envVars)

if (SystemInfo.isMac) {
MirrordLogger.logger.debug("isMac, patching SIP.")
patchedPath?.let {
executionInfo.patchedPath?.let {
MirrordLogger.logger.debug("patchedPath is not null: $it, meaning original was SIP")
savedData.scriptInfo = startupInfo
if (config.startupInfo.USE_DEFAULT) {
Expand Down

0 comments on commit 395ad4a

Please sign in to comment.