OOZIE-3526 Global job-xml not being overwritten by job-xml specified for an action (mgogineni via rohini)
diff --git a/core/src/main/java/org/apache/oozie/workflow/lite/LiteWorkflowAppParser.java b/core/src/main/java/org/apache/oozie/workflow/lite/LiteWorkflowAppParser.java
index ae0cc76..1f121c5 100644
--- a/core/src/main/java/org/apache/oozie/workflow/lite/LiteWorkflowAppParser.java
+++ b/core/src/main/java/org/apache/oozie/workflow/lite/LiteWorkflowAppParser.java
@@ -532,6 +532,7 @@
@SuppressWarnings("unchecked")
List<Element> actionJobXmls = actionElement.getChildren(JOB_XML, actionNs);
if (gData != null && gData.jobXmls != null) {
+ int i = 0;
for(String gJobXml : gData.jobXmls) {
boolean alreadyExists = false;
for (Element actionXml : actionJobXmls) {
@@ -543,7 +544,8 @@
if (!alreadyExists) {
Element ejobXml = new Element(JOB_XML, actionNs);
ejobXml.setText(gJobXml);
- actionElement.addContent(ejobXml);
+ actionElement.addContent(i, ejobXml);
+ i++;
}
}
}
diff --git a/core/src/test/java/org/apache/oozie/action/hadoop/ActionExecutorTestCase.java b/core/src/test/java/org/apache/oozie/action/hadoop/ActionExecutorTestCase.java
index 8b893b8..6f118bd 100644
--- a/core/src/test/java/org/apache/oozie/action/hadoop/ActionExecutorTestCase.java
+++ b/core/src/test/java/org/apache/oozie/action/hadoop/ActionExecutorTestCase.java
@@ -267,11 +267,16 @@
* @throws Exception
*/
protected WorkflowJobBean createBaseWorkflow(XConfiguration protoConf, String actionName) throws Exception {
- Path appUri = new Path(getAppPath(), "workflow.xml");
-
String content = "<workflow-app xmlns='uri:oozie:workflow:1.0' xmlns:sla='uri:oozie:sla:0.1' name='no-op-wf'>";
content += "<start to='end' />";
content += "<end name='end' /></workflow-app>";
+
+ return createBaseWorkflow(protoConf, actionName, content);
+ }
+
+ protected WorkflowJobBean createBaseWorkflow(XConfiguration protoConf, String actionName, String content) throws Exception {
+ Path appUri = new Path(getAppPath(), "workflow.xml");
+
writeToFile(content, getAppPath(), "workflow.xml");
WorkflowApp app = new LiteWorkflowApp("testApp", "<workflow-app/>",
diff --git a/release-log.txt b/release-log.txt
index 86693cc..bd927d4 100644
--- a/release-log.txt
+++ b/release-log.txt
@@ -1,5 +1,6 @@
-- Oozie 5.2.0 release (trunk - unreleased)
+OOZIE-3526 Global job-xml not being overwritten by job-xml specified for an action (mgogineni via rohini)
OOZIE-2755 Oozie HA: ZKJobsConcurrencyService throws runtime exception when numOozies is zero(asalamon74 via kmarton)
OOZIE-3527 Oozie stuck in waiting state if CoordPushDependencyCheckXCommand is not requeued (mgogineni via rohini)
OOZIE-3524 fs:fileSize() does not work correctly for files with extra slash in path (mgogineni via asalamon74)
diff --git a/sharelib/streaming/src/test/java/org/apache/oozie/action/hadoop/TestMapReduceActionExecutor.java b/sharelib/streaming/src/test/java/org/apache/oozie/action/hadoop/TestMapReduceActionExecutor.java
index 476c9fd..75b94d1 100644
--- a/sharelib/streaming/src/test/java/org/apache/oozie/action/hadoop/TestMapReduceActionExecutor.java
+++ b/sharelib/streaming/src/test/java/org/apache/oozie/action/hadoop/TestMapReduceActionExecutor.java
@@ -22,6 +22,7 @@
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
+import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -227,6 +228,100 @@
assertEquals("global-output-dir", actionConf.get("outputDir"));
}
+ public void testGlobalOverrideJobXml() throws Exception {
+ FileSystem fs = getFileSystem();
+
+ String jobXml1 = createJobXml("aa", "from_jobXml1", "bb", "from_jobXml1", "jobXml1", fs);
+ String jobXml2 = createJobXml("bb", "from_jobXml2", "cc", "from_jobXml2", "jobXml2", fs);
+ String jobXml3 = createJobXml("cc", "from_jobXml3", "dd", "from_jobXml3", "jobXml3", fs);
+ String jobXml4 = createJobXml("dd", "from_jobXml4", "ee", "from_jobXml4", "jobXml4", fs);
+
+ String actionXml = "<map-reduce>"
+ + " <prepare>"
+ + " <delete path=\"${nameNode}/user/${wf:user()}/mr/${outputDir}\"/>"
+ + " </prepare>"
+ + " <job-xml>" + jobXml3 + "</job-xml>"
+ + " <job-xml>" + jobXml4 + "</job-xml>"
+ + " <configuration>"
+ + " <property><name>ee</name><value>from_action_config</value></property>"
+ + " </configuration>"
+ + " </map-reduce>";
+ String wfXml = "<workflow-app xmlns=\"uri:oozie:workflow:0.5\" name=\"map-reduce-wf\">"
+ + "<global>"
+ + "<job-tracker>${jobTracker}</job-tracker>"
+ + "<name-node>${nameNode}</name-node>"
+ + "<job-xml>" + jobXml1 + "</job-xml>"
+ + "<job-xml>" + jobXml2 + "</job-xml>"
+ + "<configuration>"
+ + "<property><name>aa</name><value>from_global_config</value></property>"
+ + "<property><name>ee</name><value>from_global_config</value></property>"
+ + "</configuration>"
+ + "</global>"
+ + " <start to=\"mr-node\"/>"
+ + " <action name=\"mr-node\">"
+ + actionXml
+ + " <ok to=\"end\"/>"
+ + " <error to=\"fail\"/>"
+ + "</action>"
+ + "<kill name=\"fail\">"
+ + " <message>Map/Reduce failed, error message[${wf:errorMessage(wf:lastErrorNode())}]</message>"
+ + "</kill>"
+ + "<end name=\"end\"/>"
+ + "</workflow-app>";
+
+ Writer writer = new FileWriter(getTestCaseDir() + "/workflow.xml");
+ IOUtils.copyCharStream(new StringReader(wfXml), writer);
+
+ Configuration conf = new XConfiguration();
+ conf.set("nameNode", getNameNodeUri());
+ conf.set("jobTracker", getJobTrackerUri());
+ conf.set(OozieClient.USER_NAME, getTestUser());
+ conf.set(OozieClient.APP_PATH, "file://" + getTestCaseDir() + File.separator + "workflow.xml");
+
+ OutputStream os = new FileOutputStream(getTestCaseDir() + "/config-default.xml");
+ XConfiguration defaultConf = new XConfiguration();
+ defaultConf.set("aa", "from_config_default");
+ defaultConf.set("ff", "from_config_default");
+ defaultConf.writeXml(os);
+ os.close();
+ defaultConf.set(WorkflowAppService.HADOOP_USER, getTestUser());
+
+ String wfId = new SubmitXCommand(conf).call();
+ new StartXCommand(wfId).call();
+ waitForWorkflowAction(wfId + "@mr-node");
+ WorkflowActionBean mrAction = WorkflowActionQueryExecutor.getInstance().get(WorkflowActionQuery.GET_ACTION,
+ wfId + "@mr-node");
+
+ JavaActionExecutor ae = new JavaActionExecutor();
+ WorkflowJobBean wf = createBaseWorkflow(defaultConf, "mr-action", wfXml);
+ Context context = new Context(wf, mrAction);
+ Element mrActionXml = XmlUtils.parseXml(mrAction.getConf());
+ Configuration actionConfig = ae.setupActionConf(conf, context, mrActionXml, getAppPath());
+
+ // Check attribute values
+ assertEquals("from_global_config", actionConfig.get("aa"));
+ assertEquals("from_jobXml2", actionConfig.get("bb"));
+ assertEquals("from_jobXml3", actionConfig.get("cc"));
+ assertEquals("from_jobXml4", actionConfig.get("dd"));
+ assertEquals("from_action_config", actionConfig.get("ee"));
+ assertEquals("from_config_default", actionConfig.get("ff"));
+ }
+
+ protected String createJobXml(String key1, String value1, String key2, String value2, String filename, FileSystem fs)
+ throws Exception {
+ String content = "<configuration>"
+ + "<property><name>" + key1 + "</name><value>" + value1 + "</value></property>"
+ + "<property><name>" + key2 + "</name><value>" + value2 + "</value></property>"
+ + "</configuration>";
+
+ Path path = new Path(getAppPath(), filename);
+ Writer writer = new OutputStreamWriter(fs.create(path, true));
+ writer.write(content);
+ writer.close();
+
+ return path.toString();
+ }
+
public void testSetupMethods() throws Exception {
MapReduceActionExecutor ae = new MapReduceActionExecutor();
List<Class<?>> classes = Arrays.<Class<?>>asList(StreamingMain.class);