[YARN-10607] User environment is unable to prepend PATH when mapreduce.admin.user.env also sets PATH. Contributed by Eric Badger.
(cherry picked from commit c22c77af43
)
This commit is contained in:
parent
bdd22b61c2
commit
d3c7cb7c38
|
@ -1238,6 +1238,15 @@ public class YarnConfiguration extends Configuration {
|
||||||
public static final String NM_ADMIN_USER_ENV = NM_PREFIX + "admin-env";
|
public static final String NM_ADMIN_USER_ENV = NM_PREFIX + "admin-env";
|
||||||
public static final String DEFAULT_NM_ADMIN_USER_ENV = "MALLOC_ARENA_MAX=$MALLOC_ARENA_MAX";
|
public static final String DEFAULT_NM_ADMIN_USER_ENV = "MALLOC_ARENA_MAX=$MALLOC_ARENA_MAX";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PATH components that will be prepended to the user's path.
|
||||||
|
* If this is defined and the user does not define PATH, NM will also
|
||||||
|
* append ":$PATH" to prevent this from eclipsing the PATH defined in
|
||||||
|
* the container. This feature is only available for Linux.
|
||||||
|
* */
|
||||||
|
public static final String NM_ADMIN_FORCE_PATH = NM_PREFIX + "force.path";
|
||||||
|
public static final String DEFAULT_NM_ADMIN_FORCE_PATH = "";
|
||||||
|
|
||||||
/** Environment variables that containers may override rather than use NodeManager's default.*/
|
/** Environment variables that containers may override rather than use NodeManager's default.*/
|
||||||
public static final String NM_ENV_WHITELIST = NM_PREFIX + "env-whitelist";
|
public static final String NM_ENV_WHITELIST = NM_PREFIX + "env-whitelist";
|
||||||
public static final String DEFAULT_NM_ENV_WHITELIST = StringUtils.join(",",
|
public static final String DEFAULT_NM_ENV_WHITELIST = StringUtils.join(",",
|
||||||
|
|
|
@ -1182,6 +1182,17 @@
|
||||||
<value>MALLOC_ARENA_MAX=$MALLOC_ARENA_MAX</value>
|
<value>MALLOC_ARENA_MAX=$MALLOC_ARENA_MAX</value>
|
||||||
</property>
|
</property>
|
||||||
|
|
||||||
|
<property>
|
||||||
|
<description>
|
||||||
|
* PATH components that will be prepended to the user's path.
|
||||||
|
* If this is defined and the user does not define PATH, NM will also
|
||||||
|
* append ":$PATH" to prevent this from eclipsing the PATH defined in
|
||||||
|
* the container. This feature is only available for Linux.
|
||||||
|
</description>
|
||||||
|
<name>yarn.nodemanager.force.path</name>
|
||||||
|
<value></value>
|
||||||
|
</property>
|
||||||
|
|
||||||
<property>
|
<property>
|
||||||
<description>Environment variables that containers may override rather than use NodeManager's default.</description>
|
<description>Environment variables that containers may override rather than use NodeManager's default.</description>
|
||||||
<name>yarn.nodemanager.env-whitelist</name>
|
<name>yarn.nodemanager.env-whitelist</name>
|
||||||
|
|
|
@ -1636,6 +1636,27 @@ public class ContainerLaunch implements Callable<Integer> {
|
||||||
nmVars.addAll(Apps.getEnvVarsFromInputProperty(
|
nmVars.addAll(Apps.getEnvVarsFromInputProperty(
|
||||||
YarnConfiguration.NM_ADMIN_USER_ENV, defEnvStr, conf));
|
YarnConfiguration.NM_ADMIN_USER_ENV, defEnvStr, conf));
|
||||||
|
|
||||||
|
if (!Shell.WINDOWS) {
|
||||||
|
// maybe force path components
|
||||||
|
String forcePath = conf.get(YarnConfiguration.NM_ADMIN_FORCE_PATH,
|
||||||
|
YarnConfiguration.DEFAULT_NM_ADMIN_FORCE_PATH);
|
||||||
|
if (!forcePath.isEmpty()) {
|
||||||
|
String userPath = environment.get(Environment.PATH.name());
|
||||||
|
environment.remove(Environment.PATH.name());
|
||||||
|
if (userPath == null || userPath.isEmpty()) {
|
||||||
|
Apps.addToEnvironment(environment, Environment.PATH.name(),
|
||||||
|
forcePath, File.pathSeparator);
|
||||||
|
Apps.addToEnvironment(environment, Environment.PATH.name(),
|
||||||
|
"$PATH", File.pathSeparator);
|
||||||
|
} else {
|
||||||
|
Apps.addToEnvironment(environment, Environment.PATH.name(),
|
||||||
|
forcePath, File.pathSeparator);
|
||||||
|
Apps.addToEnvironment(environment, Environment.PATH.name(),
|
||||||
|
userPath, File.pathSeparator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Remove Windows check and use this approach on all platforms after
|
// TODO: Remove Windows check and use this approach on all platforms after
|
||||||
// additional testing. See YARN-358.
|
// additional testing. See YARN-358.
|
||||||
if (Shell.WINDOWS) {
|
if (Shell.WINDOWS) {
|
||||||
|
|
|
@ -823,6 +823,69 @@ public class TestContainerLaunch extends BaseContainerManagerTest {
|
||||||
Assert.assertEquals(testVal3, userSetEnv.get(testKey3));
|
Assert.assertEquals(testVal3, userSetEnv.get(testKey3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testNmForcePath() throws Exception {
|
||||||
|
// Valid only for unix
|
||||||
|
assumeNotWindows();
|
||||||
|
ContainerLaunchContext containerLaunchContext =
|
||||||
|
recordFactory.newRecordInstance(ContainerLaunchContext.class);
|
||||||
|
ApplicationId appId = ApplicationId.newInstance(0, 0);
|
||||||
|
ApplicationAttemptId appAttemptId =
|
||||||
|
ApplicationAttemptId.newInstance(appId, 1);
|
||||||
|
ContainerId cId = ContainerId.newContainerId(appAttemptId, 0);
|
||||||
|
Map<String, String> userSetEnv = new HashMap<>();
|
||||||
|
Set<String> nmEnvTrack = new LinkedHashSet<>();
|
||||||
|
containerLaunchContext.setEnvironment(userSetEnv);
|
||||||
|
Container container = mock(Container.class);
|
||||||
|
when(container.getContainerId()).thenReturn(cId);
|
||||||
|
when(container.getLaunchContext()).thenReturn(containerLaunchContext);
|
||||||
|
when(container.getLocalizedResources()).thenReturn(null);
|
||||||
|
Dispatcher dispatcher = mock(Dispatcher.class);
|
||||||
|
EventHandler<Event> eventHandler = new EventHandler<Event>() {
|
||||||
|
public void handle(Event event) {
|
||||||
|
Assert.assertTrue(event instanceof ContainerExitEvent);
|
||||||
|
ContainerExitEvent exitEvent = (ContainerExitEvent) event;
|
||||||
|
Assert.assertEquals(ContainerEventType.CONTAINER_EXITED_WITH_FAILURE,
|
||||||
|
exitEvent.getType());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
when(dispatcher.getEventHandler()).thenReturn(eventHandler);
|
||||||
|
|
||||||
|
String testDir = System.getProperty("test.build.data",
|
||||||
|
"target/test-dir");
|
||||||
|
Path pwd = new Path(testDir);
|
||||||
|
List<Path> appDirs = new ArrayList<>();
|
||||||
|
List<String> userLocalDirs = new ArrayList<>();
|
||||||
|
List<String> containerLogs = new ArrayList<>();
|
||||||
|
Map<Path, List<String>> resources = new HashMap<>();
|
||||||
|
Path nmp = new Path(testDir);
|
||||||
|
|
||||||
|
YarnConfiguration conf = new YarnConfiguration();
|
||||||
|
String forcePath = "./force-path";
|
||||||
|
conf.set("yarn.nodemanager.force.path", forcePath);
|
||||||
|
|
||||||
|
ContainerLaunch launch = new ContainerLaunch(distContext, conf,
|
||||||
|
dispatcher, exec, null, container, dirsHandler, containerManager);
|
||||||
|
launch.sanitizeEnv(userSetEnv, pwd, appDirs, userLocalDirs, containerLogs,
|
||||||
|
resources, nmp, nmEnvTrack);
|
||||||
|
|
||||||
|
Assert.assertTrue(userSetEnv.containsKey(Environment.PATH.name()));
|
||||||
|
Assert.assertEquals(forcePath + ":$PATH",
|
||||||
|
userSetEnv.get(Environment.PATH.name()));
|
||||||
|
|
||||||
|
String userPath = "/usr/bin:/usr/local/bin";
|
||||||
|
userSetEnv.put(Environment.PATH.name(), userPath);
|
||||||
|
containerLaunchContext.setEnvironment(userSetEnv);
|
||||||
|
when(container.getLaunchContext()).thenReturn(containerLaunchContext);
|
||||||
|
|
||||||
|
launch.sanitizeEnv(userSetEnv, pwd, appDirs, userLocalDirs, containerLogs,
|
||||||
|
resources, nmp, nmEnvTrack);
|
||||||
|
|
||||||
|
Assert.assertTrue(userSetEnv.containsKey(Environment.PATH.name()));
|
||||||
|
Assert.assertEquals(forcePath + ":" + userPath,
|
||||||
|
userSetEnv.get(Environment.PATH.name()));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testErrorLogOnContainerExit() throws Exception {
|
public void testErrorLogOnContainerExit() throws Exception {
|
||||||
verifyTailErrorLogOnContainerExit(new Configuration(), "/stderr", false);
|
verifyTailErrorLogOnContainerExit(new Configuration(), "/stderr", false);
|
||||||
|
|
Loading…
Reference in New Issue