From 13e012c6d374b532af509ae8a34e15183b0646ec Mon Sep 17 00:00:00 2001
From: Janne Valkealahti <janne.valkealahti@gmail.com>
Date: Mon, 21 Jun 2021 10:33:27 +0100
Subject: [PATCH] Add env inherit options for JavaCommandBuilder (#206)

- Bring back removed use of env inherit/retain options
- Fixes #205
---
 .../spi/local/JavaCommandBuilder.java         | 31 +++++++++++++++++++
 .../JavaExecutionCommandBuilderTests.java     | 25 +++++++++++++++
 2 files changed, 56 insertions(+)

diff --git a/spring-cloud-deployer-local/src/main/java/org/springframework/cloud/deployer/spi/local/JavaCommandBuilder.java b/spring-cloud-deployer-local/src/main/java/org/springframework/cloud/deployer/spi/local/JavaCommandBuilder.java
index 626e8c6..a6c609d 100644
--- a/spring-cloud-deployer-local/src/main/java/org/springframework/cloud/deployer/spi/local/JavaCommandBuilder.java
+++ b/spring-cloud-deployer-local/src/main/java/org/springframework/cloud/deployer/spi/local/JavaCommandBuilder.java
@@ -21,10 +21,13 @@ import java.net.Inet4Address;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Optional;
 import java.util.concurrent.ThreadLocalRandom;
+import java.util.regex.Pattern;
 import java.util.stream.Stream;
 
 import org.slf4j.Logger;
@@ -91,11 +94,39 @@ public class JavaCommandBuilder implements CommandBuilder {
 
 		ProcessBuilder builder = new ProcessBuilder(AbstractLocalDeployerSupport.windowsSupport(commands.toArray(new String[0])));
 
+		// retain before we put in app related variables.
+		retainEnvVars(builder.environment(), localDeployerProperties);
 		builder.environment().putAll(appInstanceEnv);
 
 		return builder;
 	}
 
+	/**
+	 * Retain the environment variable strings in the provided set indicated by
+	 * {@link LocalDeployerProperties#getEnvVarsToInherit}.
+	 * This assumes that the provided set can be modified.
+	 *
+	 * @param vars set of environment variable strings
+	 * @param localDeployerProperties local deployer properties
+	 */
+	protected void retainEnvVars(Map<String, String> vars, LocalDeployerProperties localDeployerProperties) {
+		List<String> patterns = new ArrayList<>(Arrays.asList(localDeployerProperties.getEnvVarsToInherit()));
+		for (Iterator<Entry<String, String>> iterator = vars.entrySet().iterator(); iterator.hasNext();) {
+			Entry<String, String> entry = iterator.next();
+			String var = entry.getKey();
+			boolean retain = false;
+			for (String pattern : patterns) {
+				if (Pattern.matches(pattern, var)) {
+					retain = true;
+					break;
+				}
+			}
+			if (!retain) {
+				iterator.remove();
+			}
+		}
+	}
+
 	protected void addJavaOptions(List<String> commands, Map<String, String> deploymentProperties,
 			LocalDeployerProperties localDeployerProperties) {
 		String memory = null;
diff --git a/spring-cloud-deployer-local/src/test/java/org/springframework/cloud/deployer/spi/local/JavaExecutionCommandBuilderTests.java b/spring-cloud-deployer-local/src/test/java/org/springframework/cloud/deployer/spi/local/JavaExecutionCommandBuilderTests.java
index 2323ccc..68d31df 100644
--- a/spring-cloud-deployer-local/src/test/java/org/springframework/cloud/deployer/spi/local/JavaExecutionCommandBuilderTests.java
+++ b/spring-cloud-deployer-local/src/test/java/org/springframework/cloud/deployer/spi/local/JavaExecutionCommandBuilderTests.java
@@ -23,6 +23,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.stream.Collectors;
 
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
@@ -208,6 +209,30 @@ public class JavaExecutionCommandBuilderTests {
 
 	}
 
+	@Test
+	public void testRetainEnv() {
+		LocalDeployerProperties properties1 = new LocalDeployerProperties();
+		LocalAppDeployer deployer1 = new LocalAppDeployer(properties1);
+		AppDefinition definition1 = new AppDefinition("foo", null);
+		AppDeploymentRequest request1 = new AppDeploymentRequest(definition1, testResource(), deploymentProperties);
+		ProcessBuilder builder1 = deployer1.buildProcessBuilder(request1, definition1.getProperties(), Optional.of(1), "foo");
+		List<String> env1 = builder1.environment().keySet().stream().map(String::toLowerCase).collect(Collectors.toList());
+
+		LocalDeployerProperties properties2 = new LocalDeployerProperties();
+		properties2.setEnvVarsToInherit(new String[0]);
+		LocalAppDeployer deployer2 = new LocalAppDeployer(properties2);
+		AppDefinition definition2 = new AppDefinition("foo", null);
+		AppDeploymentRequest request2 = new AppDeploymentRequest(definition2, testResource(), deploymentProperties);
+		ProcessBuilder builder2 = deployer2.buildProcessBuilder(request2, definition2.getProperties(), Optional.of(1), "foo");
+		List<String> env2 = builder2.environment().keySet().stream().map(String::toLowerCase).collect(Collectors.toList());
+
+		if (env1.contains("path")) {
+			// path should be there, and it was check that something were removed
+			assertThat(builder1.environment().keySet().size()).isGreaterThan(builder2.environment().keySet().size());
+		}
+		assertThat(env2).doesNotContain("path");
+	}
+
 	protected Resource testResource() {
 		return new ClassPathResource("testResource.txt");
 	}
-- 
GitLab