| /** |
| * 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.oozie.command.wf; |
| |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.OutputStream; |
| import java.io.OutputStreamWriter; |
| import java.io.PrintWriter; |
| import java.io.StringReader; |
| import java.net.URI; |
| import java.nio.charset.StandardCharsets; |
| |
| import org.apache.commons.lang3.RandomStringUtils; |
| import org.apache.hadoop.conf.Configuration; |
| import org.apache.oozie.ErrorCode; |
| import org.apache.oozie.WorkflowActionBean; |
| import org.apache.oozie.WorkflowJobBean; |
| import org.apache.oozie.executor.jpa.WorkflowActionQueryExecutor; |
| import org.apache.oozie.local.LocalOozie; |
| import org.apache.oozie.client.OozieClient; |
| import org.apache.oozie.client.WorkflowJob; |
| import org.apache.oozie.command.CommandException; |
| import org.apache.oozie.executor.jpa.WorkflowJobQueryExecutor; |
| import org.apache.oozie.executor.jpa.WorkflowJobQueryExecutor.WorkflowJobQuery; |
| import org.apache.oozie.service.Services; |
| import org.apache.oozie.service.WorkflowAppService; |
| import org.apache.oozie.service.WorkflowStoreService; |
| import org.apache.oozie.store.WorkflowStore; |
| import org.apache.oozie.test.XDataTestCase; |
| import org.apache.oozie.util.XConfiguration; |
| import org.apache.oozie.service.XLogService; |
| import org.apache.oozie.util.IOUtils; |
| import org.apache.oozie.util.XmlUtils; |
| import org.jdom.Element; |
| |
| public class TestSubmitXCommand extends XDataTestCase { |
| @Override |
| protected void setUp() throws Exception { |
| super.setUp(); |
| setSystemProperty(XLogService.LOG4J_FILE, "oozie-log4j.properties"); |
| LocalOozie.start(); |
| } |
| |
| @Override |
| protected void tearDown() throws Exception { |
| LocalOozie.stop(); |
| super.tearDown(); |
| } |
| |
| public void testSubmitAppName() throws Exception { |
| Configuration conf = new XConfiguration(); |
| String workflowUri = getTestCaseFileUri("workflow.xml"); |
| String appXml = "<workflow-app xmlns='uri:oozie:workflow:0.1' name='${appName}-foo'> " + "<start to='end' /> " |
| + "<end name='end' /> " + "</workflow-app>"; |
| |
| writeToFile(appXml, workflowUri); |
| conf.set(OozieClient.APP_PATH, workflowUri); |
| conf.set(OozieClient.USER_NAME, getTestUser()); |
| conf.set("appName", "var-app-name"); |
| SubmitXCommand sc = new SubmitXCommand(conf); |
| String jobId = sc.call(); |
| WorkflowStoreService wss = Services.get().get(WorkflowStoreService.class); |
| WorkflowStore ws = wss.create(); |
| WorkflowJobBean wfb = ws.getWorkflow(jobId, false); |
| assertEquals("var-app-name-foo", wfb.getAppName()); |
| } |
| |
| public void testSubmitReservedVars() throws Exception { |
| Configuration conf = new XConfiguration(); |
| String workflowUri = getTestCaseFileUri("workflow.xml"); |
| String appXml = "<workflow-app xmlns='uri:oozie:workflow:0.1' name='map-reduce-wf'> " + "<start to='end' /> " |
| + "<end name='end' /> " + "</workflow-app>"; |
| |
| writeToFile(appXml, workflowUri); |
| conf.set(OozieClient.APP_PATH, workflowUri); |
| conf.set(OozieClient.USER_NAME, getTestUser()); |
| conf.set("GB", "5"); |
| SubmitXCommand sc = new SubmitXCommand(conf); |
| |
| try { |
| sc.call(); |
| fail("WF job submission should fail with reserved variable definitions."); |
| } |
| catch (CommandException ce) { |
| |
| } |
| } |
| |
| public void testAppPathIsDir() throws Exception { |
| Configuration conf = new XConfiguration(); |
| String workflowUri = getTestCaseFileUri("workflow.xml"); |
| String appXml = "<workflow-app xmlns='uri:oozie:workflow:0.1' name='map-reduce-wf'> " + "<start to='end' /> " |
| + "<end name='end' /> " + "</workflow-app>"; |
| |
| writeToFile(appXml, workflowUri); |
| conf.set(OozieClient.APP_PATH, workflowUri); |
| conf.set(OozieClient.USER_NAME, getTestUser()); |
| |
| SubmitXCommand sc = new SubmitXCommand(conf); |
| |
| try { |
| sc.call(); |
| } |
| catch (CommandException ce) { |
| fail("Should succeed"); |
| } |
| } |
| |
| public void testSubmitLongXml() throws Exception { |
| Configuration conf = new XConfiguration(); |
| String workflowUri = getTestCaseFileUri("workflow.xml"); |
| String actionXml = "<map-reduce>" |
| + "<job-tracker>${jobTracker}</job-tracker>" |
| + "<name-node>${nameNode}</name-node>" |
| + " <prepare>" |
| + " <delete path=\"${nameNode}/user/${wf:user()}/mr/${outputDir}\"/>" |
| + " </prepare>" |
| + " <configuration>" |
| + " <property><name>bb</name><value>BB</value></property>" |
| + " <property><name>cc</name><value>from_action</value></property>" |
| + " </configuration>" |
| + " </map-reduce>"; |
| String appXml = "<workflow-app xmlns='uri:oozie:workflow:0.5' name='too-long-wf'> " + |
| "<global><configuration>"+generate64kData()+"</configuration></global><start to='mr-node' /> " |
| + " <action name=\"mr-node\">" |
| + actionXml |
| + " <ok to=\"end\"/>" |
| + " <error to=\"end\"/>" |
| + "</action>" |
| + "<end name='end' /> " + "</workflow-app>"; |
| |
| writeToFile(appXml, workflowUri); |
| conf.set(OozieClient.APP_PATH, workflowUri); |
| conf.set(OozieClient.USER_NAME, getTestUser()); |
| addBunchOfProperties(conf); |
| |
| SubmitXCommand sc = new SubmitXCommand(conf); |
| sc.call(); |
| } |
| |
| private void addBunchOfProperties(Configuration conf) { |
| int i=0; |
| while(conf.size() < 10000){ |
| conf.set("ID"+i, i+"something"); |
| i++; |
| } |
| } |
| |
| private String generate64kData() { |
| return "<property><name>radnom</name><value>"+ RandomStringUtils.randomAlphanumeric(70000)+"</value></property>"; |
| } |
| |
| public void testAppPathIsFile1() throws Exception { |
| Configuration conf = new XConfiguration(); |
| String workflowUri = getTestCaseFileUri("workflow.xml"); |
| String appXml = "<workflow-app xmlns='uri:oozie:workflow:0.1' name='map-reduce-wf'> " + "<start to='end' /> " |
| + "<end name='end' /> " + "</workflow-app>"; |
| |
| writeToFile(appXml, workflowUri); |
| conf.set(OozieClient.APP_PATH, workflowUri); |
| conf.set(OozieClient.USER_NAME, getTestUser()); |
| |
| SubmitXCommand sc = new SubmitXCommand(conf); |
| |
| try { |
| sc.call(); |
| } |
| catch (CommandException ce) { |
| fail("Should succeed"); |
| } |
| } |
| |
| public void testAppPathIsFile2() throws Exception { |
| Configuration conf = new XConfiguration(); |
| String workflowUri = getTestCaseFileUri("workflow.xml"); |
| String appXml = "<workflow-app xmlns='uri:oozie:workflow:0.1' name='map-reduce-wf'> " + "<start to='end' /> " |
| + "<end name='end' /> " + "</workflow-app>"; |
| |
| writeToFile(appXml, workflowUri); |
| conf.set(OozieClient.APP_PATH, workflowUri); |
| conf.set(OozieClient.USER_NAME, getTestUser()); |
| |
| SubmitXCommand sc = new SubmitXCommand(conf); |
| |
| try { |
| sc.call(); |
| } |
| catch (CommandException ce) { |
| fail("Should succeed"); |
| } |
| } |
| |
| public void testAppPathIsFileNegative() throws Exception { |
| Configuration conf = new XConfiguration(); |
| String workflowUri = getTestCaseFileUri("test.xml"); |
| String appXml = "<workflow-app xmlns='uri:oozie:workflow:0.1' name='map-reduce-wf'> " + "<start to='end' /> " |
| + "<end name='end' /> " + "</workflow-app>"; |
| |
| writeToFile(appXml, workflowUri); |
| conf.set(OozieClient.APP_PATH, getTestCaseFileUri("does_not_exist.xml")); |
| conf.set(OozieClient.USER_NAME, getTestUser()); |
| SubmitXCommand sc = new SubmitXCommand(conf); |
| |
| try { |
| sc.call(); |
| fail("should fail"); |
| } |
| catch (CommandException ce) { |
| |
| } |
| } |
| |
| public void testDryrunValidXml() throws Exception { |
| Configuration conf = new XConfiguration(); |
| String workflowUri = getTestCaseFileUri("workflow.xml"); |
| String appXml = IOUtils.getResourceAsString("wf-schema-valid-global.xml", -1); |
| writeToFile(appXml, workflowUri); |
| conf.set(OozieClient.APP_PATH, workflowUri); |
| conf.set(OozieClient.USER_NAME, getTestUser()); |
| SubmitXCommand sc = new SubmitXCommand(true, conf); |
| try { |
| sc.call(); |
| fail("Should fail with variable cannot be resolved"); |
| } catch (CommandException ex) { |
| assertEquals(ErrorCode.E0803, ex.getErrorCode()); |
| assertEquals("E0803: IO error, variable [foo] cannot be resolved", ex.getMessage()); |
| } |
| conf.set("foo", "foo"); |
| sc = new SubmitXCommand(true, conf); |
| assertEquals("OK", sc.call()); |
| } |
| |
| public void testDryrunInvalidXml() throws Exception { |
| Configuration conf = new XConfiguration(); |
| String workflowUri = getTestCaseFileUri("workflow.xml"); |
| String appXml = IOUtils.getResourceAsString("wf-loop1-invalid.xml", -1); |
| writeToFile(appXml, workflowUri); |
| conf.set(OozieClient.APP_PATH, workflowUri); |
| conf.set(OozieClient.USER_NAME, getTestUser()); |
| SubmitXCommand sc = new SubmitXCommand(true, conf); |
| try { |
| sc.call(); |
| fail("Should have gotten E0707 because the XML has a loop"); |
| } catch (CommandException ce) { |
| assertEquals(ErrorCode.E0707, ce.getErrorCode()); |
| assertEquals("E0707: Loop detected at parsing, node [a], path [:start:->a->c->a]", ce.getMessage()); |
| } |
| |
| conf = new XConfiguration(); |
| appXml = IOUtils.getResourceAsString("wf-transition-invalid.xml", -1); |
| writeToFile(appXml, workflowUri); |
| conf.set(OozieClient.APP_PATH, workflowUri); |
| conf.set(OozieClient.USER_NAME, getTestUser()); |
| sc = new SubmitXCommand(true, conf); |
| try { |
| sc.call(); |
| fail("Should have gotten E0708 because the XML has an invalid transition"); |
| } catch (CommandException ce) { |
| assertEquals(ErrorCode.E0708, ce.getErrorCode()); |
| assertEquals("E0708: Invalid transition, node [c] transition [f]", ce.getMessage()); |
| } |
| |
| conf = new XConfiguration(); |
| appXml = IOUtils.getResourceAsString("wf-schema-invalid.xml", -1); |
| writeToFile(appXml, workflowUri); |
| conf.set(OozieClient.APP_PATH, workflowUri); |
| conf.set(OozieClient.USER_NAME, getTestUser()); |
| sc = new SubmitXCommand(true, conf); |
| try { |
| sc.call(); |
| fail("Should have gotten E0701 because the XML has an invalid element"); |
| } catch (CommandException ce) { |
| assertEquals(ErrorCode.E0701, ce.getErrorCode()); |
| assertTrue(ce.getMessage().contains("XML schema error")); |
| assertTrue(ce.getMessage().contains("starting with element 'xstart'")); |
| assertTrue(ce.getMessage().contains("'{\"uri:oozie:workflow:0.1\":start}' is expected")); |
| } |
| } |
| |
| // It should not store Hadoop properties |
| public void testProtoConfStorage() throws Exception { |
| final OozieClient wfClient = LocalOozie.getClient(); |
| |
| Configuration conf = new XConfiguration(); |
| String workflowUri = getTestCaseFileUri("workflow.xml"); |
| String appXml = "<workflow-app xmlns='uri:oozie:workflow:0.1' name='${appName}-foo'> " + "<start to='end' /> " |
| + "<end name='end' /> " + "</workflow-app>"; |
| |
| writeToFile(appXml, workflowUri); |
| conf.set(OozieClient.APP_PATH, workflowUri); |
| conf.set(OozieClient.USER_NAME, getTestUser()); |
| conf.set("appName", "var-app-name"); |
| SubmitXCommand sc = new SubmitXCommand(conf); |
| final String jobId = sc.call(); |
| |
| waitFor(15 * 1000, new Predicate() { |
| public boolean evaluate() throws Exception { |
| return wfClient.getJobInfo(jobId).getStatus() == WorkflowJob.Status.PREP; |
| } |
| }); |
| WorkflowJobBean wf = WorkflowJobQueryExecutor.getInstance().get(WorkflowJobQuery.GET_WORKFLOW, jobId); |
| XConfiguration protoConf = new XConfiguration(new StringReader(wf.getProtoActionConf())); |
| // Hadoop 2 adds "mapreduce.job.user.name" in addition to "user.name" |
| if (protoConf.get("mapreduce.job.user.name") != null) { |
| assertEquals(3, protoConf.size()); |
| } else { |
| assertEquals(2, protoConf.size()); |
| } |
| assertNull(protoConf.get(WorkflowAppService.APP_LIB_PATH_LIST)); |
| |
| new File(getTestCaseDir() + "/lib").mkdirs(); |
| File.createTempFile("parentLibrary", ".jar", new File(getTestCaseDir() + "/lib")); |
| conf.set(OozieClient.APP_PATH, workflowUri); |
| conf.set(OozieClient.USER_NAME, getTestUser()); |
| conf.set("appName", "var-app-name"); |
| sc = new SubmitXCommand(conf); |
| final String jobId1 = sc.call(); |
| |
| waitFor(15 * 1000, new Predicate() { |
| public boolean evaluate() throws Exception { |
| return wfClient.getJobInfo(jobId1).getStatus() == WorkflowJob.Status.PREP; |
| } |
| }); |
| wf = WorkflowJobQueryExecutor.getInstance().get(WorkflowJobQuery.GET_WORKFLOW, jobId1); |
| protoConf = new XConfiguration(new StringReader(wf.getProtoActionConf())); |
| // Hadoop 2 adds "mapreduce.job.user.name" in addition to "user.name" |
| if (protoConf.get("mapreduce.job.user.name") != null) { |
| assertEquals(4, protoConf.size()); |
| } else { |
| assertEquals(3, protoConf.size()); |
| } |
| assertNotNull(protoConf.get(WorkflowAppService.APP_LIB_PATH_LIST)); |
| } |
| |
| public void testWFConfigDefaultVarResolve() throws Exception { |
| final OozieClient wfClient = LocalOozie.getClient(); |
| OutputStream os = new FileOutputStream(getTestCaseDir() + "/config-default.xml"); |
| XConfiguration defaultConf = new XConfiguration(); |
| defaultConf.set("outputDir", "default-output-dir"); |
| defaultConf.set("foo.bar", "default-foo-bar"); |
| defaultConf.set("foobarRef", "${foo.bar}"); |
| defaultConf.set("key", "default_value"); |
| defaultConf.set("should_resolve", "${should.resolve}"); |
| defaultConf.set("mixed", "${nameNode}/${outputDir}"); |
| defaultConf.writeXml(os); |
| os.close(); |
| |
| String workflowUri = getTestCaseFileUri("workflow.xml"); |
| String actionXml = "<map-reduce>" |
| + "<job-tracker>${jobTracker}</job-tracker>" |
| + "<name-node>${nameNode}</name-node>" |
| + " <prepare>" |
| + " <delete path=\"${nameNode}/user/${wf:user()}/mr/${outputDir}\"/>" |
| + " </prepare>" |
| + " <configuration>" |
| + " <property><name>bb</name><value>BB</value></property>" |
| + " <property><name>cc</name><value>from_action</value></property>" |
| + " </configuration>" |
| + " </map-reduce>"; |
| String wfXml = "<workflow-app xmlns=\"uri:oozie:workflow:0.5\" name=\"map-reduce-wf\">" |
| + " <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>"; |
| |
| writeToFile(wfXml, workflowUri); |
| Configuration conf = new XConfiguration(); |
| conf.set("nameNode", getNameNodeUri()); |
| conf.set("jobTracker", getJobTrackerUri()); |
| conf.set("foobarRef", "foobarRef"); |
| conf.set("key", "job_prop_value"); |
| conf.set(OozieClient.APP_PATH, workflowUri); |
| conf.set(OozieClient.USER_NAME, getTestUser()); |
| conf.set("should.resolve", "resolved"); |
| SubmitXCommand sc = new SubmitXCommand(conf); |
| final String jobId = sc.call(); |
| new StartXCommand(jobId).call(); |
| waitFor(15 * 1000, new Predicate() { |
| public boolean evaluate() throws Exception { |
| return wfClient.getJobInfo(jobId).getStatus() == WorkflowJob.Status.KILLED; |
| } |
| }); |
| String actionId = jobId + "@mr-node"; |
| WorkflowActionBean action = WorkflowActionQueryExecutor.getInstance().get(WorkflowActionQueryExecutor.WorkflowActionQuery |
| .GET_ACTION, actionId); |
| Element eAction = XmlUtils.parseXml(action.getConf()); |
| Element eConf = eAction.getChild("configuration", eAction.getNamespace()); |
| Configuration actionConf = new XConfiguration(new StringReader(XmlUtils.prettyPrint(eConf).toString())); |
| assertEquals("default-output-dir", actionConf.get("outputDir")); |
| assertEquals("BB", actionConf.get("bb")); |
| assertEquals("from_action", actionConf.get("cc")); |
| assertEquals("resolved", actionConf.get("should_resolve")); |
| assertEquals("default-foo-bar", actionConf.get("foo.bar")); |
| assertEquals("default-foo-bar", actionConf.get("foobarRef")); |
| assertEquals("default_value", actionConf.get("key")); |
| assertEquals(getNameNodeUri()+"/default-output-dir", actionConf.get("mixed")); |
| } |
| |
| public void testWFConfigPathVarResolve() throws Exception { |
| final OozieClient wfClient = LocalOozie.getClient(); |
| |
| OutputStream os1 = new FileOutputStream(getTestCaseDir() + "/config-default.xml"); |
| XConfiguration defaultConf = new XConfiguration(); |
| defaultConf.set("outputDir", "default-output-dir"); |
| defaultConf.set("should_resolve", "${should.resolve}"); |
| defaultConf.set("foo.bar", "default-foo-bar"); |
| defaultConf.set("foobarRef", "${foo.bar}"); |
| defaultConf.writeXml(os1); |
| os1.close(); |
| |
| OutputStream os2 = new FileOutputStream(getTestCaseDir() + "/extra-config-file1.xml"); |
| XConfiguration confFile1 = new XConfiguration(); |
| confFile1.set("outputDir", "default-output-dir_unused1"); |
| confFile1.set("should_resolve_file1", "${should.resolve.file1}"); |
| confFile1.set("key", "default_value_unused"); |
| confFile1.set("foobarRef1", "${foo.bar}"); |
| confFile1.writeXml(os2); |
| os2.close(); |
| |
| |
| OutputStream os3 = new FileOutputStream(getTestCaseDir() + "/extra-config-file2.xml"); |
| XConfiguration confFile2 = new XConfiguration(); |
| confFile2.set("outputDir", "default-output-dir_unused2"); |
| confFile2.set("should_resolve_file2", "${should.resolve.file2}"); |
| confFile2.set("key", "default_value"); |
| confFile2.set("foobarRef2", "${foobarRef1}"); |
| confFile2.writeXml(os3); |
| os3.close(); |
| |
| |
| String workflowUri = getTestCaseFileUri("workflow.xml"); |
| String actionXml = "<map-reduce>" |
| + "<job-tracker>${jobTracker}</job-tracker>" |
| + "<name-node>${nameNode}</name-node>" |
| + " <prepare>" |
| + " <delete path=\"${nameNode}/user/${wf:user()}/mr/${outputDir}\"/>" |
| + " </prepare>" |
| + " <configuration>" |
| + " <property><name>bb</name><value>BB</value></property>" |
| + " <property><name>cc</name><value>from_action</value></property>" |
| + " </configuration>" |
| + " </map-reduce>"; |
| String wfXml = "<workflow-app xmlns=\"uri:oozie:workflow:0.5\" name=\"map-reduce-wf\">" |
| + " <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>"; |
| |
| writeToFile(wfXml, workflowUri); |
| Configuration conf = new XConfiguration(); |
| conf.set("nameNode", getNameNodeUri()); |
| conf.set("jobTracker", getJobTrackerUri()); |
| conf.set("foobarRef", "foobarRef"); |
| conf.set(OozieClient.APP_PATH, workflowUri); |
| conf.set(OozieClient.USER_NAME, getTestUser()); |
| conf.set("should.resolve", "resolved"); |
| conf.set("should.resolve.file1", "resolved"); |
| conf.set("should.resolve.file2", "resolved"); |
| conf.set("oozie.default.configuration.path", getTestCaseDir() + "/extra-config-file1.xml," |
| + getTestCaseDir() + "/extra-config-file2.xml"); |
| SubmitXCommand sc = new SubmitXCommand(conf); |
| final String jobId = sc.call(); |
| new StartXCommand(jobId).call(); |
| waitFor(15 * 1000, new Predicate() { |
| public boolean evaluate() throws Exception { |
| return wfClient.getJobInfo(jobId).getStatus() == WorkflowJob.Status.KILLED; |
| } |
| }); |
| String actionId = jobId + "@mr-node"; |
| WorkflowActionBean action = WorkflowActionQueryExecutor.getInstance().get(WorkflowActionQueryExecutor.WorkflowActionQuery |
| .GET_ACTION, actionId); |
| Element eAction = XmlUtils.parseXml(action.getConf()); |
| Element eConf = eAction.getChild("configuration", eAction.getNamespace()); |
| Configuration actionConf = new XConfiguration(new StringReader(XmlUtils.prettyPrint(eConf).toString())); |
| assertEquals("Variable should_resolve!='resolved' from config-default.xml", |
| "resolved", actionConf.get("should_resolve")); |
| assertEquals("Variable 'should_resolve_file1' from extra-config-file1 did not resolve correctly", |
| "resolved", actionConf.get("should_resolve_file1")); |
| assertEquals("Variable 'should_resolve_file2' from extra-config-file2 did not resolve correctly", |
| "resolved", actionConf.get("should_resolve_file2")); |
| assertEquals("Variable 'outputDir' from config-default did not resolve correctly", |
| "default-output-dir", actionConf.get("outputDir")); |
| assertEquals("Variable 'bb' from workflow did not resolve correctly", |
| "BB", actionConf.get("bb")); |
| assertEquals("Variable 'cc' from workflow did not resolve correctly", |
| "from_action", actionConf.get("cc")); |
| assertEquals("Variable 'foo.bar' from config-default did not resolve correctly", |
| "default-foo-bar", actionConf.get("foo.bar")); |
| assertEquals("Variable 'foobarRef' from config-default did not resolve correctly", |
| "default-foo-bar", actionConf.get("foobarRef")); |
| assertEquals("Variable 'foobarRef1' from extra-config-file1 did not resolve correctly", |
| "default-foo-bar", actionConf.get("foobarRef1")); |
| assertEquals("Variable 'foobarRef2' from extra-config-file2 did not resolve correctly", |
| "default-foo-bar", actionConf.get("foobarRef2")); |
| assertEquals("Variable 'key' from extra-config-file2 did not resolve correctly", |
| "default_value", actionConf.get("key")); |
| } |
| |
| |
| private void writeToFile(String appXml, String appPath) throws IOException { |
| File wf = new File(URI.create(appPath)); |
| PrintWriter out = null; |
| try { |
| out = new PrintWriter(new OutputStreamWriter(new FileOutputStream(wf), StandardCharsets.UTF_8)); |
| out.println(appXml); |
| } |
| catch (IOException iex) { |
| throw iex; |
| } |
| finally { |
| if (out != null) { |
| out.close(); |
| } |
| } |
| } |
| } |