Repository: incubator-gobblin
Updated Branches:
  refs/heads/master f71f59d07 -> 7df0878e0


[GOBBLIN-336] Create a class to start the task java child process.

It's not used yet.

Testing:

Add a new unit test to verify the correct
parameters are passed to the java ProcessBuilder.

Manually tested the class. Verified that the child
process is started and console output is
redirected to the parent process's console.

Closes #2209 from HappyRay/create-single-task-
process-launcher


Project: http://git-wip-us.apache.org/repos/asf/incubator-gobblin/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-gobblin/commit/7df0878e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-gobblin/tree/7df0878e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-gobblin/diff/7df0878e

Branch: refs/heads/master
Commit: 7df0878e08932beca5d75814cd76fdca0380af88
Parents: f71f59d
Author: Ray Yang <[email protected]>
Authored: Fri Dec 15 21:36:21 2017 -0800
Committer: Hung Tran <[email protected]>
Committed: Fri Dec 15 21:36:32 2017 -0800

----------------------------------------------------------------------
 .../gobblin/cluster/SingleTaskLauncher.java     | 121 +++++++++++++++++++
 .../gobblin/cluster/SingleTaskLauncherTest.java |  71 +++++++++++
 gobblin-utility/build.gradle                    |   1 +
 .../gobblin/util/GobblinProcessBuilder.java     |  33 +++++
 .../gobblin/util/SystemPropertiesWrapper.java   |  38 ++++++
 .../util/SystemPropertiesWrapperTest.java       |  37 ++++++
 6 files changed, 301 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-gobblin/blob/7df0878e/gobblin-cluster/src/main/java/org/apache/gobblin/cluster/SingleTaskLauncher.java
----------------------------------------------------------------------
diff --git 
a/gobblin-cluster/src/main/java/org/apache/gobblin/cluster/SingleTaskLauncher.java
 
b/gobblin-cluster/src/main/java/org/apache/gobblin/cluster/SingleTaskLauncher.java
new file mode 100644
index 0000000..945b5e5
--- /dev/null
+++ 
b/gobblin-cluster/src/main/java/org/apache/gobblin/cluster/SingleTaskLauncher.java
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.gobblin.cluster;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.gobblin.util.GobblinProcessBuilder;
+import org.apache.gobblin.util.SystemPropertiesWrapper;
+
+import static 
org.apache.gobblin.cluster.SingleTaskRunnerMainOptions.CLUSTER_CONFIG_FILE_PATH;
+import static org.apache.gobblin.cluster.SingleTaskRunnerMainOptions.JOB_ID;
+import static 
org.apache.gobblin.cluster.SingleTaskRunnerMainOptions.WORK_UNIT_FILE_PATH;
+
+
+class SingleTaskLauncher {
+  private static final Logger logger = 
LoggerFactory.getLogger(SingleTaskLauncher.class);
+
+  private final GobblinProcessBuilder processBuilder;
+  private final SystemPropertiesWrapper propertiesWrapper;
+  private final Path clusterConfigFilePath;
+
+  SingleTaskLauncher(final GobblinProcessBuilder processBuilder,
+      final SystemPropertiesWrapper propertiesWrapper, final Path 
clusterConfigFilePath) {
+    this.processBuilder = processBuilder;
+    this.propertiesWrapper = propertiesWrapper;
+    this.clusterConfigFilePath = clusterConfigFilePath;
+  }
+
+  Process launch(final String jobId, final Path workUnitFilePath)
+      throws IOException {
+    final SingleTaskLauncher.CmdBuilder cmdBuilder = this.new 
CmdBuilder(jobId, workUnitFilePath);
+    final List<String> command = cmdBuilder.build();
+    logger.info("Launching a task process. cmd: " + command);
+    final Process taskProcess = this.processBuilder.start(command);
+
+    return taskProcess;
+  }
+
+  private class CmdBuilder {
+    private final String jobId;
+    private final Path workUnitFilePath;
+    private final List<String> cmd = new ArrayList<>();
+
+    private CmdBuilder(final String jobId, final Path workUnitFilePath) {
+      this.jobId = jobId;
+      this.workUnitFilePath = workUnitFilePath;
+    }
+
+    List<String> build() {
+      addJavaBin();
+      addClassPath();
+      addClassName();
+      addOptions();
+      return this.cmd;
+    }
+
+    private void addClassName() {
+      final String runnerClassName = 
SingleTaskRunnerMain.class.getCanonicalName();
+      this.cmd.add(runnerClassName);
+    }
+
+    private void addJavaBin() {
+      final String javaHomeDir = 
SingleTaskLauncher.this.propertiesWrapper.getJavaHome();
+      final Path javaBinPath = Paths.get(javaHomeDir, "bin", "java");
+      this.cmd.add(javaBinPath.toString());
+    }
+
+    private void addClassPath() {
+      this.cmd.add("-cp");
+      final String classPath = 
SingleTaskLauncher.this.propertiesWrapper.getJavaClassPath();
+      this.cmd.add(classPath);
+    }
+
+    private void addOptions() {
+      addClusterConfigPath();
+      addJobId();
+      addWorkUnitPath();
+    }
+
+    private void addClusterConfigPath() {
+      this.cmd.add(formatParam(CLUSTER_CONFIG_FILE_PATH));
+      this.cmd.add(SingleTaskLauncher.this.clusterConfigFilePath.toString());
+    }
+
+    private void addWorkUnitPath() {
+      this.cmd.add(formatParam(WORK_UNIT_FILE_PATH));
+      this.cmd.add(this.workUnitFilePath.toString());
+    }
+
+    private void addJobId() {
+      this.cmd.add(formatParam(JOB_ID));
+      this.cmd.add(this.jobId);
+    }
+
+    private String formatParam(final String param) {
+      return "--" + param;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gobblin/blob/7df0878e/gobblin-cluster/src/test/java/org/apache/gobblin/cluster/SingleTaskLauncherTest.java
----------------------------------------------------------------------
diff --git 
a/gobblin-cluster/src/test/java/org/apache/gobblin/cluster/SingleTaskLauncherTest.java
 
b/gobblin-cluster/src/test/java/org/apache/gobblin/cluster/SingleTaskLauncherTest.java
new file mode 100644
index 0000000..a8a361c
--- /dev/null
+++ 
b/gobblin-cluster/src/test/java/org/apache/gobblin/cluster/SingleTaskLauncherTest.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.gobblin.cluster;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.testng.annotations.Test;
+
+import org.apache.gobblin.util.GobblinProcessBuilder;
+import org.apache.gobblin.util.SystemPropertiesWrapper;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+
+public class SingleTaskLauncherTest {
+
+  private static final String JOB_ID = "1";
+  private static final String JAVAHOME = "/javahome";
+  private static final String TEST_CLASS_PATH = "foo.jar:bar.jar";
+  private static final String WORK_UNIT_PATH = "workUnit.wu";
+  private static final String CLUSTER_CONFIG_CONF_PATH = "clusterConfig.conf";
+
+  @Test
+  public void testLaunch()
+      throws Exception {
+    final SystemPropertiesWrapper propertiesWrapper = 
mock(SystemPropertiesWrapper.class);
+    when(propertiesWrapper.getJavaHome()).thenReturn(JAVAHOME);
+    when(propertiesWrapper.getJavaClassPath()).thenReturn(TEST_CLASS_PATH);
+
+    final GobblinProcessBuilder processBuilder = 
mock(GobblinProcessBuilder.class);
+    final Process mockProcess = mock(Process.class);
+    when(processBuilder.start(any())).thenReturn(mockProcess);
+
+    final Path clusterConfPath = Paths.get(CLUSTER_CONFIG_CONF_PATH);
+    final SingleTaskLauncher launcher =
+        new SingleTaskLauncher(processBuilder, propertiesWrapper, 
clusterConfPath);
+
+    final Path workUnitPath = Paths.get(WORK_UNIT_PATH);
+    final Process process = launcher.launch(JOB_ID, workUnitPath);
+
+    final List<String> expectedInput = new ArrayList<>(Arrays
+        .asList("/javahome/bin/java", "-cp", TEST_CLASS_PATH,
+            "org.apache.gobblin.cluster.SingleTaskRunnerMain", 
"--cluster_config_file_path",
+            CLUSTER_CONFIG_CONF_PATH, "--job_id", JOB_ID, 
"--work_unit_file_path", WORK_UNIT_PATH));
+    verify(processBuilder).start(expectedInput);
+    assertThat(process).isEqualTo(mockProcess);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gobblin/blob/7df0878e/gobblin-utility/build.gradle
----------------------------------------------------------------------
diff --git a/gobblin-utility/build.gradle b/gobblin-utility/build.gradle
index 9d7505b..a8f87bb 100644
--- a/gobblin-utility/build.gradle
+++ b/gobblin-utility/build.gradle
@@ -54,6 +54,7 @@ dependencies {
   testCompile externalDependency.hamcrest
   testCompile externalDependency.testng
   testCompile externalDependency.mockito
+  testCompile externalDependency.assertj
 }
 
 configurations {

http://git-wip-us.apache.org/repos/asf/incubator-gobblin/blob/7df0878e/gobblin-utility/src/main/java/org/apache/gobblin/util/GobblinProcessBuilder.java
----------------------------------------------------------------------
diff --git 
a/gobblin-utility/src/main/java/org/apache/gobblin/util/GobblinProcessBuilder.java
 
b/gobblin-utility/src/main/java/org/apache/gobblin/util/GobblinProcessBuilder.java
new file mode 100644
index 0000000..205fd8b
--- /dev/null
+++ 
b/gobblin-utility/src/main/java/org/apache/gobblin/util/GobblinProcessBuilder.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.gobblin.util;
+
+import java.io.IOException;
+import java.util.List;
+
+
+public class GobblinProcessBuilder {
+  public Process start(final List<String> command)
+      throws IOException {
+    final ProcessBuilder processBuilder = new ProcessBuilder(command);
+    processBuilder.redirectOutput(ProcessBuilder.Redirect.INHERIT);
+    final Process process = processBuilder.start();
+    return process;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gobblin/blob/7df0878e/gobblin-utility/src/main/java/org/apache/gobblin/util/SystemPropertiesWrapper.java
----------------------------------------------------------------------
diff --git 
a/gobblin-utility/src/main/java/org/apache/gobblin/util/SystemPropertiesWrapper.java
 
b/gobblin-utility/src/main/java/org/apache/gobblin/util/SystemPropertiesWrapper.java
new file mode 100644
index 0000000..be70b2e
--- /dev/null
+++ 
b/gobblin-utility/src/main/java/org/apache/gobblin/util/SystemPropertiesWrapper.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.gobblin.util;
+
+public class SystemPropertiesWrapper {
+  private String get(final String name) {
+    return System.getProperty(name);
+  }
+
+  /**
+   * The path to the JRE that is used to run the program which does the 
lookup. It is not
+   * related to JAVA_HOME.
+   * e.g.
+   * /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home/jre
+   */
+  public String getJavaHome() {
+    return get("java.home");
+  }
+
+  public String getJavaClassPath() {
+    return get("java.class.path");
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-gobblin/blob/7df0878e/gobblin-utility/src/test/java/org/apache/gobblin/util/SystemPropertiesWrapperTest.java
----------------------------------------------------------------------
diff --git 
a/gobblin-utility/src/test/java/org/apache/gobblin/util/SystemPropertiesWrapperTest.java
 
b/gobblin-utility/src/test/java/org/apache/gobblin/util/SystemPropertiesWrapperTest.java
new file mode 100644
index 0000000..178520e
--- /dev/null
+++ 
b/gobblin-utility/src/test/java/org/apache/gobblin/util/SystemPropertiesWrapperTest.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.gobblin.util;
+
+import org.testng.annotations.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+
+public class SystemPropertiesWrapperTest {
+
+  @Test
+  public void testGetJavaHome() {
+    final SystemPropertiesWrapper propertiesWrapper = new 
SystemPropertiesWrapper();
+    final String home = propertiesWrapper.getJavaHome();
+    // It's hard to assert where the java JRE home directory is used to launch 
this process.
+    // This test is designed to print out the actual value for debugging and 
demonstration
+    // purposes.
+    System.out.println(home);
+    assertThat(home).isNotEmpty();
+  }
+}

Reply via email to