You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@oozie.apache.org by an...@apache.org on 2018/06/19 09:46:52 UTC
[02/16] oozie git commit: OOZIE-2339 [fluent-job] Minimum Viable
Fluent Job API (daniel.becker, andras.piros via rkanter, gezapeti, pbacsko)
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/mapping/TestSubWorkflowActionMapping.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/mapping/TestSubWorkflowActionMapping.java b/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/mapping/TestSubWorkflowActionMapping.java
new file mode 100644
index 0000000..10f673f
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/mapping/TestSubWorkflowActionMapping.java
@@ -0,0 +1,47 @@
+/**
+ * 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.fluentjob.api.mapping;
+
+import org.apache.oozie.fluentjob.api.generated.workflow.SUBWORKFLOW;
+import org.apache.oozie.fluentjob.api.action.SubWorkflowAction;
+import org.apache.oozie.fluentjob.api.action.SubWorkflowActionBuilder;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class TestSubWorkflowActionMapping {
+
+ @Test
+ public void testMappingSubWorkflowAction() {
+ final String appPath = "/path/to/app";
+
+ final SubWorkflowAction action = SubWorkflowActionBuilder.create()
+ .withAppPath(appPath)
+ .withPropagatingConfiguration()
+ .withConfigProperty("propertyName", "propertyValue")
+ .build();
+
+ final SUBWORKFLOW subWorkflowAction = DozerBeanMapperSingleton.instance().map(action, SUBWORKFLOW.class);
+
+ assertEquals(appPath, subWorkflowAction.getAppPath());
+ assertNotNull(subWorkflowAction.getPropagateConfiguration());
+ assertNotNull(subWorkflowAction.getConfiguration());
+ }
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/mapping/TestWorkflowAttributesMapping.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/mapping/TestWorkflowAttributesMapping.java b/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/mapping/TestWorkflowAttributesMapping.java
new file mode 100644
index 0000000..24cbb64
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/mapping/TestWorkflowAttributesMapping.java
@@ -0,0 +1,53 @@
+/**
+ * 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.fluentjob.api.mapping;
+
+import org.apache.oozie.fluentjob.api.dag.Graph;
+import org.apache.oozie.fluentjob.api.generated.workflow.WORKFLOWAPP;
+import org.apache.oozie.fluentjob.api.workflow.Workflow;
+import org.apache.oozie.fluentjob.api.workflow.WorkflowBuilder;
+import org.junit.Test;
+
+import static org.junit.Assert.assertNull;
+
+public class TestWorkflowAttributesMapping {
+
+ private final SourceDataFactory factory = new SourceDataFactory();
+
+ @Test
+ public void testMappingNoCredentialsToWorkflow() {
+ final Workflow source = new WorkflowBuilder()
+ .build();
+
+ final WORKFLOWAPP destination = DozerBeanMapperSingleton.instance().map(new Graph(source), WORKFLOWAPP.class);
+
+ assertNull(destination.getCredentials());
+ }
+
+ @Test
+ public void testMappingCredentialsAsWorkflowParameters() {
+ final Workflow source = new WorkflowBuilder()
+ .withCredentials(factory.createCredentials())
+ .build();
+
+ final WORKFLOWAPP destination = DozerBeanMapperSingleton.instance().map(new Graph(source), WORKFLOWAPP.class);
+
+ factory.assertCredentials(destination.getCredentials());
+ }
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/workflow/TestCredentialBuilder.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/workflow/TestCredentialBuilder.java b/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/workflow/TestCredentialBuilder.java
new file mode 100644
index 0000000..06c5b3d
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/workflow/TestCredentialBuilder.java
@@ -0,0 +1,56 @@
+/**
+ * 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.fluentjob.api.workflow;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestCredentialBuilder {
+
+ @Test
+ public void testCreate() {
+ final Credential credential = CredentialBuilder.create()
+ .withName("hive2")
+ .withType("hive")
+ .withConfigurationEntry("jdbcUrl", "jdbc://localhost/hive")
+ .build();
+
+ assertEquals("hive2", credential.getName());
+ assertEquals("hive", credential.getType());
+ assertEquals("jdbcUrl", credential.getConfigurationEntries().get(0).getName());
+ assertEquals("jdbc://localhost/hive", credential.getConfigurationEntries().get(0).getValue());
+ }
+
+ @Test
+ public void testCreateFromExisting() {
+ final Credential credential = CredentialBuilder.create()
+ .withName("hive2")
+ .withType("hive")
+ .withConfigurationEntry("jdbcUrl", "jdbc://localhost/hive")
+ .build();
+
+ final Credential fromExisting = CredentialBuilder.createFromExisting(credential).build();
+
+ assertEquals("hive2", fromExisting.getName());
+ assertEquals("hive", fromExisting.getType());
+ assertEquals("jdbcUrl", fromExisting.getConfigurationEntries().get(0).getName());
+ assertEquals("jdbc://localhost/hive", fromExisting.getConfigurationEntries().get(0).getValue());
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/workflow/TestCredentialsBuilder.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/workflow/TestCredentialsBuilder.java b/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/workflow/TestCredentialsBuilder.java
new file mode 100644
index 0000000..4d3dce3
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/workflow/TestCredentialsBuilder.java
@@ -0,0 +1,66 @@
+/**
+ * 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.fluentjob.api.workflow;
+
+import com.google.common.collect.Lists;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestCredentialsBuilder {
+
+ @Test
+ public void testCreate() {
+ final Credentials credentials = CredentialsBuilder.create()
+ .withCredential("hive2",
+ "hive",
+ Lists.newArrayList(
+ new ConfigurationEntry("jdbcUrl", "jdbc://localhost/hive")))
+ .build();
+
+ assertEquals("hive2", credentials.getCredentials().get(0).getName());
+ assertEquals("hive", credentials.getCredentials().get(0).getType());
+ assertEquals("jdbcUrl", credentials.getCredentials().get(0).getConfigurationEntries().get(0).getName());
+ assertEquals("jdbc://localhost/hive", credentials.getCredentials().get(0).getConfigurationEntries().get(0).getValue());
+ }
+
+ @Test
+ public void testCreateFromExisting() {
+ final Credentials credentials = CredentialsBuilder.create()
+ .withCredential("hive2",
+ "hive",
+ Lists.newArrayList(
+ new ConfigurationEntry("jdbcUrl", "jdbc://localhost/hive")))
+ .build();
+
+ final Credentials fromExisting = CredentialsBuilder.createFromExisting(credentials)
+ .withCredential("hbase",
+ "hbase")
+ .build();
+
+ assertEquals("hive2", fromExisting.getCredentials().get(0).getName());
+ assertEquals("hive", fromExisting.getCredentials().get(0).getType());
+ assertEquals("jdbcUrl", fromExisting.getCredentials().get(0).getConfigurationEntries().get(0).getName());
+ assertEquals("jdbc://localhost/hive", fromExisting.getCredentials().get(0).getConfigurationEntries().get(0).getValue());
+
+ assertEquals("hbase", fromExisting.getCredentials().get(1).getName());
+ assertEquals("hbase", fromExisting.getCredentials().get(1).getType());
+ assertEquals(0, fromExisting.getCredentials().get(1).getConfigurationEntries().size());
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/workflow/TestGlobalBuilder.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/workflow/TestGlobalBuilder.java b/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/workflow/TestGlobalBuilder.java
new file mode 100644
index 0000000..c417170
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/workflow/TestGlobalBuilder.java
@@ -0,0 +1,63 @@
+/**
+ * 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.fluentjob.api.workflow;
+
+import org.apache.oozie.fluentjob.api.action.LauncherBuilder;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+public class TestGlobalBuilder {
+
+ public static final String DEFAULT = "default";
+
+ @Test
+ public void testAfterCopyFieldsAreSetCorrectly() {
+ final Global original = GlobalBuilder.create()
+ .withResourceManager(DEFAULT)
+ .withNameNode(DEFAULT)
+ .withJobXml(DEFAULT)
+ .withConfigProperty("key1", "value1")
+ .withLauncher(new LauncherBuilder()
+ .withMemoryMb(1024L)
+ .withVCores(1L)
+ .build())
+ .build();
+
+ assertEquals(DEFAULT, original.getResourceManager());
+ assertEquals(DEFAULT, original.getNameNode());
+ assertEquals(DEFAULT, original.getJobXmls().get(0));
+ assertEquals("value1", original.getConfigProperty("key1"));
+ assertEquals(1024L, original.getLauncher().getMemoryMb());
+ assertEquals(1L, original.getLauncher().getVCores());
+
+ final Global copied = GlobalBuilder.createFromExisting(original)
+ .withoutJobXml(DEFAULT)
+ .withConfigProperty("key1", null)
+ .build();
+
+ assertEquals(DEFAULT, copied.getResourceManager());
+ assertEquals(DEFAULT, copied.getNameNode());
+ assertEquals(0, copied.getJobXmls().size());
+ assertNull(copied.getConfigProperty("key1"));
+ assertEquals(1024L, copied.getLauncher().getMemoryMb());
+ assertEquals(1L, copied.getLauncher().getVCores());
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/workflow/TestParametersBuilder.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/workflow/TestParametersBuilder.java b/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/workflow/TestParametersBuilder.java
new file mode 100644
index 0000000..f9405e6
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/workflow/TestParametersBuilder.java
@@ -0,0 +1,80 @@
+/**
+ * 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.fluentjob.api.workflow;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+public class TestParametersBuilder {
+ private ParametersBuilder builder;
+
+ @Before
+ public void setUp() {
+ this.builder = ParametersBuilder.create();
+ }
+
+ @Test
+ public void testWithoutDescription() {
+ final Parameters parameters = builder
+ .withParameter("name1", "value1")
+ .withParameter("name2", "value2")
+ .build();
+
+ assertEquals("name1", parameters.getParameters().get(0).getName());
+ assertEquals("value1", parameters.getParameters().get(0).getValue());
+ assertNull(parameters.getParameters().get(0).getDescription());
+ assertEquals("name2", parameters.getParameters().get(1).getName());
+ assertEquals("value2", parameters.getParameters().get(1).getValue());
+ assertNull(parameters.getParameters().get(1).getDescription());
+ }
+
+ @Test
+ public void testWithDescription() {
+ final Parameters parameters = builder
+ .withParameter("name1", "value1", "description1")
+ .withParameter("name2", "value2", "description2")
+ .build();
+
+ assertEquals("name1", parameters.getParameters().get(0).getName());
+ assertEquals("value1", parameters.getParameters().get(0).getValue());
+ assertEquals("description1", parameters.getParameters().get(0).getDescription());
+ assertEquals("name2", parameters.getParameters().get(1).getName());
+ assertEquals("value2", parameters.getParameters().get(1).getValue());
+ assertEquals("description2", parameters.getParameters().get(1).getDescription());
+ }
+
+ @Test
+ public void testCreateFromExisting() {
+ final Parameters existing = builder
+ .withParameter("name1", "value1")
+ .withParameter("name2", "value2")
+ .build();
+
+ final Parameters fromExisting = ParametersBuilder.createFromExisting(existing)
+ .withParameter("name3", "value3")
+ .build();
+
+ assertEquals("value1", fromExisting.getParameters().get(0).getValue());
+ assertEquals("value2", fromExisting.getParameters().get(1).getValue());
+ assertEquals("value3", fromExisting.getParameters().get(2).getValue());
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/workflow/TestWorkflowBuilder.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/workflow/TestWorkflowBuilder.java b/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/workflow/TestWorkflowBuilder.java
new file mode 100644
index 0000000..29caf27
--- /dev/null
+++ b/fluent-job/fluent-job-api/src/test/java/org/apache/oozie/fluentjob/api/workflow/TestWorkflowBuilder.java
@@ -0,0 +1,258 @@
+/**
+ * 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.fluentjob.api.workflow;
+
+import com.google.common.collect.Lists;
+import org.apache.oozie.fluentjob.api.action.MapReduceActionBuilder;
+import org.apache.oozie.fluentjob.api.action.Node;
+import org.apache.oozie.fluentjob.api.action.ShellAction;
+import org.apache.oozie.fluentjob.api.action.ShellActionBuilder;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+public class TestWorkflowBuilder {
+ private static final String NAME = "workflow-name";
+
+ @Rule
+ public final ExpectedException expectedException = ExpectedException.none();
+
+ @Test
+ public void testAddName() {
+ final WorkflowBuilder builder = new WorkflowBuilder();
+ builder.withName(NAME);
+
+ final Workflow workflow = builder.build();
+
+ assertEquals(NAME, workflow.getName());
+ }
+
+ @Test
+ public void testAddDagTrivial() {
+ final Node mrAction1 = MapReduceActionBuilder.create()
+ .withName("mr1")
+ .withNameNode("${nameNode}")
+ .withResourceManager("${resourceManager}")
+ .withConfigProperty("mapred.output.dir", "${outputDir}")
+ .build();
+
+ final Node mrAction2 = MapReduceActionBuilder.create()
+ .withName("mr2")
+ .withNameNode("${nameNode}")
+ .withResourceManager("${resourceManager}")
+ .withConfigProperty("mapred.output.dir", "${outputDir}")
+ .build();
+
+ final WorkflowBuilder builder = new WorkflowBuilder();
+
+ builder.withDagContainingNode(mrAction1)
+ .withDagContainingNode(mrAction2);
+
+ final Workflow workflow = builder.build();
+
+ final Set<Node> expectedRoots = new HashSet<>(Arrays.asList(mrAction1, mrAction2));
+ assertEquals(expectedRoots, workflow.getRoots());
+
+ final Set<Node> expectedNodes = new HashSet<>(Arrays.asList(mrAction1, mrAction2));
+ assertEquals(expectedNodes, workflow.getNodes());
+ }
+
+ @Test
+ public void testAddDagFindRoots() {
+ final Node mrAction1 = MapReduceActionBuilder.create()
+ .withName("mr1")
+ .build();
+
+ final Node mrAction2 = MapReduceActionBuilder.create()
+ .withName("mr2")
+ .build();
+
+ final Node mrAction3 = MapReduceActionBuilder.create()
+ .withName("mr3")
+ .withParent(mrAction1)
+ .withParent(mrAction2)
+ .build();
+
+ final WorkflowBuilder builder = new WorkflowBuilder();
+
+ builder.withDagContainingNode(mrAction3);
+
+ final Workflow workflow = builder.build();
+
+ final Set<Node> expectedRoots = new HashSet<>(Arrays.asList(mrAction1, mrAction2));
+ assertEquals(expectedRoots, workflow.getRoots());
+
+ final Set<Node> expectedNodes = new HashSet<>(Arrays.asList(mrAction1, mrAction2, mrAction3));
+ assertEquals(expectedNodes, workflow.getNodes());
+ }
+
+ @Test
+ public void testAddDagThrowOnDuplicateNodeNames() {
+ final Node mrAction = MapReduceActionBuilder.create()
+ .withName("mr-action")
+ .build();
+
+ final Node mrActionWithTheSameName = MapReduceActionBuilder.create()
+ .withName("mr-action")
+ .build();
+
+ final WorkflowBuilder builder = new WorkflowBuilder();
+ builder.withName(NAME)
+ .withDagContainingNode(mrAction)
+ .withDagContainingNode(mrActionWithTheSameName);
+
+ expectedException.expect(IllegalArgumentException.class);
+ builder.build();
+ }
+
+ @Test
+ public void testAddDagWithConditionalChildrenAndConditionalParents() {
+ final String condition = "condition";
+
+ final Node mrAction1 = MapReduceActionBuilder.create()
+ .withName("mr1")
+ .build();
+
+ final Node mrAction2 = MapReduceActionBuilder.create()
+ .withName("mr2")
+ .build();
+
+ final Node mrAction3 = MapReduceActionBuilder.create()
+ .withName("mr3")
+ .withParentWithCondition(mrAction1, condition)
+ .withParent(mrAction2)
+ .build();
+ final Node mrAction4 = MapReduceActionBuilder.create()
+ .withName("mr4")
+ .withParentWithCondition(mrAction3, condition)
+ .build();
+ final Node mrAction5 = MapReduceActionBuilder.create()
+ .withName("mr5")
+ .withParentWithCondition(mrAction3, condition)
+ .build();
+
+ final WorkflowBuilder builder = new WorkflowBuilder();
+
+ builder.withDagContainingNode(mrAction3);
+
+ final Workflow workflow = builder.build();
+
+ final Set<Node> expectedRoots = new HashSet<>(Arrays.asList(mrAction1, mrAction2));
+ assertEquals(expectedRoots, workflow.getRoots());
+
+ final Set<Node> expectedNodes = new HashSet<>(Arrays.asList(mrAction1, mrAction2, mrAction3, mrAction4, mrAction5));
+ assertEquals(expectedNodes, workflow.getNodes());
+ }
+
+ @Test
+ public void testAddMixedParameters() {
+ final Workflow workflow = new WorkflowBuilder()
+ .withParameter("name1", "value1")
+ .withParameter("name2", "value2", "description2")
+ .build();
+
+ assertEquals("name1", workflow.getParameters().getParameters().get(0).getName());
+ assertEquals("value1", workflow.getParameters().getParameters().get(0).getValue());
+ assertNull(workflow.getParameters().getParameters().get(0).getDescription());
+ assertEquals("name2", workflow.getParameters().getParameters().get(1).getName());
+ assertEquals("value2", workflow.getParameters().getParameters().get(1).getValue());
+ assertEquals("description2", workflow.getParameters().getParameters().get(1).getDescription());
+ }
+
+ @Test
+ public void testAddGlobal() {
+ final Workflow workflow = new WorkflowBuilder()
+ .withGlobal(GlobalBuilder.create()
+ .withConfigProperty("key1", "value1")
+ .build())
+ .build();
+
+ assertEquals("value1", workflow.getGlobal().getConfigProperty("key1"));
+ }
+
+ @Test
+ public void testAddCredentials() {
+ final Workflow workflow = new WorkflowBuilder()
+ .withCredentials(CredentialsBuilder.create()
+ .withCredential("hbase", "hbase")
+ .build())
+ .build();
+
+ assertEquals("hbase", workflow.getCredentials().getCredentials().get(0).getName());
+ assertEquals("hbase", workflow.getCredentials().getCredentials().get(0).getType());
+ }
+
+ @Test
+ public void testOmittedCredentialsAreAutogenerated() {
+ final Credential hbaseCredential = CredentialBuilder.create()
+ .withName("hbase")
+ .withType("hbase")
+ .build();
+
+ final ShellAction hbaseAction = ShellActionBuilder.create()
+ .withName("hbase")
+ .withCredential(hbaseCredential)
+ .build();
+
+ final Workflow workflow = new WorkflowBuilder()
+ .withDagContainingNode(hbaseAction)
+ .build();
+
+ assertEquals(1, workflow.getCredentials().getCredentials().size());
+ assertEquals("hbase", workflow.getCredentials().getCredentials().get(0).getName());
+ assertEquals("hbase", workflow.getCredentials().getCredentials().get(0).getType());
+ }
+
+ @Test
+ public void testOverrideCredentialsPreviouslyAddedInActionsOnWorkflowLevel() {
+ final Credential hbaseCredential = CredentialBuilder.create()
+ .withName("hbase")
+ .withType("hbase")
+ .build();
+
+ final ShellAction hbaseAction = ShellActionBuilder.create()
+ .withName("hbase")
+ .withCredential(hbaseCredential)
+ .build();
+
+ final Workflow workflow = new WorkflowBuilder()
+ .withDagContainingNode(hbaseAction)
+ .withCredentials(CredentialsBuilder.create()
+ .withCredential("hive2", "hive2", Lists.newArrayList(
+ new ConfigurationEntry("jdbcUrl", "jdbc://localhost/hive")))
+ .build())
+ .build();
+
+ assertEquals(1, workflow.getCredentials().getCredentials().size());
+ assertEquals("hive2", workflow.getCredentials().getCredentials().get(0).getName());
+ assertEquals("hive2", workflow.getCredentials().getCredentials().get(0).getType());
+ assertEquals(1, workflow.getCredentials().getCredentials().get(0).getConfigurationEntries().size());
+ assertEquals("jdbcUrl",
+ workflow.getCredentials().getCredentials().get(0).getConfigurationEntries().get(0).getName());
+ assertEquals("jdbc://localhost/hive",
+ workflow.getCredentials().getCredentials().get(0).getConfigurationEntries().get(0).getValue());
+ }
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-client/pom.xml
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-client/pom.xml b/fluent-job/fluent-job-client/pom.xml
new file mode 100644
index 0000000..612fabb
--- /dev/null
+++ b/fluent-job/fluent-job-client/pom.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>oozie-fluent-job</artifactId>
+ <groupId>org.apache.oozie</groupId>
+ <version>5.1.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>oozie-fluent-job-client</artifactId>
+ <version>5.1.0-SNAPSHOT</version>
+ <description>Apache Oozie Fluent Job Client</description>
+ <name>Apache Oozie Fluent Job Client</name>
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.oozie</groupId>
+ <artifactId>oozie-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.oozie</groupId>
+ <artifactId>oozie-core</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.derby</groupId>
+ <artifactId>derby</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.oozie</groupId>
+ <artifactId>oozie-sharelib-hive</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.hadoop</groupId>
+ <artifactId>hadoop-client</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.hadoop</groupId>
+ <artifactId>hadoop-minicluster</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.oozie.test</groupId>
+ <artifactId>oozie-mini</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.oozie.test</groupId>
+ <artifactId>oozie-mini</artifactId>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.oozie</groupId>
+ <artifactId>oozie-client</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.xmlunit</groupId>
+ <artifactId>xmlunit-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/jaxb/TestJAXBWorkflow.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/jaxb/TestJAXBWorkflow.java b/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/jaxb/TestJAXBWorkflow.java
new file mode 100644
index 0000000..47adb11
--- /dev/null
+++ b/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/jaxb/TestJAXBWorkflow.java
@@ -0,0 +1,435 @@
+/**
+ * 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.jobs.client.jaxb;
+
+import org.apache.oozie.fluentjob.api.generated.workflow.ACTION;
+import org.apache.oozie.fluentjob.api.generated.workflow.ACTIONTRANSITION;
+import org.apache.oozie.fluentjob.api.generated.workflow.CONFIGURATION;
+import org.apache.oozie.fluentjob.api.generated.workflow.DELETE;
+import org.apache.oozie.fluentjob.api.generated.workflow.END;
+import org.apache.oozie.fluentjob.api.generated.workflow.KILL;
+import org.apache.oozie.fluentjob.api.generated.workflow.MAPREDUCE;
+import org.apache.oozie.fluentjob.api.generated.workflow.ObjectFactory;
+import org.apache.oozie.fluentjob.api.generated.workflow.PREPARE;
+import org.apache.oozie.fluentjob.api.generated.workflow.START;
+import org.apache.oozie.fluentjob.api.generated.workflow.WORKFLOWAPP;
+
+import org.junit.Test;
+import org.xml.sax.SAXException;
+import org.xmlunit.builder.DiffBuilder;
+import org.xmlunit.builder.Input;
+import org.xmlunit.diff.Comparison;
+import org.xmlunit.diff.ComparisonResult;
+import org.xmlunit.diff.ComparisonType;
+import org.xmlunit.diff.Diff;
+import org.xmlunit.diff.DifferenceEvaluator;
+import org.xmlunit.diff.DifferenceEvaluators;
+
+import javax.xml.XMLConstants;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+/**
+ * This class tests whether the workflow.xml files are parsed correctly into JAXB objects and whether the JAXB objects
+ * are serialized correctly to xml.
+ */
+public class TestJAXBWorkflow {
+ private static final String GENERATED_PACKAGES_ALL = "org.apache.oozie.fluentjob.api.generated.action.distcp:" +
+ "org.apache.oozie.fluentjob.api.generated.action.email:" +
+ "org.apache.oozie.fluentjob.api.generated.action.hive2:" +
+ "org.apache.oozie.fluentjob.api.generated.action.hive:" +
+ "org.apache.oozie.fluentjob.api.generated.sla:" +
+ "org.apache.oozie.fluentjob.api.generated.workflow:" +
+ "org.apache.oozie.fluentjob.api.generated.action.shell:" +
+ "org.apache.oozie.fluentjob.api.generated.action.spark:" +
+ "org.apache.oozie.fluentjob.api.generated.action.sqoop:" +
+ "org.apache.oozie.fluentjob.api.generated.action.ssh";
+ private static final String GENERATED_PACKAGES_WORKFLOW = "org.apache.oozie.fluentjob.api.generated.workflow";
+ private static final String WORKFLOW_MAPREDUCE_ACTION = "/workflow-mapreduce-action.xml";
+ private static final String WORKFLOW_ALL_ACTIONS = "/workflow-all-actions.xml";
+
+ /**
+ * Tests whether a workflow.xml object is parsed correctly into a JAXB element tree by checking some of the main
+ * properties.
+ * @throws SAXException If a SAX error occurs during parsing the schema file.
+ * @throws JAXBException If an error was encountered while creating the <tt>JAXBContext</tt> or the
+ * <tt>Unmarshaller</tt> objects.
+ */
+ @Test
+ public void whenWorkflowXmlWithAllActionTypesIsUnmarshalledAttributesArePreserved()
+ throws SAXException, JAXBException, URISyntaxException {
+ final WORKFLOWAPP wf = unmarshalWorkflowWithAllActionTypes();
+
+ assertEquals("jaxb-example-wf", wf.getName());
+ assertEquals("mr-node", wf.getStart().getTo());
+ assertEquals("end", wf.getEnd().getName());
+
+ final List<Object> actions = wf.getDecisionOrForkOrJoin();
+
+ final KILL kill = (KILL) actions.get(9);
+ assertKill(kill);
+
+ final MAPREDUCE mr = ((ACTION) actions.get(0)).getMapReduce();
+ assertMapReduce(mr);
+
+ final org.apache.oozie.fluentjob.api.generated.action.distcp.ACTION distcp =
+ (org.apache.oozie.fluentjob.api.generated.action.distcp.ACTION)
+ ((JAXBElement<?>) ((ACTION) actions.get(1)).getOther()).getValue();
+ assertDistcp(distcp);
+
+ final org.apache.oozie.fluentjob.api.generated.action.email.ACTION email =
+ (org.apache.oozie.fluentjob.api.generated.action.email.ACTION)
+ ((JAXBElement<?>) ((ACTION) actions.get(2)).getOther()).getValue();
+ assertEmail(email);
+
+ final org.apache.oozie.fluentjob.api.generated.action.hive2.ACTION hive2 =
+ (org.apache.oozie.fluentjob.api.generated.action.hive2.ACTION)
+ ((JAXBElement<?>) ((ACTION) actions.get(3)).getOther()).getValue();
+ assertHive2(hive2);
+
+ final org.apache.oozie.fluentjob.api.generated.action.hive.ACTION hive =
+ (org.apache.oozie.fluentjob.api.generated.action.hive.ACTION)
+ ((JAXBElement<?>) ((ACTION) actions.get(4)).getOther()).getValue();
+ assertHive(hive);
+
+ final org.apache.oozie.fluentjob.api.generated.action.shell.ACTION shell =
+ (org.apache.oozie.fluentjob.api.generated.action.shell.ACTION)
+ ((JAXBElement<?>) ((ACTION) actions.get(5)).getOther()).getValue();
+ assertShell(shell);
+
+ final org.apache.oozie.fluentjob.api.generated.action.spark.ACTION spark =
+ (org.apache.oozie.fluentjob.api.generated.action.spark.ACTION)
+ ((JAXBElement<?>) ((ACTION) actions.get(6)).getOther()).getValue();
+ assertSpark(spark);
+
+ final org.apache.oozie.fluentjob.api.generated.action.sqoop.ACTION sqoop =
+ (org.apache.oozie.fluentjob.api.generated.action.sqoop.ACTION)
+ ((JAXBElement<?>) ((ACTION) actions.get(7)).getOther()).getValue();
+ assertSqoop(sqoop);
+
+ final org.apache.oozie.fluentjob.api.generated.action.ssh.ACTION ssh =
+ (org.apache.oozie.fluentjob.api.generated.action.ssh.ACTION)
+ ((JAXBElement<?>) ((ACTION) actions.get(8)).getOther()).getValue();
+ assertSsh(ssh);
+ }
+
+ private void assertKill(final KILL kill) {
+ assertEquals("fail", kill.getName());
+ assertEquals("Action failed, error message[${wf:errorMessage(wf:lastErrorNode())}]", kill.getMessage());
+ }
+
+ private void assertMapReduce(final MAPREDUCE mr) {
+ final PREPARE prepare = mr.getPrepare();
+ assertEquals(0, prepare.getMkdir().size());
+
+ final List<DELETE> deleteList = prepare.getDelete();
+ assertEquals(1, deleteList.size());
+
+ final DELETE delete = deleteList.get(0);
+ assertEquals("${nameNode}/user/${wf:user()}/${examplesRoot}/output-data/${outputDir}", delete.getPath());
+
+ final CONFIGURATION conf = mr.getConfiguration();
+ final List<CONFIGURATION.Property> properties = conf.getProperty();
+
+ final CONFIGURATION.Property mapper = properties.get(1);
+ assertEquals("mapred.mapper.class", mapper.getName());
+ assertEquals("org.apache.oozie.example.SampleMapper", mapper.getValue());
+ }
+
+ private void assertDistcp(final org.apache.oozie.fluentjob.api.generated.action.distcp.ACTION distcp) {
+ assertEquals(1, distcp.getPrepare().getDelete().size());
+ assertEquals(1, distcp.getPrepare().getMkdir().size());
+ assertEquals(2, distcp.getConfiguration().getProperty().size());
+ assertEquals(2, distcp.getArg().size());
+ }
+
+ private void assertEmail(final org.apache.oozie.fluentjob.api.generated.action.email.ACTION email) {
+ assertEquals("foo@bar.com", email.getTo());
+ assertEquals("foo", email.getSubject());
+ assertEquals("bar", email.getBody());
+ }
+
+ private void assertHive2(final org.apache.oozie.fluentjob.api.generated.action.hive2.ACTION hive2) {
+ assertEquals(1, hive2.getPrepare().getDelete().size());
+ assertEquals(1, hive2.getConfiguration().getProperty().size());
+ assertEquals(2, hive2.getParam().size());
+ }
+
+ private void assertHive(final org.apache.oozie.fluentjob.api.generated.action.hive.ACTION hive) {
+ assertEquals(1, hive.getPrepare().getDelete().size());
+ assertEquals(1, hive.getConfiguration().getProperty().size());
+ assertEquals(2, hive.getParam().size());
+ }
+
+ private void assertShell(final org.apache.oozie.fluentjob.api.generated.action.shell.ACTION shell) {
+ assertEquals("echo", shell.getExec());
+ assertEquals(1, shell.getArgument().size());
+ }
+
+ private void assertSpark(final org.apache.oozie.fluentjob.api.generated.action.spark.ACTION spark) {
+ assertEquals(1, spark.getPrepare().getDelete().size());
+ assertEquals(1, spark.getConfiguration().getProperty().size());
+ assertEquals(2, spark.getArg().size());
+ }
+
+ private void assertSqoop(final org.apache.oozie.fluentjob.api.generated.action.sqoop.ACTION sqoop) {
+ assertEquals(1, sqoop.getPrepare().getDelete().size());
+ assertEquals(1, sqoop.getConfiguration().getProperty().size());
+ }
+
+ private void assertSsh(final org.apache.oozie.fluentjob.api.generated.action.ssh.ACTION ssh) {
+ assertEquals("foo@bar.com", ssh.getHost());
+ assertEquals("uploaddata", ssh.getCommand());
+ assertEquals(2, ssh.getArgs().size());
+ }
+
+ /**
+ * Tests whether a programmatically built JAXB element tree is serialized correctly to xml.
+ *
+ * @throws JAXBException If an error was encountered while creating the <tt>JAXBContext</tt>
+ * or during the marshalling.
+ */
+ @Test
+ public void marshallingWorkflowProducesCorrectXml() throws JAXBException, URISyntaxException, IOException,
+ ParserConfigurationException, SAXException {
+ final WORKFLOWAPP programmaticallyCreatedWfApp = getWfApp();
+ final String outputXml = marshalWorkflowApp(programmaticallyCreatedWfApp, GENERATED_PACKAGES_WORKFLOW);
+
+ final Diff diff = DiffBuilder.compare(Input.fromURL(getClass().getResource(WORKFLOW_MAPREDUCE_ACTION)))
+ .withTest(Input.fromString(outputXml))
+ .ignoreComments()
+ .withDifferenceEvaluator(DifferenceEvaluators.chain(
+ DifferenceEvaluators.Default,
+ new IgnoreWhitespaceInTextValueDifferenceEvaluator(),
+ new IgnoreNamespacePrefixDifferenceEvaluator()))
+ .build();
+
+ assertFalse(diff.hasDifferences());
+ }
+
+ @Test
+ public void testMarshallingWorkflowWithAllActionTypesWorks() throws JAXBException, SAXException,
+ URISyntaxException, UnsupportedEncodingException {
+ final WORKFLOWAPP wf = unmarshalWorkflowWithAllActionTypes();
+ final String outputXml = marshalWorkflowApp(wf, GENERATED_PACKAGES_ALL);
+
+ final Diff diff = DiffBuilder.compare(Input.fromURL(getClass().getResource(WORKFLOW_ALL_ACTIONS)))
+ .withTest(Input.fromString(outputXml))
+ .ignoreComments()
+ .withDifferenceEvaluator(DifferenceEvaluators.chain(
+ DifferenceEvaluators.Default,
+ new IgnoreWhitespaceInTextValueDifferenceEvaluator(),
+ new IgnoreNamespacePrefixDifferenceEvaluator()))
+ .build();
+
+ assertFalse("unmarshalled and marshalled workflow XMLs differ", diff.hasDifferences());
+ }
+
+ private static class IgnoreWhitespaceInTextValueDifferenceEvaluator implements DifferenceEvaluator {
+ @Override
+ public ComparisonResult evaluate(final Comparison comparison, final ComparisonResult comparisonResult) {
+ // We want to ignore whitespace differences in TEXT_VALUE comparisons but not anywhere else,
+ // for example not in attribute names.
+ if (isTextValueComparison(comparison) && expectedAndActualValueTrimmedAreEqual(comparison)) {
+ return ComparisonResult.EQUAL;
+ } else {
+ return comparisonResult;
+ }
+ }
+
+ private boolean isTextValueComparison(final Comparison comparison) {
+ return comparison.getType().equals(ComparisonType.TEXT_VALUE);
+ }
+
+ private boolean expectedAndActualValueTrimmedAreEqual(final Comparison comparison) {
+ final String expectedNodeValue = comparison.getControlDetails().getTarget().getNodeValue();
+ final String actualNodeValue = comparison.getTestDetails().getTarget().getNodeValue();
+
+ if (expectedNodeValue == null || actualNodeValue == null) {
+ return false;
+ }
+
+ return expectedNodeValue.trim().equals(actualNodeValue.trim());
+ }
+ }
+
+ private static class IgnoreNamespacePrefixDifferenceEvaluator implements DifferenceEvaluator {
+
+ @Override
+ public ComparisonResult evaluate(final Comparison comparison, final ComparisonResult comparisonResult) {
+ if (isElementNodeComparison(comparison)) {
+ return ComparisonResult.EQUAL;
+ }
+
+ return comparisonResult;
+ }
+
+ private boolean isElementNodeComparison(final Comparison comparison) {
+ return comparison.getType().equals(ComparisonType.NAMESPACE_PREFIX);
+ }
+ }
+
+ private WORKFLOWAPP unmarshalWorkflowWithAllActionTypes() throws SAXException, JAXBException, URISyntaxException {
+ final JAXBContext jc = JAXBContext.newInstance(GENERATED_PACKAGES_ALL);
+ final Unmarshaller u = jc.createUnmarshaller();
+ final Schema wfSchema = getSchema();
+ u.setSchema(wfSchema);
+
+ final URL wfUrl = getClass().getResource(WORKFLOW_ALL_ACTIONS);
+ final JAXBElement element = (JAXBElement) u.unmarshal(wfUrl);
+
+ return (WORKFLOWAPP) element.getValue();
+ }
+
+ private Schema getSchema() throws SAXException, URISyntaxException {
+ final SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ return sf.newSchema(new Source [] {
+ getStreamSource("/oozie-common-1.0.xsd"),
+ getStreamSource("/distcp-action-1.0.xsd"),
+ getStreamSource("/email-action-0.2.xsd"),
+ getStreamSource("/hive2-action-1.0.xsd"),
+ getStreamSource("/hive-action-1.0.xsd"),
+ getStreamSource("/oozie-sla-0.2.xsd"),
+ getStreamSource("/oozie-workflow-1.0.xsd"),
+ getStreamSource("/shell-action-1.0.xsd"),
+ getStreamSource("/spark-action-1.0.xsd"),
+ getStreamSource("/sqoop-action-1.0.xsd"),
+ getStreamSource("/ssh-action-0.2.xsd")
+ });
+ }
+
+ private Source getStreamSource(final String resourceURI) throws URISyntaxException {
+ return new StreamSource(getClass().getResource(resourceURI).toExternalForm());
+ }
+
+ private String marshalWorkflowApp(final WORKFLOWAPP wfApp, final String packages)
+ throws JAXBException, UnsupportedEncodingException {
+ final JAXBElement wfElement = new ObjectFactory().createWorkflowApp(wfApp);
+
+ final JAXBContext jc = JAXBContext.newInstance(packages);
+ final Marshaller m = jc.createMarshaller();
+ m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+ final ByteArrayOutputStream out = new ByteArrayOutputStream();
+ m.marshal(wfElement, out);
+
+ return out.toString(Charset.defaultCharset().toString());
+ }
+
+ private WORKFLOWAPP getWfApp() {
+ final START start = new START();
+ start.setTo("mr-node");
+
+ final KILL kill = new KILL();
+ kill.setName("fail");
+ kill.setMessage("Map/Reduce failed, error message[${wf:errorMessage(wf:lastErrorNode())}]");
+
+ final END end = new END();
+ end.setName("end");
+
+ final WORKFLOWAPP wfApp = new WORKFLOWAPP();
+ wfApp.setName("jaxb-example-wf");
+ wfApp.setStart(start);
+ wfApp.getDecisionOrForkOrJoin().add(getMapReduceAction());
+ wfApp.getDecisionOrForkOrJoin().add(kill);
+ wfApp.setEnd(end);
+
+ return wfApp;
+ }
+
+ private ACTION getMapReduceAction() {
+ final ACTION action = new ACTION();
+
+ action.setName("mr-node");
+ action.setMapReduce(getMapreduce());
+
+ final ACTIONTRANSITION okTransition = new ACTIONTRANSITION();
+ okTransition.setTo("end");
+ action.setOk(okTransition);
+
+ final ACTIONTRANSITION errorTransition = new ACTIONTRANSITION();
+ errorTransition.setTo("fail");
+ action.setError(errorTransition);
+
+ return action;
+ }
+
+ private MAPREDUCE getMapreduce() {
+ final MAPREDUCE mr = new MAPREDUCE();
+
+ mr.setResourceManager("${resourceManager}");
+ mr.setNameNode("${nameNode}");
+ mr.setPrepare(getPrepare());
+ mr.setConfiguration(getConfiguration());
+
+ return mr;
+ }
+
+ private CONFIGURATION getConfiguration() {
+ final String[][] nameValuePairs = {
+ {"mapred.job.queue.name", "${queueName}"},
+ {"mapred.mapper.class", "org.apache.oozie.example.SampleMapper"},
+ {"mapred.reducer.class", "org.apache.oozie.example.SampleReducer"},
+ {"mapred.map.tasks", "1"},
+ {"mapred.input.dir", "/user/${wf:user()}/${examplesRoot}/input-data/text"},
+ {"mapred.output.dir", "/user/${wf:user()}/${examplesRoot}/output-data/${outputDir}"}
+ };
+
+ final CONFIGURATION config = new CONFIGURATION();
+ final List<CONFIGURATION.Property> properties = config.getProperty();
+
+ for (final String[] pair : nameValuePairs) {
+ final CONFIGURATION.Property property = new CONFIGURATION.Property();
+ property.setName(pair[0]);
+ property.setValue(pair[1]);
+
+ properties.add(property);
+ }
+
+ return config;
+ }
+
+ private PREPARE getPrepare() {
+ final PREPARE prepare = new PREPARE();
+
+ final DELETE delete = new DELETE();
+ delete.setPath("${nameNode}/user/${wf:user()}/${examplesRoot}/output-data/${outputDir}");
+
+ prepare.getDelete().add(delete);
+
+ return prepare;
+ }
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestDistcpAction.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestDistcpAction.java b/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestDistcpAction.java
new file mode 100644
index 0000000..e377d5c
--- /dev/null
+++ b/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestDistcpAction.java
@@ -0,0 +1,89 @@
+/**
+ * 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.jobs.client.minitest;
+
+import org.apache.oozie.client.OozieClientException;
+import org.apache.oozie.fluentjob.api.GraphVisualization;
+import org.apache.oozie.fluentjob.api.action.DistcpAction;
+import org.apache.oozie.fluentjob.api.action.DistcpActionBuilder;
+import org.apache.oozie.fluentjob.api.action.Prepare;
+import org.apache.oozie.fluentjob.api.action.PrepareBuilder;
+import org.apache.oozie.fluentjob.api.action.SshActionBuilder;
+import org.apache.oozie.fluentjob.api.dag.Graph;
+import org.apache.oozie.fluentjob.api.serialization.WorkflowMarshaller;
+import org.apache.oozie.fluentjob.api.workflow.Workflow;
+import org.apache.oozie.fluentjob.api.workflow.WorkflowBuilder;
+import org.apache.oozie.test.WorkflowTestCase;
+
+import javax.xml.bind.JAXBException;
+import java.io.IOException;
+
+public class TestDistcpAction extends WorkflowTestCase {
+ public void testForkedDistcpActions() throws IOException, JAXBException, OozieClientException {
+ final Prepare prepare = new PrepareBuilder()
+ .withDelete("hdfs://localhost:8020/user/${wf:user()}/examples/output")
+ .build();
+
+ final DistcpAction parent = DistcpActionBuilder.create()
+ .withResourceManager(getJobTrackerUri())
+ .withNameNode(getNameNodeUri())
+ .withPrepare(prepare)
+ .withConfigProperty("mapred.job.queue.name", "default")
+ .withJavaOpts("-Dopt1 -Dopt2")
+ .withArg("arg1")
+ .build();
+
+ // We are reusing the definition of parent and only modifying and adding what is different.
+ final DistcpAction leftChild = DistcpActionBuilder.createFromExistingAction(parent)
+ .withParent(parent)
+ .withoutArg("arg1")
+ .withArg("arg2")
+ .build();
+
+ final DistcpAction rightChild = DistcpActionBuilder.createFromExistingAction(leftChild)
+ .withoutArg("arg2")
+ .withArg("arg3")
+ .build();
+
+ final Workflow workflow = new WorkflowBuilder()
+ .withName("simple-distcp-example")
+ .withDagContainingNode(parent).build();
+
+ SshActionBuilder.create()
+ .withParent(leftChild)
+ .withParent(rightChild)
+ .withHost("localhost")
+ .withCommand("pwd")
+ .build();
+
+ final String xml = WorkflowMarshaller.marshal(workflow);
+
+ System.out.println(xml);
+
+ GraphVisualization.workflowToPng(workflow, "simple-distcp-example-workflow.png");
+
+ final Graph intermediateGraph = new Graph(workflow);
+
+ GraphVisualization.graphToPng(intermediateGraph, "simple-distcp-example-graph.png");
+
+ log.debug("Workflow XML is:\n{0}", xml);
+
+ validate(xml);
+ }
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestEmailAction.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestEmailAction.java b/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestEmailAction.java
new file mode 100644
index 0000000..d46cee2
--- /dev/null
+++ b/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestEmailAction.java
@@ -0,0 +1,73 @@
+/**
+ * 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.jobs.client.minitest;
+
+import org.apache.oozie.client.OozieClientException;
+import org.apache.oozie.fluentjob.api.GraphVisualization;
+import org.apache.oozie.fluentjob.api.action.EmailActionBuilder;
+import org.apache.oozie.fluentjob.api.action.Node;
+import org.apache.oozie.fluentjob.api.dag.Graph;
+import org.apache.oozie.fluentjob.api.serialization.WorkflowMarshaller;
+import org.apache.oozie.fluentjob.api.workflow.Workflow;
+import org.apache.oozie.fluentjob.api.workflow.WorkflowBuilder;
+import org.apache.oozie.test.WorkflowTestCase;
+
+import javax.xml.bind.JAXBException;
+import java.io.IOException;
+
+public class TestEmailAction extends WorkflowTestCase {
+
+ public void testForkedEmailActions() throws JAXBException, IOException, OozieClientException {
+ final Node parent = EmailActionBuilder.create()
+ .withRecipient("somebody@apache.org")
+ .withSubject("Subject")
+ .withBody("This is a wonderful e-mail.")
+ .build();
+
+ EmailActionBuilder.create()
+ .withParent(parent)
+ .withRecipient("somebody.else@apache.org")
+ .withSubject("Re: Subject")
+ .withBody("This is an even more wonderful e-mail.")
+ .build();
+
+ EmailActionBuilder.create()
+ .withParent(parent)
+ .withRecipient("somebody@apache.org")
+ .withSubject("Re: Subject")
+ .withBody("No, this is the most wonderful e-mail.")
+ .build();
+
+ final Workflow workflow = new WorkflowBuilder()
+ .withName("simple-email-example")
+ .withDagContainingNode(parent).build();
+
+ GraphVisualization.workflowToPng(workflow, "simple-email-example-workflow.png");
+
+ final Graph intermediateGraph = new Graph(workflow);
+
+ GraphVisualization.graphToPng(intermediateGraph, "simple-email-example-graph.png");
+
+ final String xml = WorkflowMarshaller.marshal(workflow);
+
+ log.debug("Workflow XML is:\n{0}", xml);
+
+ validate(xml);
+ }
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestFSAction.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestFSAction.java b/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestFSAction.java
new file mode 100644
index 0000000..947360f
--- /dev/null
+++ b/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestFSAction.java
@@ -0,0 +1,72 @@
+/**
+ * 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.jobs.client.minitest;
+
+import org.apache.oozie.client.OozieClientException;
+import org.apache.oozie.fluentjob.api.GraphVisualization;
+import org.apache.oozie.fluentjob.api.action.Delete;
+import org.apache.oozie.fluentjob.api.action.FSAction;
+import org.apache.oozie.fluentjob.api.action.FSActionBuilder;
+import org.apache.oozie.fluentjob.api.action.Mkdir;
+import org.apache.oozie.fluentjob.api.dag.Graph;
+import org.apache.oozie.fluentjob.api.serialization.WorkflowMarshaller;
+import org.apache.oozie.fluentjob.api.workflow.Workflow;
+import org.apache.oozie.fluentjob.api.workflow.WorkflowBuilder;
+import org.apache.oozie.test.WorkflowTestCase;
+
+import javax.xml.bind.JAXBException;
+import java.io.IOException;
+import java.util.Date;
+
+public class TestFSAction extends WorkflowTestCase {
+
+ public void testTwoFSActions() throws JAXBException, IOException, OozieClientException {
+ final String hdfsPath = getFsTestCaseDir() + "/user/${wf:user()}/examples/output_" + new Date().getTime();
+
+ final Delete delete = new Delete(hdfsPath, true);
+
+ final Mkdir mkdir = new Mkdir(hdfsPath);
+
+ final FSAction parent = FSActionBuilder.create()
+ .withNameNode(getNameNodeUri())
+ .withDelete(delete)
+ .withMkdir(mkdir)
+ .build();
+
+ FSActionBuilder.createFromExistingAction(parent)
+ .withParent(parent)
+ .build();
+
+ final Workflow workflow = new WorkflowBuilder()
+ .withName("simple-fs-example")
+ .withDagContainingNode(parent).build();
+
+ final String xml = WorkflowMarshaller.marshal(workflow);
+
+ log.debug("Workflow XML is:\n{0}", xml);
+
+ GraphVisualization.workflowToPng(workflow, "simple-fs-example-workflow.png");
+
+ final Graph intermediateGraph = new Graph(workflow);
+
+ GraphVisualization.graphToPng(intermediateGraph, "simple-fs-example-graph.png");
+
+ validate(xml);
+ }
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestHive2Action.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestHive2Action.java b/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestHive2Action.java
new file mode 100644
index 0000000..bb4fa98
--- /dev/null
+++ b/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestHive2Action.java
@@ -0,0 +1,83 @@
+/**
+ * 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.jobs.client.minitest;
+
+import org.apache.oozie.client.OozieClientException;
+import org.apache.oozie.fluentjob.api.GraphVisualization;
+import org.apache.oozie.fluentjob.api.action.Hive2Action;
+import org.apache.oozie.fluentjob.api.action.Hive2ActionBuilder;
+import org.apache.oozie.fluentjob.api.action.Prepare;
+import org.apache.oozie.fluentjob.api.action.PrepareBuilder;
+import org.apache.oozie.fluentjob.api.dag.Graph;
+import org.apache.oozie.fluentjob.api.serialization.WorkflowMarshaller;
+import org.apache.oozie.fluentjob.api.workflow.Workflow;
+import org.apache.oozie.fluentjob.api.workflow.WorkflowBuilder;
+import org.apache.oozie.test.WorkflowTestCase;
+
+import javax.xml.bind.JAXBException;
+import java.io.IOException;
+
+public class TestHive2Action extends WorkflowTestCase {
+ public void testForkedHive2Actions() throws IOException, JAXBException, OozieClientException {
+ final Prepare prepare = new PrepareBuilder()
+ .withDelete("hdfs://localhost:8020/user/${wf:user()}/examples/output")
+ .build();
+
+ final Hive2Action parent = Hive2ActionBuilder.create()
+ .withResourceManager(getJobTrackerUri())
+ .withNameNode(getNameNodeUri())
+ .withPrepare(prepare)
+ .withConfigProperty("mapred.job.queue.name", "default")
+ .withArg("arg1")
+ .withJdbcUrl("jdbc://hive2")
+ .withPassword("secret")
+ .withScript("hive2.sql")
+ .build();
+
+ // We are reusing the definition of parent and only modifying and adding what is different.
+ final Hive2Action leftChild = Hive2ActionBuilder.createFromExistingAction(parent)
+ .withParent(parent)
+ .withoutArg("arg1")
+ .withArg("arg2")
+ .build();
+
+ Hive2ActionBuilder.createFromExistingAction(leftChild)
+ .withoutArg("arg2")
+ .withArg("arg3")
+ .build();
+
+ final Workflow workflow = new WorkflowBuilder()
+ .withName("simple-hive2-example")
+ .withDagContainingNode(parent).build();
+
+ final String xml = WorkflowMarshaller.marshal(workflow);
+
+ System.out.println(xml);
+
+ GraphVisualization.workflowToPng(workflow, "simple-hive2-example-workflow.png");
+
+ final Graph intermediateGraph = new Graph(workflow);
+
+ GraphVisualization.graphToPng(intermediateGraph, "simple-hive2-example-graph.png");
+
+ log.debug("Workflow XML is:\n{0}", xml);
+
+ validate(xml);
+ }
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestHiveAction.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestHiveAction.java b/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestHiveAction.java
new file mode 100644
index 0000000..017487d
--- /dev/null
+++ b/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestHiveAction.java
@@ -0,0 +1,81 @@
+/**
+ * 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.jobs.client.minitest;
+
+import org.apache.oozie.client.OozieClientException;
+import org.apache.oozie.fluentjob.api.GraphVisualization;
+import org.apache.oozie.fluentjob.api.action.HiveAction;
+import org.apache.oozie.fluentjob.api.action.HiveActionBuilder;
+import org.apache.oozie.fluentjob.api.action.Prepare;
+import org.apache.oozie.fluentjob.api.action.PrepareBuilder;
+import org.apache.oozie.fluentjob.api.dag.Graph;
+import org.apache.oozie.fluentjob.api.serialization.WorkflowMarshaller;
+import org.apache.oozie.fluentjob.api.workflow.Workflow;
+import org.apache.oozie.fluentjob.api.workflow.WorkflowBuilder;
+import org.apache.oozie.test.WorkflowTestCase;
+
+import javax.xml.bind.JAXBException;
+import java.io.IOException;
+
+public class TestHiveAction extends WorkflowTestCase {
+ public void testForkedHiveActions() throws IOException, JAXBException, OozieClientException {
+ final Prepare prepare = new PrepareBuilder()
+ .withDelete("hdfs://localhost:8020/user/${wf:user()}/examples/output")
+ .build();
+
+ final HiveAction parent = HiveActionBuilder.create()
+ .withResourceManager(getJobTrackerUri())
+ .withNameNode(getNameNodeUri())
+ .withPrepare(prepare)
+ .withConfigProperty("mapred.job.queue.name", "default")
+ .withArg("arg1")
+ .withScript("hive2.sql")
+ .build();
+
+ // We are reusing the definition of parent and only modifying and adding what is different.
+ final HiveAction leftChild = HiveActionBuilder.createFromExistingAction(parent)
+ .withParent(parent)
+ .withoutArg("arg1")
+ .withArg("arg2")
+ .build();
+
+ HiveActionBuilder.createFromExistingAction(leftChild)
+ .withoutArg("arg2")
+ .withArg("arg3")
+ .build();
+
+ final Workflow workflow = new WorkflowBuilder()
+ .withName("simple-hive-example")
+ .withDagContainingNode(parent).build();
+
+ final String xml = WorkflowMarshaller.marshal(workflow);
+
+ System.out.println(xml);
+
+ GraphVisualization.workflowToPng(workflow, "simple-hive-example-workflow.png");
+
+ final Graph intermediateGraph = new Graph(workflow);
+
+ GraphVisualization.graphToPng(intermediateGraph, "simple-hive-example-graph.png");
+
+ log.debug("Workflow XML is:\n{0}", xml);
+
+ validate(xml);
+ }
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestJavaAction.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestJavaAction.java b/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestJavaAction.java
new file mode 100644
index 0000000..397144b
--- /dev/null
+++ b/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestJavaAction.java
@@ -0,0 +1,92 @@
+/**
+ * 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.jobs.client.minitest;
+
+import org.apache.oozie.client.OozieClientException;
+import org.apache.oozie.fluentjob.api.GraphVisualization;
+import org.apache.oozie.fluentjob.api.action.JavaAction;
+import org.apache.oozie.fluentjob.api.action.JavaActionBuilder;
+import org.apache.oozie.fluentjob.api.action.Prepare;
+import org.apache.oozie.fluentjob.api.action.PrepareBuilder;
+import org.apache.oozie.fluentjob.api.dag.Graph;
+import org.apache.oozie.fluentjob.api.serialization.WorkflowMarshaller;
+import org.apache.oozie.fluentjob.api.workflow.Workflow;
+import org.apache.oozie.fluentjob.api.workflow.WorkflowBuilder;
+import org.apache.oozie.test.WorkflowTestCase;
+
+import javax.xml.bind.JAXBException;
+import java.io.IOException;
+
+public class TestJavaAction extends WorkflowTestCase {
+ public void testForkedJavaActions() throws IOException, JAXBException, OozieClientException {
+ final Prepare prepare = new PrepareBuilder()
+ .withDelete("hdfs://localhost:8020/user/${wf:user()}/examples/output")
+ .build();
+
+ final JavaAction parent = JavaActionBuilder.create()
+ .withResourceManager(getJobTrackerUri())
+ .withNameNode(getNameNodeUri())
+ .withPrepare(prepare)
+ .withConfigProperty("mapred.job.queue.name", "default")
+ .withArg("arg1")
+ .withMainClass("org.apache.oozie.MyFirstMainClass")
+ .withJavaOptsString("-Dopt1a -Dopt1b")
+ .withCaptureOutput(true)
+ .build();
+
+ // We are reusing the definition of parent and only modifying and adding what is different.
+ final JavaAction leftChild = JavaActionBuilder.createFromExistingAction(parent)
+ .withParent(parent)
+ .withoutArg("arg1")
+ .withArg("arg2")
+ .withJavaOptsString(null)
+ .withJavaOpt("-Dopt2a")
+ .withJavaOpt("-Dopt2b")
+ .withCaptureOutput(false)
+ .build();
+
+ JavaActionBuilder.createFromExistingAction(leftChild)
+ .withoutArg("arg2")
+ .withArg("arg3")
+ .withJavaOptsString(null)
+ .withoutJavaOpt("-Dopt2a")
+ .withoutJavaOpt("-Dopt2b")
+ .withJavaOpt("-Dopt3a")
+ .withJavaOpt("-Dopt3b")
+ .build();
+
+ final Workflow workflow = new WorkflowBuilder()
+ .withName("simple-java-example")
+ .withDagContainingNode(parent).build();
+
+ final String xml = WorkflowMarshaller.marshal(workflow);
+
+ System.out.println(xml);
+
+ GraphVisualization.workflowToPng(workflow, "simple-java-example-workflow.png");
+
+ final Graph intermediateGraph = new Graph(workflow);
+
+ GraphVisualization.graphToPng(intermediateGraph, "simple-java-example-graph.png");
+
+ log.debug("Workflow XML is:\n{0}", xml);
+
+ validate(xml);
+ }
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestMapReduceAction.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestMapReduceAction.java b/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestMapReduceAction.java
new file mode 100644
index 0000000..573208b
--- /dev/null
+++ b/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestMapReduceAction.java
@@ -0,0 +1,76 @@
+/**
+ * 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.jobs.client.minitest;
+
+import org.apache.oozie.client.OozieClientException;
+import org.apache.oozie.fluentjob.api.GraphVisualization;
+import org.apache.oozie.fluentjob.api.action.MapReduceAction;
+import org.apache.oozie.fluentjob.api.action.MapReduceActionBuilder;
+import org.apache.oozie.fluentjob.api.action.Prepare;
+import org.apache.oozie.fluentjob.api.action.PrepareBuilder;
+import org.apache.oozie.fluentjob.api.dag.Graph;
+import org.apache.oozie.fluentjob.api.serialization.WorkflowMarshaller;
+import org.apache.oozie.fluentjob.api.workflow.Workflow;
+import org.apache.oozie.fluentjob.api.workflow.WorkflowBuilder;
+import org.apache.oozie.test.WorkflowTestCase;
+
+import javax.xml.bind.JAXBException;
+import java.io.IOException;
+
+public class TestMapReduceAction extends WorkflowTestCase {
+ public void testForkedMapReduceActions() throws IOException, JAXBException, OozieClientException {
+ final Prepare prepare = new PrepareBuilder()
+ .withDelete("hdfs://localhost:8020/user/${wf:user()}/examples/output")
+ .build();
+
+ final MapReduceAction parent = MapReduceActionBuilder.create()
+ .withResourceManager(getJobTrackerUri())
+ .withNameNode(getNameNodeUri())
+ .withPrepare(prepare)
+ .withConfigProperty("mapred.job.queue.name", "default")
+ .withConfigProperty("mapred.mapper.class", "org.apache.hadoop.mapred.lib.IdentityMapper")
+ .withConfigProperty("mapred.input.dir", "/user/${wf:user()}/examples/input")
+ .withConfigProperty("mapred.output.dir", "/user/${wf:user()}/examples/output")
+ .build();
+
+ // We are reusing the definition of mrAction1 and only modifying and adding what is different.
+ final MapReduceAction leftChild = MapReduceActionBuilder.createFromExistingAction(parent)
+ .withParent(parent)
+ .build();
+
+ MapReduceActionBuilder.createFromExistingAction(leftChild)
+ .build();
+
+ final Workflow workflow = new WorkflowBuilder()
+ .withName("simple-map-reduce-example")
+ .withDagContainingNode(parent).build();
+
+ final String xml = WorkflowMarshaller.marshal(workflow);
+
+ System.out.println(xml);
+
+ GraphVisualization.workflowToPng(workflow, "simple-map-reduce-example-workflow.png");
+
+ final Graph intermediateGraph = new Graph(workflow);
+
+ GraphVisualization.graphToPng(intermediateGraph, "simple-map-reduce-example-graph.png");
+
+ validate(xml);
+ }
+}
http://git-wip-us.apache.org/repos/asf/oozie/blob/8a0a6487/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestPigAction.java
----------------------------------------------------------------------
diff --git a/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestPigAction.java b/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestPigAction.java
new file mode 100644
index 0000000..b4daf33
--- /dev/null
+++ b/fluent-job/fluent-job-client/src/test/java/org/apache/oozie/jobs/client/minitest/TestPigAction.java
@@ -0,0 +1,81 @@
+/**
+ * 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.jobs.client.minitest;
+
+import org.apache.oozie.client.OozieClientException;
+import org.apache.oozie.fluentjob.api.GraphVisualization;
+import org.apache.oozie.fluentjob.api.action.PigAction;
+import org.apache.oozie.fluentjob.api.action.PigActionBuilder;
+import org.apache.oozie.fluentjob.api.action.Prepare;
+import org.apache.oozie.fluentjob.api.action.PrepareBuilder;
+import org.apache.oozie.fluentjob.api.dag.Graph;
+import org.apache.oozie.fluentjob.api.serialization.WorkflowMarshaller;
+import org.apache.oozie.fluentjob.api.workflow.Workflow;
+import org.apache.oozie.fluentjob.api.workflow.WorkflowBuilder;
+import org.apache.oozie.test.WorkflowTestCase;
+
+import javax.xml.bind.JAXBException;
+import java.io.IOException;
+
+public class TestPigAction extends WorkflowTestCase {
+ public void testForkedPigActions() throws IOException, JAXBException, OozieClientException {
+ final Prepare prepare = new PrepareBuilder()
+ .withDelete("hdfs://localhost:8020/user/${wf:user()}/examples/output")
+ .build();
+
+ final PigAction parent = PigActionBuilder.create()
+ .withResourceManager(getJobTrackerUri())
+ .withNameNode(getNameNodeUri())
+ .withPrepare(prepare)
+ .withConfigProperty("mapred.job.queue.name", "default")
+ .withArg("arg1")
+ .withScript("pig.sql")
+ .build();
+
+ // We are reusing the definition of parent and only modifying and adding what is different.
+ final PigAction leftChild = PigActionBuilder.createFromExistingAction(parent)
+ .withParent(parent)
+ .withoutArg("arg1")
+ .withArg("arg2")
+ .build();
+
+ PigActionBuilder.createFromExistingAction(leftChild)
+ .withoutArg("arg2")
+ .withArg("arg3")
+ .build();
+
+ final Workflow workflow = new WorkflowBuilder()
+ .withName("simple-pig-example")
+ .withDagContainingNode(parent).build();
+
+ final String xml = WorkflowMarshaller.marshal(workflow);
+
+ System.out.println(xml);
+
+ GraphVisualization.workflowToPng(workflow, "simple-pig-example-workflow.png");
+
+ final Graph intermediateGraph = new Graph(workflow);
+
+ GraphVisualization.graphToPng(intermediateGraph, "simple-pig-example-graph.png");
+
+ log.debug("Workflow XML is:\n{0}", xml);
+
+ validate(xml);
+ }
+}