YARN-8805. Automatically convert the launch command to the exec form when using entrypoint support
This commit is contained in:
parent
b4aa24d3c5
commit
fa7a0b269a
|
@ -47,9 +47,12 @@ import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import static org.apache.hadoop.yarn.service.api.ServiceApiConstants.COMPONENT_ID;
|
import static org.apache.hadoop.yarn.service.api.ServiceApiConstants.COMPONENT_ID;
|
||||||
|
@ -149,6 +152,20 @@ public class ProviderUtils implements YarnServiceConstants {
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String replaceSpacesWithDelimiter(String content,
|
||||||
|
String delimiter) {
|
||||||
|
List<String> parts = new ArrayList<String>();
|
||||||
|
Matcher m = Pattern.compile("([^\"]\\S*|\".+?\")\\s*").matcher(content);
|
||||||
|
while (m.find()) {
|
||||||
|
String part = m.group(1);
|
||||||
|
if(part.startsWith("\"") && part.endsWith("\"")) {
|
||||||
|
part = part.replaceAll("^\"|\"$", "");
|
||||||
|
}
|
||||||
|
parts.add(part);
|
||||||
|
}
|
||||||
|
return String.join(delimiter, parts);
|
||||||
|
}
|
||||||
|
|
||||||
// configs will be substituted by corresponding env in tokenMap
|
// configs will be substituted by corresponding env in tokenMap
|
||||||
public static void substituteMapWithTokens(Map<String, String> configs,
|
public static void substituteMapWithTokens(Map<String, String> configs,
|
||||||
Map<String, String> tokenMap) {
|
Map<String, String> tokenMap) {
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.apache.hadoop.yarn.service.provider.ProviderUtils;
|
||||||
import org.apache.hadoop.yarn.api.records.Container;
|
import org.apache.hadoop.yarn.api.records.Container;
|
||||||
import org.apache.hadoop.yarn.service.api.records.Service;
|
import org.apache.hadoop.yarn.service.api.records.Service;
|
||||||
import org.apache.hadoop.yarn.service.utils.SliderFileSystem;
|
import org.apache.hadoop.yarn.service.utils.SliderFileSystem;
|
||||||
|
|
||||||
import org.apache.hadoop.yarn.service.containerlaunch.AbstractLauncher;
|
import org.apache.hadoop.yarn.service.containerlaunch.AbstractLauncher;
|
||||||
import org.apache.hadoop.yarn.service.containerlaunch.CommandLineBuilder;
|
import org.apache.hadoop.yarn.service.containerlaunch.CommandLineBuilder;
|
||||||
import org.apache.hadoop.yarn.service.containerlaunch.ContainerLaunchService;
|
import org.apache.hadoop.yarn.service.containerlaunch.ContainerLaunchService;
|
||||||
|
@ -84,6 +85,11 @@ public class DockerProviderService extends AbstractProviderService
|
||||||
if (useEntryPoint) {
|
if (useEntryPoint) {
|
||||||
String launchCommand = compLaunchContext.getLaunchCommand();
|
String launchCommand = compLaunchContext.getLaunchCommand();
|
||||||
if (!StringUtils.isEmpty(launchCommand)) {
|
if (!StringUtils.isEmpty(launchCommand)) {
|
||||||
|
if(launchCommand.contains(" ")) {
|
||||||
|
// convert space delimiter command to exec format
|
||||||
|
launchCommand = ProviderUtils
|
||||||
|
.replaceSpacesWithDelimiter(launchCommand, ",");
|
||||||
|
}
|
||||||
launcher.addCommand(launchCommand);
|
launcher.addCommand(launchCommand);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -82,7 +82,7 @@ public class TestAbstractProviderService {
|
||||||
Component component = serviceContext.scheduler.getAllComponents().entrySet()
|
Component component = serviceContext.scheduler.getAllComponents().entrySet()
|
||||||
.iterator().next().getValue();
|
.iterator().next().getValue();
|
||||||
ContainerLaunchService.ComponentLaunchContext clc =
|
ContainerLaunchService.ComponentLaunchContext clc =
|
||||||
createEntryPointCLCFor(testService, component);
|
createEntryPointCLCFor(testService, component, "sleep,9000");
|
||||||
|
|
||||||
ComponentInstance instance = component.getAllComponentInstances().iterator()
|
ComponentInstance instance = component.getAllComponentInstances().iterator()
|
||||||
.next();
|
.next();
|
||||||
|
@ -95,13 +95,32 @@ public class TestAbstractProviderService {
|
||||||
launcher.getCommands());
|
launcher.getCommands());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuildContainerLaunchCommandWithSpace() throws Exception {
|
||||||
|
AbstractProviderService providerService = new DockerProviderService();
|
||||||
|
Component component = serviceContext.scheduler.getAllComponents().entrySet()
|
||||||
|
.iterator().next().getValue();
|
||||||
|
ContainerLaunchService.ComponentLaunchContext clc =
|
||||||
|
createEntryPointCLCFor(testService, component, "ls -l \" space\"");
|
||||||
|
|
||||||
|
ComponentInstance instance = component.getAllComponentInstances().iterator()
|
||||||
|
.next();
|
||||||
|
Container container = mock(Container.class);
|
||||||
|
providerService.buildContainerLaunchCommand(launcher, testService, instance,
|
||||||
|
rule.getFs(), serviceContext.scheduler.getConfig(), container, clc,
|
||||||
|
null);
|
||||||
|
|
||||||
|
Assert.assertEquals("commands don't match.",
|
||||||
|
Lists.newArrayList("ls,-l, space"), launcher.getCommands());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBuildContainerLaunchContext() throws Exception {
|
public void testBuildContainerLaunchContext() throws Exception {
|
||||||
AbstractProviderService providerService = new DockerProviderService();
|
AbstractProviderService providerService = new DockerProviderService();
|
||||||
Component component = serviceContext.scheduler.getAllComponents().entrySet()
|
Component component = serviceContext.scheduler.getAllComponents().entrySet()
|
||||||
.iterator().next().getValue();
|
.iterator().next().getValue();
|
||||||
ContainerLaunchService.ComponentLaunchContext clc =
|
ContainerLaunchService.ComponentLaunchContext clc =
|
||||||
createEntryPointCLCFor(testService, component);
|
createEntryPointCLCFor(testService, component, "sleep,9000");
|
||||||
|
|
||||||
ComponentInstance instance = component.getAllComponentInstances().iterator()
|
ComponentInstance instance = component.getAllComponentInstances().iterator()
|
||||||
.next();
|
.next();
|
||||||
|
@ -118,8 +137,8 @@ public class TestAbstractProviderService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ContainerLaunchService.ComponentLaunchContext
|
private static ContainerLaunchService.ComponentLaunchContext
|
||||||
createEntryPointCLCFor(Service service, Component component) {
|
createEntryPointCLCFor(Service service, Component component,
|
||||||
String launchCmd = "sleep,9000";
|
String launchCmd) {
|
||||||
Artifact artifact = new Artifact();
|
Artifact artifact = new Artifact();
|
||||||
artifact.setType(Artifact.TypeEnum.DOCKER);
|
artifact.setType(Artifact.TypeEnum.DOCKER);
|
||||||
artifact.setId("example");
|
artifact.setId("example");
|
||||||
|
|
|
@ -168,4 +168,13 @@ public class TestProviderUtils {
|
||||||
Assert.assertEquals(resolved.getResolvedRsrcPaths().get("destFile1"),
|
Assert.assertEquals(resolved.getResolvedRsrcPaths().get("destFile1"),
|
||||||
"destFile1");
|
"destFile1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReplaceSpacesWithDelimiter() {
|
||||||
|
String command = "ls -l \" space\"";
|
||||||
|
String expected = "ls,-l, space";
|
||||||
|
String actual = ProviderUtils.replaceSpacesWithDelimiter(command, ",");
|
||||||
|
Assert.assertEquals("replaceSpaceWithDelimiter produces unexpected result.",
|
||||||
|
expected, actual);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue