You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@falcon.apache.org by ra...@apache.org on 2014/11/05 18:26:31 UTC
git commit: FALCON-861 Add ACL tests for falcon client and ACL
update. Contributed by Raghav Kumar Gautam
Repository: incubator-falcon
Updated Branches:
refs/heads/master 437109646 -> 8fc5ff611
FALCON-861 Add ACL tests for falcon client and ACL update. Contributed by Raghav Kumar Gautam
Project: http://git-wip-us.apache.org/repos/asf/incubator-falcon/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-falcon/commit/8fc5ff61
Tree: http://git-wip-us.apache.org/repos/asf/incubator-falcon/tree/8fc5ff61
Diff: http://git-wip-us.apache.org/repos/asf/incubator-falcon/diff/8fc5ff61
Branch: refs/heads/master
Commit: 8fc5ff611439d632217f689581769df1a39df377
Parents: 4371096
Author: Raghav Kumar Gautam <ra...@apache.org>
Authored: Wed Nov 5 09:26:11 2014 -0800
Committer: Raghav Kumar Gautam <ra...@apache.org>
Committed: Wed Nov 5 09:26:11 2014 -0800
----------------------------------------------------------------------
falcon-regression/CHANGES.txt | 3 +
falcon-regression/README.md | 7 +
falcon-regression/merlin-core/pom.xml | 5 +
.../core/enumsAndConstants/MerlinConstants.java | 15 +-
.../core/interfaces/FalconClientBuilder.java | 178 +++++++++++++++++++
.../core/interfaces/IEntityManagerHelper.java | 33 ++++
.../core/supportClasses/ExecResult.java | 25 ++-
.../falcon/regression/core/util/AssertUtil.java | 13 ++
.../falcon/regression/core/util/ExecUtil.java | 77 +++-----
.../falcon/regression/core/util/FileUtil.java | 47 +++++
.../falcon/regression/core/util/OSUtil.java | 3 +
.../regression/security/AclValidationTest.java | 2 +-
.../regression/security/ClusterAclTest.java | 2 +-
.../regression/security/FalconClientTest.java | 106 +++++++++++
.../falcon/regression/security/FeedAclTest.java | 43 ++++-
.../regression/security/ProcessAclTest.java | 54 +++++-
falcon-regression/pom.xml | 5 +
17 files changed, 550 insertions(+), 68 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/8fc5ff61/falcon-regression/CHANGES.txt
----------------------------------------------------------------------
diff --git a/falcon-regression/CHANGES.txt b/falcon-regression/CHANGES.txt
index 2854075..0f88e29 100644
--- a/falcon-regression/CHANGES.txt
+++ b/falcon-regression/CHANGES.txt
@@ -5,6 +5,9 @@ Trunk (Unreleased)
INCOMPATIBLE CHANGES
NEW FEATURES
+ FALCON-861 Add ACL tests for falcon client and ACL update
+ (Raghav Kumar Gautam)
+
FALCON-844 List instances tests (Paul Isaychuk via Ruslan Ostafiychuk)
FALCON-841 Test falcon process with different frequencies
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/8fc5ff61/falcon-regression/README.md
----------------------------------------------------------------------
diff --git a/falcon-regression/README.md b/falcon-regression/README.md
index 12b15dd..abfa689 100644
--- a/falcon-regression/README.md
+++ b/falcon-regression/README.md
@@ -126,6 +126,13 @@ For testing with kerberos set keytabs properties for different users:
falcon.super2.user.keytab=/home/qa/hadoopqa/keytabs/falcon2.headless.keytab
other.user.keytab=/home/qa/hadoopqa/keytabs/root.headless.keytab
+Testing on Windows
+------------------
+Some tests switch user to run commands as a different user. Location of binary to switch user is
+configurable:
+
+ windows.su.binary=ExecuteAs.exe
+
Automatic capture of oozie logs
-------------------------------
For full falcon regression runs. It might be desirable to pull all oozie job
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/8fc5ff61/falcon-regression/merlin-core/pom.xml
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/pom.xml b/falcon-regression/merlin-core/pom.xml
index 21641a3..a9699b9 100644
--- a/falcon-regression/merlin-core/pom.xml
+++ b/falcon-regression/merlin-core/pom.xml
@@ -159,5 +159,10 @@
<groupId>org.apache.falcon</groupId>
<artifactId>falcon-client</artifactId>
</dependency>
+
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-exec</artifactId>
+ </dependency>
</dependencies>
</project>
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/8fc5ff61/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/enumsAndConstants/MerlinConstants.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/enumsAndConstants/MerlinConstants.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/enumsAndConstants/MerlinConstants.java
index dab5d2c..d6780f3 100644
--- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/enumsAndConstants/MerlinConstants.java
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/enumsAndConstants/MerlinConstants.java
@@ -46,7 +46,10 @@ public final class MerlinConstants {
Config.getProperty("current_user.group.name", "users");
/** a user that does not belong to the group of current user. */
- public static final String DIFFERENT_USER = Config.getProperty("other.user.name", "root");
+ public static final String DIFFERENT_USER_NAME = Config.getProperty("other.user.name", "root");
+
+ /** a user that does not belong to the group of current user. */
+ public static final String DIFFERENT_USER_GROUP = Config.getProperty("other.user.name", "root");
/** falcon super user. */
public static final String FALCON_SUPER_USER_NAME =
@@ -59,6 +62,7 @@ public final class MerlinConstants {
private static final String USER_2_KEYTAB_STR = "user2_keytab";
public static final String USER2_NAME;
private static HashMap<String, String> keyTabMap;
+ private static HashMap<String, String> passwordMap;
public static final String ACL_OWNER = Config.getProperty("ACL.OWNER", RequestKeys.CURRENT_USER);
public static final String ACL_GROUP = Config.getProperty("ACL.GROUP", "default");
public static final String USER_REALM = Config.getProperty("USER.REALM", "");
@@ -81,11 +85,18 @@ public final class MerlinConstants {
keyTabMap.put(user2Name, user2Keytab);
keyTabMap.put(FALCON_SUPER_USER_NAME, Config.getProperty("falcon.super.user.keytab"));
keyTabMap.put(FALCON_SUPER_USER2_NAME, Config.getProperty("falcon.super.user2.keytab"));
- keyTabMap.put(DIFFERENT_USER, Config.getProperty("other.user.keytab"));
+ keyTabMap.put(DIFFERENT_USER_NAME, Config.getProperty("other.user.keytab"));
+ passwordMap = new HashMap<String, String>();
+ passwordMap.put(DIFFERENT_USER_NAME, Config.getProperty("other.user.password"));
}
public static String getKeytabForUser(String user) {
Assert.assertTrue(keyTabMap.containsKey(user), "Unknown user: " + user);
return keyTabMap.get(user);
}
+
+ public static String getPasswordForUser(String user) {
+ Assert.assertTrue(passwordMap.containsKey(user), "Unknown user: " + user);
+ return passwordMap.get(user);
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/8fc5ff61/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/interfaces/FalconClientBuilder.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/interfaces/FalconClientBuilder.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/interfaces/FalconClientBuilder.java
new file mode 100644
index 0000000..02b7529
--- /dev/null
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/interfaces/FalconClientBuilder.java
@@ -0,0 +1,178 @@
+/**
+ * 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.falcon.regression.core.interfaces;
+
+import org.apache.commons.exec.CommandLine;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.builder.Builder;
+import org.apache.falcon.regression.core.enumsAndConstants.MerlinConstants;
+import org.apache.falcon.regression.core.util.Config;
+import org.apache.falcon.regression.core.util.OSUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * FalconClientBuilder is to be used for launching falcon client command.
+ */
+public class FalconClientBuilder implements Builder<CommandLine> {
+ private final String user;
+ private final CommandLine commandLine;
+ private final List<String> args;
+ private final SuType suType;
+
+ private enum SuType {
+ /**
+ * Takes care of switching user on linux. Current implemented through sudo.
+ */
+ LIN_SUDO {
+ @Override
+ public CommandLine getCommandLine(String user) {
+ return CommandLine.parse("sudo").addArgument("-u")
+ .addArgument(user).addArgument(falconClientBinary);
+ }
+ @Override
+ public void addArgsToCommandLine(CommandLine commandLine, List<String> args) {
+ for (String arg : args) {
+ commandLine.addArgument(arg);
+ }
+ }
+ },
+ /**
+ * Takes care of switching user on windows. Needs to be implemented.
+ */
+ WIN_SU {
+ @Override
+ public CommandLine getCommandLine(String user) {
+ return CommandLine.parse(OSUtil.WIN_SU_BINARY)
+ .addArgument("-u").addArgument(user)
+ .addArgument("-p").addArgument(MerlinConstants.getPasswordForUser(user))
+ .addArgument(falconClientBinary);
+ }
+ @Override
+ public void addArgsToCommandLine(CommandLine commandLine, List<String> args) {
+ String lastArg = StringUtils.join(args, " ");
+ commandLine.addArgument(lastArg, true);
+ }
+ },
+ /**
+ * Takes care of the case where no user switch is required.
+ */
+ NONE {
+ @Override
+ public CommandLine getCommandLine(String user) {
+ return CommandLine.parse(falconClientBinary);
+ }
+ @Override
+ public void addArgsToCommandLine(CommandLine commandLine, List<String> args) {
+ for (String arg : args) {
+ commandLine.addArgument(arg);
+ }
+ }
+ };
+
+ private static final String falconClientBinary =
+ Config.getProperty("falcon.client.binary", "falcon");
+ public abstract void addArgsToCommandLine(CommandLine commandLine, List<String> args);
+ public abstract CommandLine getCommandLine(String user);
+ }
+
+ private FalconClientBuilder(String user) {
+ this.user = user;
+ args = new ArrayList<String>();
+ if (user == null) {
+ suType = SuType.NONE;
+ commandLine = suType.getCommandLine(null);
+ } else {
+ if (OSUtil.IS_WINDOWS) {
+ suType = SuType.WIN_SU;
+ commandLine = suType.getCommandLine(user);
+ } else {
+ suType = SuType.LIN_SUDO;
+ //attempting sudo su - root -c "falcon admin -version"
+ commandLine = suType.getCommandLine(user);
+ }
+ }
+ }
+
+ /**
+ * Get an instance of FalconClientBuilder
+ * @return instance of FalconClientBuilder
+ */
+ public static FalconClientBuilder getBuilder() {
+ return new FalconClientBuilder(null);
+ }
+
+ /**
+ * Get an instance of FalconClientBuilder for the given user. It would do commandline
+ * construction in a way that the final command is run as given user.
+ * @return instance of FalconClientBuilder
+ */
+ public static FalconClientBuilder getBuilder(String user) {
+ return new FalconClientBuilder(user);
+ }
+
+ /**
+ * Add the given argument
+ * @param arg argument to be added to builder
+ * @return this
+ */
+ private FalconClientBuilder addArg(String arg) {
+ args.add(arg);
+ return this;
+ }
+
+ /**
+ * Create submit command
+ * @param entityType type of the entity
+ * @param fileName file containing the entity to be submitted
+ * @return this
+ */
+ public FalconClientBuilder getSubmitCommand(String entityType, String fileName) {
+ addArg("entity").addArg("-submit");
+ addArg("-type").addArg(entityType);
+ addArg("-file").addArg(fileName);
+ return this;
+ }
+
+ /**
+ * Create delete command
+ * @param entityType type of the entity
+ * @param entityName name of the entity to be deleted
+ * @return this
+ */
+ public FalconClientBuilder getDeleteCommand(String entityType, String entityName) {
+ addArg("entity").addArg("-delete");
+ addArg("-type").addArg(entityType);
+ addArg("-name").addArg(entityName);
+ return this;
+ }
+
+
+ /**
+ * Build the CommandLine object for this FalconClientBuilder
+ * @return instance of CommandLine object
+ */
+ @Override
+ public CommandLine build() {
+ suType.addArgsToCommandLine(commandLine, args);
+ return new CommandLine(commandLine);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/8fc5ff61/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/interfaces/IEntityManagerHelper.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/interfaces/IEntityManagerHelper.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/interfaces/IEntityManagerHelper.java
index 7264142..e1d808e 100644
--- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/interfaces/IEntityManagerHelper.java
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/interfaces/IEntityManagerHelper.java
@@ -19,12 +19,15 @@
package org.apache.falcon.regression.core.interfaces;
import com.jcraft.jsch.JSchException;
+import org.apache.commons.exec.CommandLine;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.falcon.regression.core.response.InstancesSummaryResult;
import org.apache.falcon.regression.core.response.InstancesResult;
import org.apache.falcon.regression.core.response.ServiceResponse;
+import org.apache.falcon.regression.core.supportClasses.ExecResult;
import org.apache.falcon.regression.core.util.Config;
import org.apache.falcon.regression.core.util.ExecUtil;
+import org.apache.falcon.regression.core.util.FileUtil;
import org.apache.falcon.regression.core.util.HCatUtil;
import org.apache.falcon.regression.core.util.InstanceUtil;
import org.apache.falcon.regression.core.util.OSUtil;
@@ -538,6 +541,36 @@ public abstract class IEntityManagerHelper {
}
/**
+ * Submit an entity through falcon client.
+ * @param entityStr string of the entity to be submitted
+ * @return
+ * @throws IOException
+ */
+ public ExecResult clientSubmit(final String entityStr) throws IOException {
+ LOGGER.info("Submitting " + getEntityType() + " through falcon client: \n"
+ + Util.prettyPrintXml(entityStr));
+ final String fileName = FileUtil.writeEntityToFile(entityStr);
+ final CommandLine commandLine = FalconClientBuilder.getBuilder()
+ .getSubmitCommand(getEntityType(), fileName).build();
+ return ExecUtil.executeCommand(commandLine);
+ }
+
+ /**
+ * Delete an entity through falcon client.
+ * @param entityStr string of the entity to be submitted
+ * @return
+ * @throws IOException
+ */
+ public ExecResult clientDelete(final String entityStr, String user) throws IOException {
+ final String entityName = getEntityName(entityStr);
+ LOGGER.info("Deleting " + getEntityType() + ": " + entityName);
+ final CommandLine commandLine = FalconClientBuilder.getBuilder(user)
+ .getDeleteCommand(getEntityType(), entityName).build();
+ return ExecUtil.executeCommand(commandLine);
+ }
+
+
+ /**
* Retrieves entities summary.
* @param clusterName compulsory parameter for request
* @param params list of optional parameters
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/8fc5ff61/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/supportClasses/ExecResult.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/supportClasses/ExecResult.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/supportClasses/ExecResult.java
index f878aa8..c5172eb 100644
--- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/supportClasses/ExecResult.java
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/supportClasses/ExecResult.java
@@ -18,22 +18,31 @@
package org.apache.falcon.regression.core.supportClasses;
+import org.apache.commons.exec.CommandLine;
+
public final class ExecResult {
private final int exitVal;
private final String output;
private final String error;
+ private final CommandLine commandLine;
- public ExecResult(final int exitVal, final String output, final String error) {
+ public ExecResult(CommandLine commandLine, final int exitVal, final String output,
+ final String error) {
this.exitVal = exitVal;
this.output = output;
this.error = error;
+ this.commandLine = commandLine;
}
public int getExitVal() {
return exitVal;
}
+ public boolean hasSuceeded() {
+ return exitVal == 0;
+ }
+
public String getOutput() {
return output;
}
@@ -41,4 +50,18 @@ public final class ExecResult {
public String getError() {
return error;
}
+
+ public CommandLine getCommandLine() {
+ return commandLine;
+ }
+
+ @Override
+ public String toString() {
+ return "ExecResult{" +
+ "exitVal=" + exitVal +
+ ", output='" + output + '\'' +
+ ", error='" + error + '\'' +
+ ", commandLine=" + commandLine +
+ '}';
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/8fc5ff61/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/AssertUtil.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/AssertUtil.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/AssertUtil.java
index 569d1f3..3384af0 100644
--- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/AssertUtil.java
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/AssertUtil.java
@@ -24,6 +24,7 @@ import org.apache.falcon.regression.core.bundle.Bundle;
import org.apache.falcon.regression.core.response.APIResult;
import org.apache.falcon.regression.core.response.InstancesResult;
import org.apache.falcon.regression.core.response.ServiceResponse;
+import org.apache.falcon.regression.core.supportClasses.ExecResult;
import org.apache.hadoop.fs.ContentSummary;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
@@ -207,6 +208,18 @@ public final class AssertUtil {
}
/**
+ * Assert that command executed unsuccessfully
+ *
+ * @param execResult ExecResult of the command execution
+ */
+ public static void assertFailed(ExecResult execResult, String expectedMessage) {
+ Assert.assertFalse(execResult.hasSuceeded(),
+ "Unexpectedly succeeded execResult: " + execResult);
+ Assert.assertTrue(execResult.getError().contains(expectedMessage),
+ "Expected error: " + expectedMessage + " in execResult: " + execResult);
+ }
+
+ /**
* Checks that ServiceResponse status is status FAILED with some status code.
*
* @param response ServiceResponse
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/8fc5ff61/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/ExecUtil.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/ExecUtil.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/ExecUtil.java
index d240e76..8dcb202 100644
--- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/ExecUtil.java
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/ExecUtil.java
@@ -23,11 +23,16 @@ import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.UserInfo;
-import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.commons.exec.CommandLine;
+import org.apache.commons.exec.DefaultExecutor;
+import org.apache.commons.exec.ExecuteWatchdog;
+import org.apache.commons.exec.PumpStreamHandler;
+import org.apache.falcon.regression.core.supportClasses.ExecResult;
import org.apache.log4j.Logger;
import org.testng.Assert;
import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -132,37 +137,29 @@ public final class ExecUtil {
}
public static ExecResult executeCommand(String command) {
- LOGGER.info("Command to be executed: " + command);
- StringBuilder errors = new StringBuilder();
- StringBuilder output = new StringBuilder();
+ return executeCommand(CommandLine.parse(command));
+ }
+ public static ExecResult executeCommand(CommandLine commandLine) {
+ LOGGER.info("Command to be executed: " + commandLine);
+ DefaultExecutor executor = new DefaultExecutor();
+ executor.setWatchdog(new ExecuteWatchdog(5 * 1000)); //timeout of 5 seconds
+ final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+ final ByteArrayOutputStream errStream = new ByteArrayOutputStream();
+ executor.setStreamHandler(new PumpStreamHandler(outStream, errStream));
+ int exitVal = 1;
try {
- Process process = Runtime.getRuntime().exec(command);
-
- BufferedReader errorReader =
- new BufferedReader(new InputStreamReader(process.getErrorStream()));
- BufferedReader consoleReader =
- new BufferedReader(new InputStreamReader(process.getInputStream()));
-
- String line;
- while ((line = errorReader.readLine()) != null) {
- errors.append(line).append("\n");
- }
-
- while ((line = consoleReader.readLine()) != null) {
- output.append(line).append("\n");
- }
- final int exitVal = process.waitFor();
- LOGGER.info("exitVal: " + exitVal);
- LOGGER.info("output: " + output);
- LOGGER.info("errors: " + errors);
- return new ExecResult(exitVal, output.toString().trim(), errors.toString().trim());
- } catch (InterruptedException e) {
- Assert.fail("Process execution failed:" + ExceptionUtils.getStackTrace(e));
+ exitVal = executor.execute(commandLine);
} catch (IOException e) {
- Assert.fail("Process execution failed:" + ExceptionUtils.getStackTrace(e));
+ LOGGER.warn("Caught exception: " + e);
}
- return null;
+ final String output = outStream.toString();
+ final String errors = errStream.toString();
+
+ LOGGER.info("exitVal: " + exitVal);
+ LOGGER.info("output: " + output);
+ LOGGER.info("errors: " + errors);
+ return new ExecResult(commandLine, exitVal, output.trim(), errors.trim());
}
public static int executeCommandGetExitCode(String command) {
@@ -206,28 +203,4 @@ public final class ExecUtil {
}
}
- private static final class ExecResult {
-
- private final int exitVal;
- private final String output;
- private final String error;
-
- private ExecResult(final int exitVal, final String output, final String error) {
- this.exitVal = exitVal;
- this.output = output;
- this.error = error;
- }
-
- public int getExitVal() {
- return exitVal;
- }
-
- public String getOutput() {
- return output;
- }
-
- public String getError() {
- return error;
- }
- }
}
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/8fc5ff61/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/FileUtil.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/FileUtil.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/FileUtil.java
new file mode 100644
index 0000000..1a97e1d
--- /dev/null
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/FileUtil.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.falcon.regression.core.util;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.log4j.Logger;
+
+import java.io.File;
+import java.io.IOException;
+
+public class FileUtil {
+ private static final Logger logger = Logger.getLogger(FileUtil.class);
+ private FileUtil() {
+ }
+
+ /**
+ * Writes an entity to a file and returns the filename.
+ * @param entity to be written
+ * @return name of the file
+ * @throws IOException
+ */
+ public static String writeEntityToFile(String entity) throws IOException {
+ final String entityName = Util.readEntityName(entity);
+ final File entityFile = new File(entityName + ".xml");
+ logger.info("attempting to write: " + entityName + " at location "
+ + entityFile.getAbsolutePath());
+ FileUtils.write(entityFile, entity);
+ return entityFile.getAbsolutePath();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/8fc5ff61/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/OSUtil.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/OSUtil.java b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/OSUtil.java
index 86d4d47..ed29d07 100644
--- a/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/OSUtil.java
+++ b/falcon-regression/merlin-core/src/main/java/org/apache/falcon/regression/core/util/OSUtil.java
@@ -29,6 +29,9 @@ public final class OSUtil {
}
public static final boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().startsWith("windows");
+ public static final String WIN_SU_BINARY =
+ Config.getProperty("windows.su.binary", "ExecuteAs.exe");
+
public static final String SEPARATOR = System.getProperty("file.separator", "/");
public static final String RESOURCES =
String.format("src%stest%sresources%s", SEPARATOR, SEPARATOR, SEPARATOR);
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/8fc5ff61/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/AclValidationTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/AclValidationTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/AclValidationTest.java
index d7f21b7..d0568d7 100644
--- a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/AclValidationTest.java
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/AclValidationTest.java
@@ -130,7 +130,7 @@ public class AclValidationTest extends BaseTestClass {
public Object[][] generateUserAndGroup() {
return new Object[][] {
{MerlinConstants.USER2_NAME, MerlinConstants.CURRENT_USER_GROUP},
- {MerlinConstants.CURRENT_USER_NAME, MerlinConstants.DIFFERENT_USER},
+ {MerlinConstants.CURRENT_USER_NAME, MerlinConstants.DIFFERENT_USER_NAME},
{MerlinConstants.CURRENT_USER_NAME, "nonexistinggroup"},
{"nonexistinguser", MerlinConstants.CURRENT_USER_GROUP},
};
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/8fc5ff61/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/ClusterAclTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/ClusterAclTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/ClusterAclTest.java
index affff56..74d9ccb 100644
--- a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/ClusterAclTest.java
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/ClusterAclTest.java
@@ -102,7 +102,7 @@ public class ClusterAclTest extends BaseTestClass {
);
final Object[][] notAllowedCombinations = MathUtil.crossProduct(
- new String[]{MerlinConstants.DIFFERENT_USER},
+ new String[]{MerlinConstants.DIFFERENT_USER_NAME},
new EntityOp[]{EntityOp.dependency, EntityOp.listing, EntityOp.definition},
new Boolean[]{false}
);
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/8fc5ff61/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/FalconClientTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/FalconClientTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/FalconClientTest.java
new file mode 100644
index 0000000..c18da3d
--- /dev/null
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/FalconClientTest.java
@@ -0,0 +1,106 @@
+/**
+ * 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.falcon.regression.security;
+
+import org.apache.falcon.regression.core.bundle.Bundle;
+import org.apache.falcon.regression.core.enumsAndConstants.MerlinConstants;
+import org.apache.falcon.regression.core.helpers.ColoHelper;
+import org.apache.falcon.regression.core.supportClasses.ExecResult;
+import org.apache.falcon.regression.core.util.AssertUtil;
+import org.apache.falcon.regression.core.util.BundleUtil;
+import org.apache.falcon.regression.core.util.HadoopUtil;
+import org.apache.falcon.regression.core.util.KerberosHelper;
+import org.apache.falcon.regression.core.util.OSUtil;
+import org.apache.falcon.regression.testHelper.BaseTestClass;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.log4j.Logger;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+
+@Test(groups = "authorization")
+public class FalconClientTest extends BaseTestClass {
+ private static final Logger LOGGER = Logger.getLogger(AclValidationTest.class);
+
+ private ColoHelper cluster = servers.get(0);
+ private FileSystem clusterFS = serverFS.get(0);
+ private String baseTestDir = baseHDFSDir + "/AuthorizationTest";
+ private String aggregateWorkflowDir = baseTestDir + "/aggregator";
+ private String feedInputPath = baseTestDir + "/input" + MINUTE_DATE_PATTERN;
+
+ @BeforeClass(alwaysRun = true)
+ public void uploadWorkflow() throws Exception {
+ HadoopUtil.uploadDir(clusterFS, aggregateWorkflowDir, OSUtil.RESOURCES_OOZIE);
+ }
+
+ @BeforeMethod(alwaysRun = true)
+ public void setup(Method method) throws Exception {
+ LOGGER.info("test name: " + method.getName());
+ Bundle bundle = BundleUtil.readELBundle();
+ bundles[0] = new Bundle(bundle, cluster);
+ bundles[0].generateUniqueBundle();
+ bundles[0].setInputFeedDataPath(feedInputPath);
+ bundles[0].setProcessWorkflow(aggregateWorkflowDir);
+ }
+
+ /**
+ * Test error thrown by falcon client, when acl of the submitted cluster has bad values
+ * @throws Exception
+ */
+ @Test
+ public void badClusterSubmit() throws Exception {
+ bundles[0].setCLusterACL(MerlinConstants.DIFFERENT_USER_NAME,
+ MerlinConstants.CURRENT_USER_GROUP, "*");
+ final String cluster = bundles[0].getClusters().get(0);
+ final ExecResult execResult = prism.getClusterHelper().clientSubmit(cluster);
+ AssertUtil.assertFailed(execResult, "cluster submission failed");
+ }
+
+ /**
+ * Test error thrown by falcon client, a user tries to delete a cluster that it should not be
+ * able to delete
+ * @throws Exception
+ */
+ @Test
+ public void badClusterDelete() throws Exception {
+ bundles[0].submitClusters(prism);
+ final String cluster = bundles[0].getClusters().get(0);
+ KerberosHelper.loginFromKeytab(MerlinConstants.DIFFERENT_USER_NAME);
+ final ExecResult execResult =
+ prism.getClusterHelper().clientDelete(cluster, MerlinConstants.DIFFERENT_USER_NAME);
+ AssertUtil.assertFailed(execResult, "cluster deletion failed");
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void tearDown() {
+ KerberosHelper.loginFromKeytab(MerlinConstants.CURRENT_USER_NAME);
+ removeBundles();
+ }
+
+ @AfterClass(alwaysRun = true)
+ public void tearDownClass() throws IOException {
+ cleanTestDirs();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/8fc5ff61/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/FeedAclTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/FeedAclTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/FeedAclTest.java
index 79e5db6..6767af3 100644
--- a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/FeedAclTest.java
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/FeedAclTest.java
@@ -24,6 +24,7 @@ import org.apache.falcon.regression.core.bundle.Bundle;
import org.apache.falcon.regression.core.enumsAndConstants.MerlinConstants;
import org.apache.falcon.regression.core.helpers.ColoHelper;
import org.apache.falcon.regression.core.interfaces.IEntityManagerHelper;
+import org.apache.falcon.regression.core.util.AssertUtil;
import org.apache.falcon.regression.core.util.BundleUtil;
import org.apache.falcon.regression.core.util.HadoopUtil;
import org.apache.falcon.regression.core.util.KerberosHelper;
@@ -104,7 +105,7 @@ public class FeedAclTest extends BaseTestClass {
);
final Object[][] notAllowedCombinations = MathUtil.crossProduct(
- new String[]{MerlinConstants.DIFFERENT_USER},
+ new String[]{MerlinConstants.DIFFERENT_USER_NAME},
falconReadOps,
new Boolean[]{false}
);
@@ -146,7 +147,7 @@ public class FeedAclTest extends BaseTestClass {
);
final Object[][] notAllowedCombinations = MathUtil.crossProduct(
- new String[]{MerlinConstants.DIFFERENT_USER},
+ new String[]{MerlinConstants.DIFFERENT_USER_NAME},
falconEditOps,
new Boolean[]{false}
);
@@ -189,7 +190,7 @@ public class FeedAclTest extends BaseTestClass {
);
final Object[][] notAllowedCombinations = MathUtil.crossProduct(
- new String[]{MerlinConstants.DIFFERENT_USER},
+ new String[]{MerlinConstants.DIFFERENT_USER_NAME},
new EntityOp[]{EntityOp.delete, EntityOp.update, EntityOp.schedule,
EntityOp.submitAndSchedule, EntityOp.suspend, EntityOp.resume},
new Boolean[]{false}
@@ -198,6 +199,42 @@ public class FeedAclTest extends BaseTestClass {
return MathUtil.append(allowedCombinations, notAllowedCombinations);
}
+ /**
+ * Test feed acl modification.
+ * @throws Exception
+ */
+ @Test
+ public void feedAclUpdate() throws Exception {
+ bundles[0].submitClusters(prism);
+ final String oldFeed = bundles[0].getInputFeedFromBundle();
+ AssertUtil.assertSucceeded(feedHelper.submitAndSchedule(oldFeed));
+ final FeedMerlin feedMerlin = new FeedMerlin(oldFeed);
+ feedMerlin.setACL(MerlinConstants.DIFFERENT_USER_NAME,
+ MerlinConstants.DIFFERENT_USER_GROUP, "*");
+ final String newFeed = feedMerlin.toString();
+ AssertUtil.assertSucceeded(feedHelper.update(oldFeed, newFeed));
+ //check that current user can't access the feed
+ for(EntityOp op : new EntityOp[]{EntityOp.status, EntityOp.dependency, EntityOp.listing,
+ EntityOp.definition}) {
+ final boolean executeRes =
+ op.executeAs(MerlinConstants.DIFFERENT_USER_NAME, feedHelper, newFeed);
+ Assert.assertFalse(executeRes, "Unexpected result: user "
+ + MerlinConstants.DIFFERENT_USER_GROUP + " was not able to perform: " + op);
+ }
+ //check that different user can access the feed
+ KerberosHelper.loginFromKeytab(MerlinConstants.DIFFERENT_USER_NAME);
+ for(EntityOp op : new EntityOp[]{EntityOp.status, EntityOp.dependency, EntityOp.listing,
+ EntityOp.definition}) {
+ final boolean executeRes =
+ op.executeAs(MerlinConstants.DIFFERENT_USER_NAME, feedHelper, newFeed);
+ Assert.assertTrue(executeRes, "Unexpected result: user "
+ + MerlinConstants.DIFFERENT_USER_GROUP + " was not able to perform: " + op);
+ }
+ //check modification permissions
+ AssertUtil.assertSucceeded(feedHelper.update(newFeed, oldFeed,
+ MerlinConstants.DIFFERENT_USER_NAME));
+ }
+
@AfterMethod(alwaysRun = true)
public void tearDown() {
KerberosHelper.loginFromKeytab(MerlinConstants.CURRENT_USER_NAME);
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/8fc5ff61/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/ProcessAclTest.java
----------------------------------------------------------------------
diff --git a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/ProcessAclTest.java b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/ProcessAclTest.java
index f0775e7..bc79835 100644
--- a/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/ProcessAclTest.java
+++ b/falcon-regression/merlin/src/test/java/org/apache/falcon/regression/security/ProcessAclTest.java
@@ -24,6 +24,7 @@ import org.apache.falcon.regression.core.bundle.Bundle;
import org.apache.falcon.regression.core.enumsAndConstants.MerlinConstants;
import org.apache.falcon.regression.core.helpers.ColoHelper;
import org.apache.falcon.regression.core.interfaces.IEntityManagerHelper;
+import org.apache.falcon.regression.core.util.AssertUtil;
import org.apache.falcon.regression.core.util.BundleUtil;
import org.apache.falcon.regression.core.util.HadoopUtil;
import org.apache.falcon.regression.core.util.KerberosHelper;
@@ -88,7 +89,7 @@ public class ProcessAclTest extends BaseTestClass {
bundles[0].submitProcess(true);
final boolean executeRes = op.executeAs(user, processHelper, processString);
Assert.assertEquals(executeRes, isAllowed, "Unexpected result user " + user +
- " performing: " + op);
+ " performing: " + op);
}
@DataProvider(name = "generateUserReadOpsPermissions")
@@ -96,14 +97,15 @@ public class ProcessAclTest extends BaseTestClass {
final EntityOp[] falconReadOps = {EntityOp.status, EntityOp.dependency,
EntityOp.listing, EntityOp.definition};
final Object[][] allowedCombinations = MathUtil.crossProduct(
- new String[]{MerlinConstants.FALCON_SUPER_USER_NAME, MerlinConstants.FALCON_SUPER_USER2_NAME,
- MerlinConstants.USER2_NAME},
+ new String[]{MerlinConstants.FALCON_SUPER_USER_NAME,
+ MerlinConstants.FALCON_SUPER_USER2_NAME,
+ MerlinConstants.USER2_NAME},
falconReadOps,
new Boolean[]{true}
);
final Object[][] notAllowedCombinations = MathUtil.crossProduct(
- new String[]{MerlinConstants.DIFFERENT_USER},
+ new String[]{MerlinConstants.DIFFERENT_USER_NAME},
falconReadOps,
new Boolean[]{false}
);
@@ -145,9 +147,9 @@ public class ProcessAclTest extends BaseTestClass {
);
final Object[][] notAllowedCombinations = MathUtil.crossProduct(
- new String[]{MerlinConstants.DIFFERENT_USER},
- falconEditOps,
- new Boolean[]{false}
+ new String[]{MerlinConstants.DIFFERENT_USER_NAME},
+ falconEditOps,
+ new Boolean[]{false}
);
return MathUtil.append(allowedCombinations, notAllowedCombinations);
@@ -187,7 +189,7 @@ public class ProcessAclTest extends BaseTestClass {
);
final Object[][] notAllowedCombinations = MathUtil.crossProduct(
- new String[]{MerlinConstants.DIFFERENT_USER},
+ new String[]{MerlinConstants.DIFFERENT_USER_NAME},
new EntityOp[]{EntityOp.delete, EntityOp.update, EntityOp.schedule,
EntityOp.submitAndSchedule, EntityOp.suspend, EntityOp.resume},
new Boolean[]{false}
@@ -196,6 +198,42 @@ public class ProcessAclTest extends BaseTestClass {
return MathUtil.append(allowedCombinations, notAllowedCombinations);
}
+ /**
+ * Test process acl modification.
+ * @throws Exception
+ */
+ @Test
+ public void processAclUpdate() throws Exception {
+ bundles[0].submitFeedsScheduleProcess();
+ final String oldProcess = bundles[0].getProcessData();
+ AssertUtil.assertSucceeded(prism.getProcessHelper().submitAndSchedule(oldProcess));
+ final ProcessMerlin processMerlin = new ProcessMerlin(oldProcess);
+ processMerlin.setACL(MerlinConstants.DIFFERENT_USER_NAME,
+ MerlinConstants.DIFFERENT_USER_GROUP, "*");
+ final String newProcess = processMerlin.toString();
+ AssertUtil.assertSucceeded(processHelper.update(oldProcess, newProcess));
+ //check that current user can't access the feed
+ for(EntityOp op : new EntityOp[]{EntityOp.status, EntityOp.dependency, EntityOp.listing,
+ EntityOp.definition}) {
+ final boolean executeRes =
+ op.executeAs(MerlinConstants.DIFFERENT_USER_NAME, processHelper, newProcess);
+ Assert.assertFalse(executeRes, "Unexpected result: user "
+ + MerlinConstants.DIFFERENT_USER_GROUP + " was not able to perform: " + op);
+ }
+ //check that different user can access the feed
+ KerberosHelper.loginFromKeytab(MerlinConstants.DIFFERENT_USER_NAME);
+ for(EntityOp op : new EntityOp[]{EntityOp.status, EntityOp.dependency, EntityOp.listing,
+ EntityOp.definition}) {
+ final boolean executeRes =
+ op.executeAs(MerlinConstants.DIFFERENT_USER_NAME, processHelper, newProcess);
+ Assert.assertTrue(executeRes, "Unexpected result: user "
+ + MerlinConstants.DIFFERENT_USER_GROUP + " was not able to perform: " + op);
+ }
+ //check modification permissions
+ AssertUtil.assertSucceeded(processHelper.update(newProcess, oldProcess,
+ MerlinConstants.DIFFERENT_USER_NAME));
+ }
+
@AfterMethod(alwaysRun = true)
public void tearDown() {
KerberosHelper.loginFromKeytab(MerlinConstants.CURRENT_USER_NAME);
http://git-wip-us.apache.org/repos/asf/incubator-falcon/blob/8fc5ff61/falcon-regression/pom.xml
----------------------------------------------------------------------
diff --git a/falcon-regression/pom.xml b/falcon-regression/pom.xml
index 0424cb8..1179843 100644
--- a/falcon-regression/pom.xml
+++ b/falcon-regression/pom.xml
@@ -220,6 +220,11 @@
<artifactId>selenium-support</artifactId>
<version>2.41.0</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-exec</artifactId>
+ <version>1.2</version>
+ </dependency>
</dependencies>
</dependencyManagement>